如何在错误的合并中修复历史记录

时间:2013-05-23 11:24:27

标签: git git-merge git-revert

我在Git中遇到一个问题,我无法修复。我搜索了类似的案例,但我无法找到适合我情况的好方案。

我基本上有2个分支,master和bugfix。 Bugfix是在我们完成发布时从master获得的。每次我们修复bugfix中的内容并执行bugfix发布时,我们需要将其合并到master中。 Master包含新功能(当然不应该合并到bugfix中)。碰巧有人错误地将master与bugfix合并。

This is what happened:

 master: x1---x2
                \
 bugfix: y1--y2--M

where M is the merge between bugfix and master

对此的解决方案是恢复合并,我使用“git revert -m 1 M”(M在这里是合并中的SHA),如here所述。我做了一个恢复,因为我们已经在bugfix分支中有其他变化,我们不想丢失,这对于bugfix分支工作正常。

Current state:

 master: x1--x2------------x---x

 bugfix: y1--x1--y2--x2--M--y--y--R1

where R1 is the revert of M

当我们需要在master中合并bugfix分支时,问题会出现。如我发布的链接中所述,恢复修复了代码更改但不修复历史记录,这意味着当我在master中合并bugfix时,revert将生效并从master(x1和x2)中删除更改。在将其合并到master中之前,我能做的是修复bugfix中的revert。

Solution:

 master: x1--x2------------x---x--------M
                                       /
 bugfix: y1--x1--y2--x2--M--y--y--R1--R2

where R2 is the revert of R1

这可行,但不是最终的解决方案,因为每次我们进行合并时,我们都需要这样做“还原恢复”。我一直在寻找一个永久性的解决方案,现在看来,唯一的选择就是从bugfix分支的历史记录中删除主提交(x1和x2)。但是这里仅使用x1和x2作为示例,实际上我们有更多的提交并且解析bugfix分支的历史是非常困难且容易出错的。我确信Git可以帮助我做到这一点,但我不知道如何。

任何想法都会非常有用。

3 个答案:

答案 0 :(得分:2)

我个人建议重写历史记录(请参阅Useless的答案)并告诉您的团队。但这要求每个人都有一定程度的git知识。如果重写方法对你来说风险太大,可以选择以下方法:

发生了什么

每当您将A合并到B时,git会将所有可从A但不能BB的提交/更改添加到git checkout -b bugfix-revert bugfix git revert R1 git checkout master git merge bugfix-revert git branch -d bugfix-revert 。你的还原就是其中之一。正如你所注意到的那样,没有重写你就无法做任何事情。

解决方案

您必须将revert合并为master。如你所愿,保留你在master中恢复的内容,你还需要撤消master上的revert(=从master可以访问)。实现这一目标的最佳方法是使用以下命令:

 [master] x1---x2----------------------H
                 \                    /
 [bugfix-revert]  \                  M''
                   \                /
 [bugfix] y1--y2----M--y3--y4--M'--y5

在这些命令之后,每个分支都处于你想要的状态,你可以从现在开始再次合并bugfix。您的历史记录如下:

master

正如您所看到的,M'包含H,但其更改不在M''中,因为M'取消了这些更改。 master永远不会应用于bugfix,因为它已包含它。状态{{1}}没有改变,也没有改变。

答案 1 :(得分:1)

为什么不首先创建一个没有错误合并的新bugfix分支?您需要与所有人协调切换分支,以确保没有提交丢失

所以你有:

 [master] x1---x2
                 \
 [bugfix]  y1--y2--M--y3--y4--M'

(其中M'M的回归。但是,您可以创建一个新分支:

$ git branch bugfix-fix y4

 [master] x1---x2
                 \
 [bugfix]  y1--y2--M--y3--y4--M'
                          ^^
                     [bugfix-fix]

将其从有问题的合并和回复中分离出来

$ git rebase --onto y2 M bugfix-fix

 [master] x1---x2
                 \
 [bugfix]  y1--y2--M--y3--y4--M'
                 \
 [bugfix-fix]     y3'--y4'

然后,当您确认所需的所有内容都在bugfix-fix之后,您就可以重命名这两个分支

$ git branch -m bugfix bugfix-broken
$ git branch -m bugfix-fix bugfix

(你需要强行推动这个,这是安全的,只要你与可能已经签出的所有人协调)。

答案 2 :(得分:-1)

你的解决方案是正确的......你需要'还原恢复',然后再与你的bugfix分支合并(以引入在第一次错误合并后完成的任何错误修复提交),就像你已经显示的那样。这将从y1和y2提交中恢复修复,保持历史记录正确并提取在第一个错误合并点之后执行的更新更改。

你不需要为将来的合并而担心这个,因为最后一个合并点是历史中git会尝试进行合并的地方,而不是它之前的任何东西(你需要做的同样的确切原因)还原')......


不知道为什么你说这会使bugfix处于破碎状态。以下工作正常。您可以根据需要继续处理错误修复分支,而不必担心不得不还原任何东西(除非您显然再次执行相同的操作......)。如果您将来需要再次与master合并,您可以毫无问题(无需做任何特殊处理),因为git知道历史记录,并且只会从两个分支最后一个共同点查找合并问题/冲突(这个最后合并)。

https://github.com/g19fanatic/stackoverflow-16713251-496405

gitk example


这是一个link,其中Linus描述了这个问题,并将我上面提出的解决方案作为纠正它的一种可能方法......