14

我正在学习 git 课程,想提一下丢失的 refs 直到 running 才真正丢失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删除对象?

4

1 回答 1

21

对于要修剪的对象,它必须满足两个标准。一个是日期/时间相关的:它必须是在足够长的时间之前创建的,以便收集成熟。“很久以前”部分是您设置的内容--prune=all:您正在覆盖正常的“至少两周大”设置。

第二个标准是你的实验出错的地方。要被修剪,对象必须是unreachable。正如twalberg 在评论中指出的那样,您的每个表面上被放弃的提交(以及它们相应的树和 blob)实际上都是通过 Git 的“reflog”条目引用的。

每个这样的提交都有两个 reflog 条目:一个用于HEAD,另一个用于在HEAD提交时它自己引用的分支名称(在本例中,用于 的 reflog refs/heads/master,即 branch master)。每个 reflog 条目都有自己的时间戳,并且git gc还会为您过期 reflog 条目,尽管与对象过期的简单“14 天”默认值相比,它有一组更复杂的规则。2

因此,git gc 可以先删除所有保留旧对象的 reflog 条目,然后修剪该对象。它只是没有在这里发生。

要手动查看甚至删除 reflog 条目,请使用git reflog. 请注意,通过使用/选项(加上一些额外的显示格式选项)运行来git reflog 显示条目。你可以跑去清除所有东西,尽管当手术刀可能更合适时,这是一个大棒。用于更多的选择性。有关这方面的更多信息,请参阅文档当然还有文档git log-g--walk-reflogsgit reflog --all --expire=all--expire-unreachablegit loggit reflog


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

2文档中描述git gc确切的规则,但我认为默认情况下,30 天无法访问的提交和 90 天的可访问提交是一个不错的总结。但是,这里的可达性定义是不寻常的:它意味着可以从这个 reflog 保存旧值的引用的当前值到达。 也就是说,如果我们正在查看 的 reflog master,我们会找到master标识(例如,1234567)的提交,然后查看(例如,)的每个 reflog 条目master是否master@{27}可以从该特定提交1234567再次)访问。

3 POSIX 标准化人员给您带来了这种特殊的名称混淆。:-) 该st_birthtimespec字段是 a struct timespec,它记录秒和纳秒。

于 2016-06-09T19:08:19.607 回答