重置分支后,git提交会被删除吗?

时间:2019-02-21 04:05:20

标签: git

比方说,我只有master分支,并且进行了一些提交:提交1、2和3。

如果我执行git reset --hard提交2,则继续推送并继续提交代码。提交3会永远保留在git数据库中还是最终将被删除?

2 个答案:

答案 0 :(得分:2)

他们将继续存在。您可以致电git gc进行清理。要找到它们,例如,可以使用git refloggit fsck

AFAIK,要在GitHub上将其删除,您必须联系支持部门(see this)。

答案 1 :(得分:2)

它们存活到git gcWofWca said一样被清理干净,但是恰好在这种情况下难以确定。

某些命令会自动为您运行git gc --auto。如今,包括git commit在内:git commit总是应该运行此命令,但是代码在早期版本的Git(Git 1.5.4)中被意外删除,并且直到2.17才恢复。但是,如果git gc --auto在其评估中尚无理由运行,则无济于事,并且大多数情况下它都在运行。 1 然后,当git gc决定运行应该运行,或者当您运行git gc而没有--auto自己运行refs/heads/时立即运行它,即使那样可能也不会删除这些提交

什么使提交有效?好吧,答案很复杂:

  1. 每个引用(分支名称是其全名以refs/stash开头的引用)可能具有 reflog 。 reflog存储 reflog条目,它们是带有时间戳的记录,实际上,该引用在日期 D 设置为哈希ID H 。这允许Git在特定时间恢复分支(或任何其他引用)的状态(以绝对或相对术语指定),只要该时间附近的reflog条目尚未到期即可。

    这些reflog条目 do 到期,但是gc.reflogExpire除外,默认情况下gc.reflogExpireUnreachable的reflog条目永不过期。 Git删除所有过期的条目,仅将未过期的条目保留在日志中。每个条目的有效期限是可配置的。默认值为30天或90天,由refs/heads/mastermaster@{1}设置。哪一个适用?好吧,这很棘手:这取决于 reachability 的概念。要全面了解可达性的含义,请参见Think Like (a) Git

    在这种特殊情况下,我们对从引用本身中存储的哈希ID是否可访问在reflog条目中存储的哈希ID感兴趣。也就是说,给定类似master的名称,我们检查master来确定它是否是master本身的祖先。如果是这样,则该引用日志条目 是可访问的(从当前gc.reflogExpire开始)。如果不是,则无法从当前gc.<pattern>.reflogExpire访问该reflog条目。依次选择两个gc.<pattern>.reflogExpireUnreachble变量中的哪个。 (当然,如果分支具有通过.gitattributes和/或git reset进行的自定义设置,则使用该设置。文档将其称为 pattern ,并且似乎使用了文件名模式匹配代码,例如与HEAD相同。)

    选择了一个到期变量后,Git然后将reflog的时间戳与隐含的到期日期进行比较。如果reflog条目已过期,则将其删除。

    如果reflog条目保留,它将保护reflog包含其哈希ID的对象,从该对象可访问的所有对象。对于提交对象,这意味着提交本身受到保护,其所有祖先及其快照也受到保护。

    它的简短版本是默认情况下,reflog条目至少保留30天。作为当前分支提示祖先的Reflog条目将保留至少90天。在这种gc.pruneExpire之后,该条目不是分支提示的祖先,因此适用30天规则。

  2. 如果第1步未直接保留内部对象,则git gc --auto本身也会有一个reflog,它可能会直接保留该对象。当然,通过可达性规则,这两种方法都可以间接保存对象

  3. 如果第1步和第2步都没有直接或间接保存该对象,则可能仍未删除该对象:所有对象具有宽限期,默认为14天,并且可以配置为git commit。此宽限期可防止在后台运行的git write-tree删除由某个活动Git命令创建的对象。例如,git write-tree可能正在运行git write-tree,而git commit正在根据索引内容忙于分解树对象。 git commit-tree完成后,git commit运行git commit来创建提交对象本身。

    所有这些都内置于git commit中,但是它们仍然创建了松散的对象,而从 any 引用至今都无法访问这些对象,因此所有这些将有资格进行垃圾收集。但是14天的宽限期意味着git commit现在已经写出了一些树对象和新的提交对象,可以通过使分支名称指向提交并将引用日志条目添加到分支的完成来完成提交。刷新日志。只要git gc --auto能够在两周内完成所有这些工作,Git就可以了。如果您的计算机太慢而无法在两周内完成objects/17,那么,这在很多方面都非常糟糕。

因此,这为您提供了保留或不保留提交的一组规则。最重要的是,请记住,存储库(存储在服务器上)通常禁用了reflog,并且很少处理松散的对象-到达服务器的对象通常作为引入瘦包,服务器会“瘦”起来,然后无论如何通常会很快重新打包。因此,服务器倾向于比普通的非裸存储库更快地对其对象进行GC。


1 要确定是否该做某事,pre-auto-gc执行以下步骤:

  1. 计算 pack 个文件的数量,不包括标记为“ keep”的文件。如果超过阈值,那么该是进行包含重新包装的gc的时候了。

  2. 如果没有执行步骤1,请计算gc.autopacklimit目录中松散对象的数量。 (这里的17是一个任意选择,并且经过硬编码。您必须问Linus或为什么17。更明显的选择是42,或者2a,因为它们是十六进制的。:-))如果超出阈值,则为需要时间来构建一个新的gc。

  3. 如果第1步或第2步均未触发,请不要执行GC。否则,请运行gc.auto挂钩,使其有机会中止GC。如果该钩子不存在,或者以成功状态(即零)退出,则继续执行GC。

步骤1和2中的两个阈值由git config(默认值为50)和gc.auto(默认值为6700)控制。您可以使用{{1}配置这两个阈值之一或全部}。如果将gc.autopacklimit设置为零或负数,则无论将gc.autopacklimit设置为什么,都会禁止两种类型的auto-gc。

您在.git/objects/17中配置的数字被256除以小数部分后舍入,因此默认值6700产生27(6700/256为26.171875)。除以256的原因是,根据对象哈希ID的前两个十六进制字符,这些松散的对象分散在256个子目录中。假设哈希分布是统一的,因此,如果.git/objects/XX中有26个对象,则其他255个17/目录中的每个对象中也可能大约有26个对象,因此大约26 x 256 = 6656个松散物体。如果{{1}}中有27个松散对象,则可能大约有27 x 256 = 6912个松散对象。通过计算一个子目录来估计数量比通过计算所有子目录来计算实际数量要快。像往常一样,在这种情况下,Git会尽其所能地做快速的事情。