如何修复错误合并中的历史记录
Posted
技术标签:
【中文标题】如何修复错误合并中的历史记录【英文标题】:How to fix the history in a wrong merge 【发布时间】:2013-05-18 17:43:40 【问题描述】:我在 Git 中有一个我无法解决的问题。我已经搜索了类似的案例,但我无法找到适合我的情况的好的解决方案。
我基本上有 2 个分支,master 和 bugfix。错误修复是在我们完成发布时从 master 派生的。每次我们在 bugfix 中修复某些内容并进行 bugfix 发布时,我们都需要将其合并到 master 中。 Master 包含新功能(当然不应该合并到错误修复中)。碰巧有人错误地将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 分支时,问题会出现。如我发布的链接中所述,revert 修复了代码更改但不修复历史记录,这意味着当我在 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
这可行,但不是最终解决方案,因为每次我们进行合并时,我们都需要执行“revert of the revert”。几天来,我一直在寻找永久解决方案,似乎唯一的选择是从错误修复分支的历史记录中删除主提交(x1 和 x2)。但是这里使用 x1 和 x2 只是作为示例,实际上我们有更多的提交,并且剖析 bugfix 分支的历史非常困难且容易出错。我确信 Git 可以帮助我做到这一点,但我不知道如何。
任何想法都会非常有帮助。
【问题讨论】:
您的历史在第一张和第二张照片中看起来不同。哪一个?在第一张图片中有适当的合并,在第二张图片中是快进。 我想表明错误修复中的历史现在与大师的历史混合在一起。 您展示了它在显示为线性(按时间顺序)历史时的外观,而不是它的样子。 【参考方案1】:我个人建议重写历史(见Useless 的答案)并告诉你的团队。但这需要每个人都具备一定程度的 git 知识。如果重写方法对您来说风险太大,这里有一个替代方案:
发生了什么
当你将A
合并到B
时,git 会将所有可以从A
访问但不是B
的提交/更改添加到B
。你的回复就是其中之一。正如您所注意到的,如果不重写,您将无能为力。
解决办法
您必须将还原合并到主文件中。由于您希望将恢复的内容保留在 master 中,因此您还需要在 master 上撤消该恢复(=可从 master 访问)。实现这一目标的最佳方法是使用以下命令:
git checkout -b bugfix-revert bugfix
git revert R1
git checkout master
git merge bugfix-revert
git branch -d bugfix-revert
在这些命令之后,每个分支都将处于您想要的状态,并且您可以从现在开始再次合并错误修复。您的历史记录将如下所示:
[master] x1---x2----------------------H
\ /
[bugfix-revert] \ M''
\ /
[bugfix] y1--y2----M--y3--y4--M'--y5
如您所见,master
包含M'
,但其更改不在H
中,因为M''
取消了这些。 M'
永远不会应用于master
,因为它已经包含它。 bugfix
状态没有改变,也不必改变。
【讨论】:
我们最终选择了这个解决方案,它已经奏效了。感谢您的帮助!【参考方案2】:为什么不首先创建一个没有错误合并的新错误修复分支?不过,您需要与每个人协调切换分支,以确保不会丢失任何提交
所以你有:
[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
(您需要强行推动,只要您与可能检查过它的每个人协调,这是安全的)。
【讨论】:
协调部分比较难。如果你不小心,有人拉扯,你最终会陷入同样的境地,历史会更加混乱。 我不知道可以像这样使用变基。我们选择了其他解决方案,但我一定会记住您的。谢谢。【参考方案3】:您的解决方案是正确的...您需要“还原还原”,然后与您的错误修复分支进行另一次合并(以提取在第一次错误合并后完成的任何错误修复提交),正如您所展示的.这将从您的 y1 和 y2 提交中恢复修复,保持您的历史正确并提取在第一个错误合并点之后执行的更新更改。
您不必担心未来的合并,因为最后一个合并点是历史上 git 尝试进行合并的地方,而不是之前的任何地方(与您需要执行“还原”的确切原因相同)的还原')...
不知道你为什么说这会使错误修复处于损坏状态。以下工作正常。您可以根据需要继续在错误修复分支上工作,而不必担心必须再恢复任何内容(除非您显然再次做同样的事情......)。如果您将来需要再次与 master 合并,您可以毫无问题(不需要做任何特别的事情),因为 git 知道历史,并且只会从两个分支最后共同的点查找合并问题/冲突(这最后一次合并)。
https://github.com/g19fanatic/***-16713251-496405
这是一个link,Linus 描述了这个问题,并提出了我上面提出的解决方案作为纠正它的一种可能方法......
【讨论】:
以上是关于如何修复错误合并中的历史记录的主要内容,如果未能解决你的问题,请参考以下文章