一种方法是使用变基。
无论您选择哪种方法,您都将必须重写存储库的历史记录。你必须接受这一点,否则你将不得不接受你当前的历史。
让我们总结一下你历史的不同部分:
- 提交 4、5 和 8,这些在 master 上
- 提交 3、6、7 和 9,这些现在也在 master 上,但最初在不同的分支上
- 在您合并上述两个并行历史后,提交 10 和 11 位于 master 上
为了解决这个问题,我会做以下事情:
- 查看“原始分支”,即commit nr。 9
- 在这里创建一个新分支,只是为了确保我们可以玩一会儿
- 将这个新分支(由提交 3、6、7 和 9 组成)重新设置在 master 之上,就像最初合并时一样,所以在提交 8 之上
- 解决任何合并冲突(您在最初合并时也遇到了这些冲突,但现在可能需要以不同的方式处理它们,因为与合并相比,rebase 的操作方式)
- 完成此操作后,检查 master 上的最后一个 previous 提交,即 11,然后在新分支之上重新设置提交 10 和 11
- 如果一切现在看起来不错,您可以将 master 硬重置到这个新分支并强制推送到您的遥控器以使其成为新的历史记录
这里是过程图,一步一步(命令如下):
现在的状态:
master
v
1---2---4---5---8---M--10--11
\ /
3---6---7---9
9 的新分支:
master
v
1---2---4---5---8---M--10--11
\ /
3---6---7---9
^
TEMP1
基于 8 的变基,这将创建 3'、6'、7'、9'(' 表示“提交的副本,相同的内容,新的哈希”)
TEMP1
v
3'--6'--7'--9'
/
1---2---4---5---8---M--10--11
\ / ^
3---6---7---9 master
为11创建一个新的分支(我不喜欢和master搞混)
TEMP1
v
3'--6'--7'--9'
/
1---2---4---5---8---M--10--11
\ / ^
3---6---7---9 master
^
TEMP2
在 TEMP1 之上重新设置这个分支(10 和 11):
TEMP1 TEMP2
v v
3'--6'--7'--9'-10'-11'
/
1---2---4---5---8---M--10--11
\ / ^
3---6---7---9 master
验证 TEMP2 是否与当前 master 相同,没有丢失,没有添加等。
然后将 master 硬重置为 TEMP2:
master
v
TEMP1 TEMP2
v v
3'--6'--7'--9'-10'-11'
/
1---2---4---5---8---M--10--11
\ /
3---6---7---9
然后我会删除分支 TEMP1 和 TEMP2。
请注意,提交 3、6、7、9、M、10 和 11 仍然存在于存储库中,但它们不是直接可用的,因为没有任何东西引用它们。因此,它们有资格进行垃圾收集,实际上您的存储库的实际历史现在看起来像这样:
1---2---4---5---8---3'--6'--7'--9'-10'-11'
^
master
执行这些操作的命令是:
(步骤 0:制作本地文件夹的完整副本,包括工作文件夹和 .git 存储库,然后,如果可以,在该副本中执行以下命令,如果搞砸了,请删除该副本然后重新开始,不要在没有安全网的情况下跳跃)
git checkout <HASH-OF-9>
-
git checkout -b TEMP1(是的,您可以使用git checkout -b TEMP1 <HASH-OF-9> 在一个命令中执行此操作和上一个命令)
git rebase -i --onto <HASH-OF-8> <HASH-OF-2> TEMP1
- 解决合并冲突并提交(如果有)
-
git checkout -b TEMP2 <HASH-OF-11>
git rebase --onto TEMP1 <HASH-OF-MERGE> TEMP2
- 检查是否一切正常
-
git checkout master
git reset --hard TEMP2
最后,清理:
git branch -d TEMP1 TEMP2
git push -f
只有在您知道一切正常时才强制推送