GIT - 删除旧的 reflog 条目

16

经过反复地将存储库重新定义以适应我们的最新需求,我们的reflog中充满了提交和孤立分支。我们已经达到了重组的最终状态。

虽然仍有许多带有二进制数据的分支和提交,但存储库的大小已经增长了数倍,因此我们决定清除所有旧的reflog条目和数据。

我在手册中寻找答案,但使用git-reflog expire进行实验后并没有更聪明。

这是日志的一个示例(缩短了)

-> <sha1> [development] ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
-> <sha1> [master] ...
-> <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
-> <sha1-old> ...

如下所示,主分支下面有旧的提交和分支,记录了重组前的存储库。

我们希望清除reflog以使存储库看起来像:

-> <sha1> [development] ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
-> <sha1> [master] ...

为了减少仓库所使用的磁盘空间,我们希望采取措施。我该如何实现这一目标?

编辑(2019年3月2日12:20)

请不要提到删除和重新克隆存储库。这不是我要找的。


编辑(2019年3月2日12:30)

我尝试过的,但没有成功的方法

git reflog expire --expire=all

什么都没有发生,所以我试图聪明地调用垃圾收集器

git gc --aggressive

但是虚假的。


可能是如何从我的git仓库中删除未引用的blob的重复问题。 - max630
1个回答

44

你需要特别使用--expire-unreachable选项:

git reflog expire --expire=90.days.ago --expire-unreachable=now --all
例如。

有什么区别?

reflog 是一个记录引用的日志(因此得名“reflog” :-))。引用ref是以refs/开头的名称,例如refs/heads/master,这就是分支名称master实际存储的方式。还有一个额外的reflog,用于HEAD本身,它(由于不以refs/开头)在我在git词汇表中链接的定义中从技术上讲不是引用,但是,词汇表的定义接着说有一些特殊的引用并不以refs/开头,所以可能他们混淆了,也可能是我混淆了。:-)

无论如何,引用的目的是存储哈希值(或者对于特殊的HEAD引用,存储另一个引用的名称)。 哈希ID是一个值。 你可以更新引用,从而更改存储的值 - 因此随着时间的推移,单个名称会采用多个不同的值。 有一个当前master,然后是更改一次之前的值,master@{1},以及更改两次之前的值master@{2},等等(为了一致性,您可以将当前值拼写为master@{0})。所有这些都在gitrevisions文档中详细说明。

reflog是Git存储先前值的地方。 reflog不仅存储先前的值,还存储计算机更改该值时的时钟时间,因此Git可以处理诸如master@{3.days.ago}这样的语法,以找到表示三天前master具有的值的任何条目,为master@{0}master@{1}master@{2}等等。 (“三天”意味着3个24小时的日子:72个小时,没有分钟,没有秒,或者精确地说是259200秒前。如果您昨天多次更改了master,您可能需要比master@{yesterday}更精确。)

所以,假设master当前值为1234567...(一些很长和难看的哈希ID),而master@{1}8888888...master@{2}3333333...。到目前为止,它们似乎都很相似。但它们不一定是这样:

          1234567   <-- master
            /
...--o--8888888   [master@{1}]
      \
    3333333   [master@{2}]

这里master@{1}master@{2}的区别,除了它们的值和花括号{}中的数字之外 ——对于git reflog expire来说,重要的区别是我们可以通过从master (1234567) 开始往回追溯来找到master@{1}。如果我们从master开始往前追溯一个提交,我们就会到达master@{1}。如果我们再往前一步,我们就会到达枯燥的提交o,我们甚至不知道其编号;我们直接跳过了提交3333333

具体来说,在这种情况下,master@{2}无法从当前(1234567)的master值访问。因此,它的到期时间由--expire-unreachable参数控制,而不是由--expire参数控制。

如果您没有选择特定的值,git reflog将使用配置的默认值(如果已配置)。在没有配置默认值的情况下,可到达记录的默认保留时间为90天,不可到达记录的默认保留时间为30天。所以:

--expire=90.days.ago --expire-unreachable=30.days.ago

如果您没有更改自己的默认设置,则为默认设置。 如果您在命令行上覆盖一个默认设置,则不会更改另一个默认设置。

重新定义会生成很多不可访问的提交记录

您的问题涉及一个重要的问题:您进行了大量的重新定义操作。重新定义的工作原理是通过复制提交记录,然后切换分支名称以使用新的(并且预计改进的)提交记录。旧的提交记录仍然存在,但无法从新的分支尖端到达:

          A'-B'-C'  <-- branch
         /
...--o--o
         \
          A--B--C   [branch@{1}]

其中A--B--C是原始链(旧不堪的提交),A'-B'-C'是您想要的全新副本。由于连接始终向后,即使它们从其他引用可访问,旧的提交也始终无法从新的分支末端访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接