[英]Rebuilding git branch after a faulty merge (respecting merge commits)
I have a classic situation: I merged a dev
branch into master
, then realised I made a mistake and reverted the merge. 我有一个典型的情况:我将一个dev
分支合并到master
,然后意识到我犯了一个错误并恢复了合并。 Then added a fix into dev
and want to merge it again. 然后将一个修复程序添加到dev
并希望再次合并它。 Of course, I cannot merge it directly, since, from git's point of view, it was already merged. 当然,我不能直接合并它,因为从git的角度来看,它已经被合并了。
Revert the revert commit, apply your fix. 还原还原提交,应用您的修复程序。 Move on. 继续。
Pros : simple. 优点 :简单。
Cons : history is spoiled. 缺点 :历史被宠坏了。 It is very hard to blame deeper than this revert of the revert. 很难比这次恢复的责任更深。
I want to rebuild the dev
branch from scratch, and merge it again. 我想从头开始重建dev
分支,然后再次合并。 Should be easily done with git rebase --force-rebase
, according to the books. 根据书,应该使用git rebase --force-rebase
轻松完成。 But the branch history was not so simple, and contained a number of merges, including merges from master
. 但是分支的历史记录并不是那么简单,它包含许多合并,包括master
合并。 I want to respect these. 我要尊重这些。
Let's have an example already: 让我们已经有一个例子:
master|
v
-*------------X-----Y---------*-----*----M-W
\ / \ \ / /
\ / \ -*- /
\ / -D- G--H-- /
\ / / \ / \ /
A--B--C-----E--F--------I-----J
^
|dev
The faulty merge is M
. 错误的合并是M
Its revert is W
. 其还原为W
I assume that commits on dev
up to B
are ok, since B
was merged into master
as X
. 我认为对B
dev
提交是可以的,因为B
已作为X
合并到master
中。 I want to rebuild the branch starting from B
with exactly the same topology. 我想从B
开始以完全相同的拓扑重建分支。 See the tree below. 请参阅下面的树。 New commits are marked with the prime. 新提交标记有撇号。 You can see how commits C..J
were rebased to C'..J'
. 您可以看到如何将提交C..J
重新设置为C'..J'
。 Correspondingly, dev
is rebased to dev'
. 相应地, dev
会以dev'
。 Other commits did not change. 其他提交未更改。
dev'|
v
C'----E'-F'-------I'----J'
/ \ / \ /
| -D' G'-H'-
| / |master
| / v
-*--------+---X-----Y---------*-----*----M-W
\ | / \ \ / /
\ | / \ -*- /
\ |/ -D- G--H-- /
\ / / \ / \ /
A--B--C-----E--F--------I-----J
^
|dev
Then I'll apply my fix K
and merge this new branch to master
: 然后,我将应用我的修订K
并将此新分支合并到master
:
dev'|
v
C'----E'-F'-------I'----J'--K
/ \ / \ / \
| -D' G'-H'- \
| / \ |master
| / \v
-*--------+---X-----Y---------*-----*----M-W-M2
\ | / \ \ / /
\ | / \ -*- /
\ |/ -D- G--H-- /
\ / / \ / \ /
A--B--C-----E--F--------I-----J
^
|dev
Pros : good history. 优点 :良好的历史。
Cons : I don't know how to do this. 缺点 :我不知道该怎么做。
Ok, seems like rebase
has an option for this, and it is called --rebase-merges
. 好的,似乎rebase
为此提供了一个选项,它称为--rebase-merges
。 But it does not do what I want. 但这并不能满足我的要求。 It rebases all commits, that are ancestors of dev
and descendants of B
. 它以所有提交为基础, 即dev
祖先和B
后代 。 Which includes commits X
and Y
. 其中包括提交X
和Y
Which are on master
already, why would I want them? 哪些已经master
了,我为什么要它们? (Actually, it also brings some other commits from the more ancient history, and I don't understand why yet, but it's not the point here). (实际上,它还带来了更古老的历史中的其他一些贡献,我还不知道为什么,但这不是重点)。
Instead, I want to bring commits, that are ancestors of dev
but not master
(considering master
before the faulty merge of course). 相反,我想提出一些提交, 这些提交是dev
始祖,而不是master
(当然,在错误合并之前考虑master
)。 Sounds really easy to me. 对我来说听起来真的很容易。 Yet I don't understand how to do it, except by manually constructing this difference of commits and somehow cherry-picking them by hand, carefully preserving parents. 但是我不知道该怎么做,除非通过手工构造这种不同的提交,然后以某种方式手工挑选它们,并小心翼翼地保护父母。
So, how do I rebuild my branch, containing only work done on my branch and respecting merge commits? 那么,如何重建分支, 只包含在分支上完成的工作并尊重合并提交?
PS We cannot simply reset master
to M^
, that would be too easy. PS我们不能简单地将master
重置为M^
,这太容易了。
Ok, seems like I found a solution: 好的,好像我找到了解决方案:
git rebase --interactive --rebase-merges B dev
This produces exactly the history I want. 这正是我想要的历史。 Credits to @mstrap for the hint. 归功于@mstrap作为提示。
I'm not exactly sure why this works the way I want though. 我不确定这为什么能按我想要的方式工作。
Based on https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt , I would 基于https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt ,我会
git checkout dev
$EDITOR files
git commit files -m 'Fix'
git checkout master
git revert W
git merge dev
The revert-revert is necessary to keep the changes when you re-merge. 当您重新合并时,还原-还原是保持更改所必需的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.