你需要的命令是git rebase
,具体来说是-i/--interactive
选项。
我假设你想要将提交c留在分支A上,并且你确实希望将其他提交移到其他分支,而不是进行合并,因为合并是直接的。让我们开始操作分支A。
git rebase -i <SHA1 of commit a>^ branchA
^
表示前一个提交,因此此命令表示重新设置分支A,以"a"之前的提交为基础。Git会向您显示此范围内的提交列表。重新排序它们并告诉git压缩相应的提交:
pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f
现在历史记录应该看起来像这样:
c - [a+d+e+g] - [b+f] (branchA)
/
--o-x-x-x-x-x-x-x-x-x-x (master)
现在,让我们获取分支B的最新压缩提交 b+f。
git checkout branchB
git cherry-pick branchA
而对于主分支(master)的a+d+e+g同样适用:
git checkout master
git cherry-pick branchA^
最后,更新 branchA 指向 c:
git branch -f branchA branchA^^
我们现在应该有:
c (branch A) - [a+d+e+g] - [b+f] (dangling commits)
/
--o-x-x-x-x-x-x-x-x-x-x-[a+d+e+g] (master)
\
x-x-x-x-x-[b+f] (branchB)
请注意,如果您有多个提交需要在分支之间移动,则可以再次使用rebase(非交互式):
git branch fromAtoB branchA
git branch -f branchA branchA~2
git rebase --onto branchB branchA fromAtoB
git checkout branchB
git merge fromAtoB
git branch -d fromAtoB
最后,需要声明的是:重新排序提交记录可能会导致某些提交记录无法干净地应用。可能是因为你选择了错误的顺序(比如在对引入某个功能的提交进行补丁之前),这种情况下你需要中止 rebase (git rebase --abort
)。否则,你需要聪明地解决冲突(就像处理合并冲突一样),添加修复,然后运行 git rebase --continue
继续操作。当发生冲突时,这些指示也会在错误消息中提供。