重述问题
所以你的回购的当前状态是:
A --- B --- C --- D ------
\ \
E --- F --- G --- (M) --- H --- I --...-- Z (master)
但是合并没有成功,所以C
&表示的更改D
没有正确地合并到当前master
分支中。
不能做(不会引起疼痛)
不幸的是,您将无法达到以下状态:
A --- B --- C --- D --- E' --...-- Z' (master)
master
不会给每个将当前分支拉入他们自己的仓库的人造成问题。
一切都没有丢失
但是,您可以通过多种方式获得类似的结果(但我不能保证不会出现任何合并冲突)。根据您的评论,我假设您确实知道缺少提交的参考。为方便起见,我还将假设您已标记以下提交:
$ git tag <ref-to-D> oldmaster
$ git tag <ref-to-G> premerge
$ git tag <ref-to-H> postmerge
丢失年表
如果您并不真正关心维护提交的年表(即
A --- B --- C --- D --- E --...
),最简单的路线可能是重新定位到当前master
:
$ git checkout oldmaster
$ git rebase master
# deal with any merge-conflicts
$ git push origin master
# get it out there before anyone else extends the branch further!
如果一切按计划进行,您的分支现在将如下所示:
A --- B --- E --- F --...-- Z --- C' --- D' (master)
夸大冲突的痛苦?
如果你真的想保持年表,让我们尝试重新定位到旧的
master
:
(取决于它是如何失败的,原始合并可能会导致这种方法出现问题。如果是这样,我们将在第三种方法中处理)
$ git checkout master
$ git rebase oldmaster
# deal with any merge-conflicts
这是你害怕的冲突时期……但它可能没有那么痛苦。Git 通常非常擅长处理分支之间的差异,所以这里可能不需要太多的人工干预。
完成后,您的分支将如下所示:
A --- B --- C --- D -------- E' --- F' --...-- Z' (master)
\ \
E --- F --- G --- (M) --- H --...-- Z (origin/master)
我们现在面临的一个大问题是,其他人都认为Z
是
master
分公司的负责人。你不能把你的新东西强加给master
其他人,而不会造成太多的痛苦和痛苦。现在要做的最整洁的事情可能是:
$ git merge -s ours origin/master
# this creates a merge commit between the two master branches, but the file
# contents will be identical to our new master branch
$ git push origin master
现在图片应该是:
A --- B --- C --- D -------- E' --- F' --...-- Z' --- (M2) (master)
\ \ / (origin/master)
E --- F --- G --- (M) --- H --...-- Z --------
一步一步来
也许您喜欢以前的结果,但是冲突太多了。或者也许之前失败的合并抬起了丑陋的头并引起了问题。
让我们尝试最后一种方法,以更小的步骤进行。首先,让我们创建在原始合并时我们应该拥有的分支:
$ git checkout oldmaster
$ git rebase premerge
# remember I "assumed" you had tagged those refs?
# deal with any merge-conflicts
我们现在应该看看这个状态:
A --- B --- C --- D -------- E' --- F' --- G' (oldmaster)
\ \
E --- F --- G --- (M) --- H --- I --...-- Z (master)
我们将跳过该合并提交并尝试引入提交H
-<code>Z。因为你在这里,所以我感觉有点谨慎,所以我H
要先自己引入:
$ git cherry-pick postmerge
# deal with any merge-conflicts
如果有任何困难的冲突,他们可能会在这里。你仍然需要解决它们,但至少它们只代表一个提交(他说,他知道他不必自己合并它们!)。
树现在应该如下所示:
A --- B --- C --- D -------- E' --- F' --- G' --- H' (oldmaster)
\ \
E --- F --- G --- (M) --- H --- I --...-- Z (master)
准备好进行最后一击了吗?我们将从 master 引入剩余的提交,然后像以前一样创建一个合并提交,以便我们可以安全地将其他用户带到新分支:
$ git cherry-pick postmerge..master
$ git merge -s ours master
这应该导致:
A --- B --- C --- D -------- E' --- F' --...-- Z' --- (M2) (oldmaster)
\ \ /
E --- F --- G --- (M) --- H --...-- Z --------
(master)
因为我们正在处理oldmaster
分支,所以我们需要master
在推回之前快进真正的分支:
$ git checkout master
$ git merge oldmaster
# fast-forward merge
$ git push origin master
应该就是这样!