git checkout -b somebranch # from "A"
......some work commits here x, y, z .....
git checkout master
git pull # call new HEAD "B"
所以我们有类似的东西
A -> a1 -> a2 -> B <= master
\
x -> y -> z <= somebranch
进而:
git checkout somebranch
git rebase master
A -> ... -> B <= master
\
x' -> y' -> z' <= somebranch
git checkout master
git merge somebranch # call new HEAD "C"
A -> ... -> B -------------> C <= master
\ /
x' -> y' -> z' <= somebranch
因此,此时,您可以轻松撤消不需要的合并,只需将 master 倒回到B
. 然而,一旦你推动 C
(并且其他人已经看到它,和/或在它之上完成了工作),这变得很难。
简单的解决方案是只恢复所有提交somebranch
:
git revert x'..z'
和推。
现在,在您somebranch
再次合并之前,您必须对其进行变基(就像您最初所做的那样)。这行得通,但你最终会在大师的历史上留下一些噪音。
如果少数人看到和/或承诺了孩子,并且您可以与他们协调,则可以避免这种情况,但工作量很大。如果可能,您必须确保他们正在处理的所有内容都已提交并推送,然后您可以重新设置:
A -> ... -> B -------------> C -> c1 -> c2 -> D <= master
\ /
x' -> y' -> z' <= somebranch
对此:
c1' -> c2' -> D' <= master
/
A -> ... -> B -------------> C -> c1 -> c2 -> D
\ /
x' -> y' -> z' <= somebranch
现在中间分支将是孤立的,新的头D'
没有您的更改,并且somebranch
仍然完好无损,因此您可以稍后合并。
为此,请使用:
git rebase --onto B C c1
git push --force
其他所有人现在都必须更新到新的 head D'
,例如通过执行以下操作:
git fetch
git checkout master
git reset --hard origin/master
Note that if anyone does have local commits that still depend on C
(and aren't already visible in the c1..D
chain when you rebase), they'll need to rebase or cherry-pick them across to the new history. This is potentially a lot of (error-prone) work, so better to avoid if possible.