从远程删除未引用的对象

Removing unreferenced objects from remote

我想知道远程 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 中的那个文件对象,因为它现在不属于任何 commit/tree?如果没有,我该怎么做?

GitHub 可能会也可能不会删除无法访问的提交并在未来某个时间归档。这取决于他们。

一个正常的日常 Git 存储库——例如你控制的存储库——通常会在 git gc 运行 时完全删除未引用的提交。不过,要做到这一点,首先必须删除 all 引用。使用 git rebase 故意留下几个引用:

  • HEAD reflog 中有一个条目(可通过 git reflog 查看)。
  • 分支 reflog 中有一个条目(可通过 git reflog <em>branch</em> 查看)。
  • ORIG_HEAD 中有引用。

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

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

使用 GitHub 的主要问题是您不知道 他们 什么时候会擦除他们最后的引用,也不知道他们什么时候会随后 运行 将丢弃对象的 git gcplus,它们为拉取请求、问题和其他项目添加特殊引用,可以使对象无限期地保持活动状态。所有这一切的结果是,您无法预测某些文件何时甚至是否会从 GitHub 中消失。

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