修复具有重复提交的git历史记录

7

简要版本:
我如何将左图转换为右图?另外,我需要手动清除重复的提交(root2、a'、b')还是GC会在未来某个时候对它们进行修剪?
before-after

详细版本:
由于糟糕的CVS到git移植,当我将branch_1从CVS导入时,已经在git中创建了master,因此在同一个repo中出现了两个备选历史记录。 如图所示,branch_1的提交有些是唯一的,但有些是重复的。 有什么简单的方法可以解决这个问题吗?

我有一些想法,但不确定如何执行它们。 其中之一是完全删除branch_1并重新开始,但我不知道如何让git识别root1和root2是相同的,以便所有补丁都应用于同一行。 另一个想法是将f,g,h变基到b上,并以某种方式删除root2、a'和b'。 但我认为由于没有共同的祖先,普通的变基操作无法正常工作。

实际上,该分支的重复提交和唯一提交有数百个,因此需要非常耗时的手动操作。

2个回答

2

首先你可以尝试的一种非破坏性方法是使用嫁接点(Graft Point)

# .git/info/grafts
0000000f 0000000b

请在您的图表中将那些内容替换为提交fb的SHA1值。

这个更改是非永久性的,但应该可以通过以下方式进行审查:

git log --graph --all --decorate

如果一切看起来都很好,您可以运行 git filter-branch 来使这些更改永久生效。
请注意,在您运行 git filter-branch 并推送之前,没有其他人会看到这些更改。这可能被视为一种“特性”,因为它不会强制任何其他人对他们的工作进行混乱的变基。这只是添加了一些额外的信息,告诉像 git-log 这样的工具,当它们查看提交“f”时,应该假装它有一个“b”的父级,而不实际更新提交对象以反映这一点。更改提交对象的父级会更改其 SHA1,这意味着其子提交需要更新以指向新的 SHA1,然后是它们的子提交等。

我推荐使用git merge而不是git rebase,因为它保留了两个分支的内容(树)。git rebase则只保留更改(差异)。 - Dietrich Epp
@DietrichEpp 你的意思是我最终会得到左图,但是有一条额外的从 bf 的边吗?如果这就是你所谓的“保留树”的意思,那么我不想要,因为这两棵树实际上是重复的。 - Hilikus
不,基本上你最终得到的是右侧的图形,但它在不重写任何历史记录的情况下完成。 - pioto
@Hilikus:最终你会得到右边的图片,只不过我会把它们标记为f'、g'、h',因为它们将具有不同的提交哈希值。你仍然重写历史,只是不改变任何树内容。在重写历史后,您可以删除“grafts”文件。 - Dietrich Epp

1
请注意,您正在请求的变基将重写branch_1所有提交的提交哈希值。我使用bb'表示您美丽图表中提交的提交哈希值。
git checkout branch_1
git rebase --onto b b'

这与手册页中git rebase的以下形式相匹配:
git rebase --onto <newbase> <upstream>

根据手册,接下来会发生以下情况。

  1. 当前分支中由提交所做的所有更改,但不在 <upstream> 中的更改将保存到临时区域。
  2. 当前分支将被重置为 <upstream>,如果提供了 --onto 选项,则重置为 <newbase>
  3. 然后按顺序逐个将之前保存在临时区域中的提交重新应用于当前分支。

如果我理解正确的话,rebase 的工作方式是在两个分支之间的最后一个共同祖先以来重放当前分支中的提交。在我的情况下,没有共同的祖先。所以它要么会失败,要么会将root2作为b的子节点。无论哪种情况都是错误的。我有什么遗漏吗? - Hilikus
1
@Hilikus,请查看man git-rebase并搜索--onto选项。 - merlin2011
我需要操作仓库以删除重复提交,还是它们悬空的事实意味着它们将在某个时候被垃圾回收?我不太清楚提交是否会永久存在于仓库中,或者它们是否需要可达性才能永久存在。 - Hilikus
如果bb'树之间有任何差异,这将消除该差异,可能会导致数据丢失。因此,我建议使用嫁接,就像pioto的答案一样。从根本上讲,git rebase执行合并操作,然后在没有合并的情况下重写它,而嫁接点完全避免了合并操作。git rebase本质上没有任何问题,只是在这里嫁接可以完全满足您的需求。 - Dietrich Epp
1
@dietrichepp,虽然我总体上同意你的观点,但是OP说他正在尝试删除重复提交。 - merlin2011
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接