从远程删除未引用的对象

问题描述

我想知道远程 git 存储库是否会(或应该)在收到来自本地的 push自动删除未引用的文件对象(以及树)一些引入这些文件的提交,这些提交也删除了这些文件。由于这些跳过的提交不再在提交的历史链中,因此远程删除这些对象是合乎逻辑的,因为它们现在不是历史中任何提交的一部分。这张图可以解释:

这是rebase --onto之前的历史

 * b5b7c142 after-deleting offending-file
 * db759b06 deleted offending-file
 * 59a9440a added offending-file
 * 933729b1 before-adding-offending-file

在我后悔之前被推到了遥控器。但是这里是尝试修复它...

rebase --onto 933729b1 db759b06

有效地重建提交 b5b7c142 after-deleting offending-file

拥有不同的父级:933729b1 before-adding-offending-file 并忽略中间的两个提交。

这是上面rebase之后的样子:(请注意第一次提交SHA1因为我们改变了父级而改变)

* 17c95f49 after-deleting offending-file
| * db759b06 deleted offending-file
| * 59a9440a added offending-file
| /
* 933729b1 before-adding-offending-file

而且它在本地寻找历史记录并且该文件对象仍然存在于 .git/objects 中,它是一些仍然存在的提交的一部分。现在如果我现在推到遥控器会发生什么?它会删除 github 上 .git/objects 中的那个文件对象,因为它现在不是任何提交/树的一部分吗?如果没有,我该怎么做?

解决方法

GitHub 可能会或可能不会在未来某个时间删除无法访问的提交和文件。这取决于他们。

一个普通的日常 Git 存储库(例如,您控制的存储库)通常会在 git gc 运行时完全删除未引用的提交。但是,要做到这一点,首先所有 引用必须消失。故意使用 git rebase 会留下几个引用:

  • HEAD 引用日志中有一个条目(可使用 git reflog 查看)。
  • 分支引用日志中有一个条目(可使用 git reflog branch 查看)。
  • ORIG_HEAD 中有引用。

最后一个将被保存在 HEAD 中的前一个 ORIG_HEAD 值的下一个操作覆盖。由于 reflog 条目过期,其他两个最终将被删除。每个 reflog 条目都带有时间戳,并且在 current 时间超过添加到条目时间戳的过期时间之前一直处于“活动状态”。 git gc 的另一个功能是检查过期的条目,它将删除这些条目。过期时间由您控制,默认为 30 天和 90 天。这部分令人困惑(怎么可能是两者?)但与 GitHub 变体并没有真正相关,因为它们不使用这样的引用日志:关键是引用必须真正消失,这需要时间,这部分对于 GitHub 也是如此。

一旦引用真的消失了git gc 将丢弃保存不需要的提交和文件的内部对象,假设它们不在保存的包。保留包是你必须自己创建的东西——Git 本身不会这样做——所以如果你不这样做,你个人就不会遇到这种情况。

您在 GitHub 上遇到的主要问题是您不知道 他们 何时会清理他们的最后一个引用,也不知道他们随后何时会运行 git gc 来丢弃object——加上,他们为拉取请求、问题和其他项目添加了特殊的引用,这可以使对象无限期地保持活动状态。所有这一切的结果是,您无法预测某个文件何时甚至是否会从 GitHub 中消失。

请注意,您可以联系 GitHub 支持并让他们进行手动清理。当然,到那时,任何数量的人都可以得到这个文件,所以如果里面有任何敏感数据,现在就认为它是黑帽黑客社区所熟知的。