什么时候git修剪对象:为什么" git gc"不删除提交?

时间:2016-06-09 18:01:15

标签: git git-gc

我正在开设一个git课程并想提一下,在运行git gc之前,丢失的参考文件并没有真正丢失。但验证这一点,我发现事实并非如此。即使在运行git gc --prune=all --aggressive之后,丢失的裁判仍在那里。

显然我误解了一些事情。在说出不正确的课程之前,我想直截了当地了解事实!这是一个示例脚本说明效果:

 #!/bin/bash

 git init

 # add 10 dummy commits
 for i in {1..10}; do
     date > foo.txt
     git add foo.txt
     git commit -m "bump" foo.txt
     sleep 1
 done;

 CURRENT=$(git rev-parse HEAD)
 echo HEAD before reset: ${CURRENT}

 # rewind
 git reset --hard HEAD~5

 # add another 10 commits
 for i in {1..10}; do
     date > foo.txt
     git add foo.txt
     git commit -m "bump" foo.txt
     sleep 1
 done;

此脚本将添加10个虚拟提交,重置为过去的5个提交,并添加另外10个提交。在重置之前,它将打印它当前HEAD的哈希值。

运行CURRENT后,我期望git gc --prune=all中丢失对象。但是,我仍然可以在该哈希上运行git show

我明白在运行git reset并添加新提交后,我基本上创建了一个新分支。但我的原始分支不再有任何引用,因此它不会显示在git log --all中。它也不会被推到我想的任何遥控器上。

我对git gc的理解是删除了这些对象。情况似乎并非如此。

为什么呢? 确实git gc删除对象时

1 个答案:

答案 0 :(得分:15)

对于要修剪的对象,它必须符合两个条件。一个是与日期/时间相关的:它必须在足够长的时间之前创建 1 以便收集成熟。 “足够久以前”部分是您使用--prune=all设置的部分:您将覆盖正常的“至少两周”设置。

第二个标准是您的实验出错的地方。要进行修剪,该对象必须 无法访问。作为twalberg noted in a comment,您通过Git的“reflog”条目实际引用了每个表面上被放弃的提交(以及它们对应的树和blob)。

每个此类提交有两个reflog条目:一个用于HEAD,另一个用于HEAD在提交时自己引用的分支名称(在本例中为reflog)对于refs/heads/master,即分支master)。每个reflog条目都有自己的时间戳,git gc也会为你过期reflog条目,尽管有一套更复杂的规则,而不是对象到期的简单“14天”默认值。 2

因此,git gc 可以首先删除所有保留旧对象的reflog条目,然后修剪对象。这不会发生在这里。

要手动查看甚至删除reflog条目,请使用git reflog。请注意,git reflog 通过使用git log / -g选项运行--walk-reflogs来显示条目(以及一些其他显示格式选项)。您可以运行git reflog --all --expire=all来清除所有内容,但是当手术刀可能更合适时,这是一个大棒。使用--expire-unreachable可获得更多选择性。有关详情,请参阅the git log documentation,当然还有the git reflog documentation

1 有些Unix-y文件系统根本不存储文件创建(“出生”)时间:st_ctime结构的stat字段是 inode更改时间,而不是创建时间。如果有创建时间,则它在st_birthtimest_birthtimespec 3 但是,每个Git对象都是只读的,因此文件的创建时间也是其修改时间。因此, 始终可用的st_mtime为对象提供了创建时间。

2 the git gc documentation中描述了确切的规则,但我认为默认情况下,无法访问提交30天,可访问提交90天是一个不错的选择摘要。这里 reachable 的定义是不寻常的:它意味着可以从引用的当前值到达,此reflog包含旧值。也就是说,如果我们正在寻找在master的reflog中,我们找到master标识的提交(例如,1234567),然后查看master的每个reflog条目(例如master@{27}可以从该特定提交(<{em>}再次发送。)

3 这个特殊的名称混淆是由POSIX标准化人员提出的。 :-) 1234567字段是st_birthtimespec,它记录秒和纳秒。