在 BFG(历史编辑)之后复制所有提交

ALL commits are duplicated after BFG (history editing)

我不知道使用 BFG 删除 big/sensitive 文件的干净方法,并且错过了关键步骤: git clone --mirror git://example.com/some-big-repo.git

其中,当我尝试推送到远程时,导致历史冲突,我天真地解决了 git pull origin master --allow-unrelated-histories,合并了一些冲突,然后推送。

这会重复提交,有时会重复 5-10 次。

因为我一个人在处理这个 repo,我既没有选择将它清理到地面并从更合理的副本重新启动,也不必担心不同的提交是不同的,我相信他们完全相同。

是否有暴力破解命令来清除除了散列之外在所有方面都相同的所有提交?

Is there a brute-force command to erase all commits that are identical in all aspects but the hashes?

没有。但是,您可以放弃合并提交,这是将旧历史和新历史联系在一起的原因。那不会删除旧历史,但您可以停止使用它。最终,如果您的 Git 找不到它,它就会消失。

您需要做的是 运行 git reset --hard 在您自己的存储库上(丢弃一次合并提交),然后使用 git push -f 将所有内容发送到 origin 并让 他们 移动 他们的 master.


两个不同的提交哈希 ID 是两个不同的提交,不可能更改任何提交的任何内容。这就是为什么 BFG(和 Git 自己的 git filter-branch复制 所有提交:他们确实 不能改变旧的。这就是您获得所有内容的两份副本的方式。

首先,您制作了新的副本并抛弃了旧的以支持新的。这就是 BFG 所做的。 (这不完全是 git filter-branch 所做的:它不会扔掉旧的,它只是把它们推到一边,然后让 you 扔掉它们。)

到目前为止一切顺利。但是然后你 运行 git fetch 拿起所有旧的提交,然后 git merge 选择: 现在将旧的和新的粉碎在一起,即使它们互无关系.

如果您的新旧提交历史非常简单,我们可以这样绘制它们:

A--B--...--H   <-- origin/master

A'-B'-...--H'  <-- master

(大写字母代表提交哈希值,而主要标记,例如 A' 而不是 A,表示这些是已更改内容的副本,这就是为什么他们有不同的哈希值。)大概你的历史 - 你的提交 - 更复杂,但这种表示仍然足够:有一个原始的端点提交,例如 H,和一个新的端点提交 H', 参与.

你卡在最后的合并是这样的:

A--B--...--H    <-- origin/master
            \
             M   <-- master
            /
A'-B'-...--H'

(其中 M 的第一个父项是 H'M 的第二个父项是 H)。你自己的Git里的名字origin/master是你自己Git对origin的Git口口声声的记忆,我的master: 他们仍然记得提交 H 作为他们的 master.

如果您从自己的 b运行ch master 的顶端删除 提交 M,您将在您自己的存储库:

A--B--...--H    <-- origin/master
            \
             M   [abandoned]
            /
A'-B'-...--H'   <-- master

提交 M 仍然 存在 但您不能再 看到它 :没有简单的方法可以找到它。找到它的不容易的方法将使它至少再保留 30 天,以防你决定要回它,但最终,它们会让它消失并真正消失。

现在你可以运行:

git push --force origin master

让你的Git调用origin的Git,确保他们有所有重写的提交(A'-...-H'),然后给他们发一个形式的强制命令:是的,这使您无法访问提交 H,但将您的 master 设置为指向提交 H' 他们通常会服从这个命令——如果他们不服从,你必须找出 为什么 他们不服从(例如,GitHub 的 "protected branch" 功能)并修复 首先——然后 他们 将有:

A--B--...--H   [abandoned]

A'-B'-...--H'  <-- master

(假设您从未发送给他们 M——如果您发送了,他们也会收到,但同样会被放弃)。你的 Git 会看到他们遵守了这个命令,并将更新 你的 origin/master 来反映它:

A--B--...--H   [abandoned]
            \
             M   [abandoned]
            /
A'-B'-...--H'   <-- master, origin/master

当足够的时间到期时——对于裸服务器存储库(例如,GitHub 上的存储库)通常要短得多,但在你自己的存储库中超过 30 天——废弃的提交将与垃圾一起被清除当 Git 的垃圾收集器 运行 进行清理时。到那时,没有人会记得原始哈希 ID,原始命令将无处可寻。

好吧,除了任何 other 任何人曾经用它们制作的克隆之外,无处可寻。如果存在这样的克隆,您可能需要将它们根除并销毁,或者至少确保您不再从它们中获取并合并,否则您将再次 取回所有旧提交.