使用 BFG 清理 repo 后“无法推送一些引用”错误

问题描述

我有一个正在尝试缩小的 GitHub 存储库。我已使用 BFG repo cleaner 来执行此操作,然后是典型的 gc 命令。这确实减少了我的存储库大小(尽管它仍然比应有的大 3 倍 - 但这是另一点)。

bfg -B 100 #delete the 100 biggest blobs
git reflog expire --expire=Now --all
git gc --prune=Now --aggressive

在此之前,我的 repo 与 origin master 保持同步。当我在执行这一系列清理命令后 git addcommit 时,我被告知 nothing to commit,working tree clean。但是,当我 git push 时,出现以下错误

error: Failed to push some refs to 'https://github.com/REPONAME'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g.,'git pull ...') before pushing again.

git fetch 后跟 git merge 修复了这个错误,但是我上面所做的所有大小减小都被取消了,有时甚至使存储库的大小加倍。我如何避免这种情况?

解决方法

任何在存储库中“修改提交”的命令(包括 BFG、git filter-branchgit filter-repo)实际上都是通过复制提交来工作的。提取出有问题的旧提交。检查每个旧提交以查看应该更正的内容。如果没问题,程序可以不理会它,否则,将应用任何必要的更改(例如删除大文件,或更改父链接以指向较早更改的提交),并且程序会执行新的和改进的提交,用于而不是原始提交。

过程完成后,一些(可能和所有的一样多,但在您的情况下只有一些)提交已被复制到新的和改进的提交中。您的任务现在变得说服此存储库的每个其他克隆使用您新的和改进的提交而不是他们当前的提交。

Git 不是为此而构建的。 Git 更喜欢在现有提交之上添加新提交。例如,这就是 fetch-and-merge 所做的。如果新的和改进的提交几乎是每次提交,这个过程大约会使存储库的大小增加一倍,因为我们现在拥有所有旧提交加上所有新的和改进的提交。 >

当你运行 git push 并得到你看到的错误时,这是​​另一个 Git 说的,实际上:如果我接受你发送的内容并按照你的要求做,我将失去所有这些伟大的承诺。你先把所有这些添加到你的存储库,然后让我将你的添加到我的存储库中而不丢失我的任何一个?

当然,您希望他们丢失所有提交。他们的提交是你想要替换的旧的和糟糕的提交。1所以你需要覆盖这个错误。 Git 有办法做到这一点,使用 git push --force。另一方面,GitHub 具有一些附加值功能,如果您愿意,可能会使此失败。因此,如果您遇到 GitHub 阻止您,您至少必须暂时关闭添加的功能,以便您可以销毁 GitHub 上的提交。2

无论如何,一旦你说服 GitHub 上的 Git 放弃旧的和糟糕的提交,而支持新的和改进的提交,你就大功告成了;但请参阅脚注,并记住:也许其他(第三方)人拥有您 GitHub 克隆的克隆。你也需要说服他们更新。


1请注意,如果某些第三方可能会向您的 GitHub 存储库添加提交,他们可能会在您克隆并运行 The BFG 或其他任何内容后添加了一些,这样你就不会真正复制所有提交。为了防止这种情况发生,在开始整个过程​​之前,请确保您是唯一可以推送到 GitHub 存储库的人,至少是暂时的。

2它们通常不会马上消失,当你错误地这样做时这很好,而当你故意这样做时则很糟糕。他们坚持多久是很难预测的:要真正把他们现在扔掉,你需要让 GitHub 的人参与进来。如果您不介意他们在 GitHub 上闲逛,占用 GitHub 的磁盘空间而不是您的磁盘空间,则无需担心。