您有几种选择。
解决方案 1:Squash 合并
一种解决方案是简单地使用硬重置和一些壁球合并:
git checkout master
git reset --hard C
git merge --squash topic1
git commit -m "Rewrite D"
git merge --squash topic2
git commit -m "Rewrite E"
# Verify that the new branch is no different from the old one
git diff sha_of_old_E
这里的想法是,壁球合并会将主题分支的最终状态(即最后一次提交)复制到您当前的工作副本中,然后您可以在其中提交它。它有效地将一个分支压缩成一个提交。
文档
解决方案 2:交互式变基
另一种方法是使用交互式 rebase 将主题分支压缩为单个提交。首先,调用变基
git rebase -i C
这将在您的终端中打开交互式变基 TODO 列表编辑器。您将看到显示以下提交:
pick sha W1
pick sha X1
pick sha Y1
pick sha W2
pick sha X2
pick sha Y2
您想要做的是类似于上面的壁球合并。您可以将主题分支压缩为单个提交,因此对于主题分支的每个提交,将后代提交压缩(或“修复”)到其父级:
pick sha W1
squash sha X1
squash sha Y1
pick sha W2
squash sha X2
squash sha Y2
然后在 Vim 编辑器中点击 :wq 开始交互式变基。我不会详细介绍接下来的步骤,因为它们已经在互联网上的其他众多来源中进行了充分详细的介绍,例如 Pro Git § 6.4 Git Tools - Rewriting History - Squashing Commits。
您可能需要通过使用简单的 diff 验证新重写的分支与前一个分支没有什么不同,从而再次检查您是否正确执行了 rebase:
git diff sha_of_old_E
请注意,如果您不想为每个 squash 编辑提交消息,则可以使用“fixup”,它只会重复使用上一次提交的提交消息:
pick sha W1
fixup sha X1
fixup sha Y1
pick sha W2
fixup sha X2
fixup sha Y2
请注意,您也可以分别使用 s 或 f 进行 squash 和 fixup。
文档
强制推送警告
请注意,当然,上述两种解决方案都会重写您的提交历史记录,因此您的新提交将具有不同的 sha ID。如果您已经将旧版本的分支推送到远程,那么您需要强制推送以覆盖旧副本。如果您与其他人共享您的分支,这可能不是您想要做的事情,原因我不会在这里详述,因为在许多其他在线资源中都有详细记录强制推送的可能危险,例如: