11

在根据我们的最新需求对存储库进行了大量重新定位之后,我们的 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-03-02 12:20)

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


编辑(2019-03-02 12:30)

到目前为止我尝试过的但没有奏效的

git reflog expire --expire=all

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

git gc --aggressive

但假的。

4

1 回答 1

34

具体来说,您需要以下--expire-unreachable选项:

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

例如。

有什么不同?

reflog是用于参考的日志(因此名称为“reflog”:-))。引用ref是以 开头的名称,refs/例如refs/heads/master,这是分支名称master的实际存储方式。有一个额外的 reflogHEAD本身,它(因为它不是以 开头refs/)在技术上不是我在gitglossary中链接的定义的参考,但是,词汇表定义继续说有一些特殊的参考不要以 开头refs/,所以要么他们感到困惑,要么我很困惑。:-)

无论如何,引用的意义在于存储哈希 ID(或者在特殊HEAD引用的情况下,存储另一个引用的名称)。哈希 ID 是一个值。您可以更新引用,这会更改存储的值——因此,随着时间的推移,单个名称会采用多个不同的值。有当前master,然后有一个从一个变化前的,master@{1},从两个变化前的,master@{2},等等。(为了保持一致性,您可以根据需要拼写当前值master@{0}。)这在gitrevisions 文档中都有详细说明。

reflog是 Git 保存先前值的地方。reflog 不仅存储了之前的值,还存储了值更改时计算机的时钟时间——因此 Git 可以处理语法,例如查找代表三天前的值的任何条目或其他内容。(“三天”是指 3 个 24 小时日:72 小时,没有分,也没有秒前,或者正好是 259200 秒前。如果你昨天改变了几次,你可能需要比仅仅更精确。)master@{3.days.ago}master@{0}master@{1}master@{2}mastermastermaster@{yesterday}

无论如何,所以,假设当前值为masteris 1234567...(一些大而丑陋的哈希 ID),master@{1}8888888...while master@{2}is 3333333...。到目前为止,它们看起来都很相似。但它们不一定是这样:

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

master@{1}这里和之间的区别master@{2}——嗯,除了它们的值和花括号内的数字{}——重要的区别git reflog expire在于我们可以 master@{1}( master)开始1234567并向后工作。如果我们从一个提交开始master并返回一个提交,我们会来到master@{1}. 如果我们再往前走一步,我们会到达无聊的提交o,我们甚至不知道其编号;我们直接跳过 commit 3333333

具体来说,在这种情况下,从 的当前 ( ) 值master@{2}无法达到。所以它的到期是由论点控制的,而不是由论点控制的。1234567master--expire-unreachable--expire

如果您不选择特定值,git reflog将使用配置的默认值,如果您已配置一个。在没有配置默认值的情况下,可访问条目的默认默认值为 90 天,不可访问条目的默认默认值为 30 天。所以:

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

是默认值,除非您更改了自己的默认值。如果您在命令行上覆盖了一个默认值,那么您将保留另一个默认值。

Rebase 使很多无法访问

你的问题从一个重要的点开始:你做了很多变基。Rebase 通过复制提交来工作,然后切换分支名称以使用新的(并且可能是改进的)提交。旧的仍然存在,并且总是无法从新的分支提示中访问:

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

A--B--C原始链(旧的和 icky 的提交)在哪里,并且A'-B'-C'是您想要的闪亮的新副本。由于连接总是向后移动,旧的连接总是无法从新的分支提示中访问,即使它们可以从其他一些引用中访问。

于 2018-03-02T16:22:47.290 回答