如何在没有死亡的情况下扭转合并对极化分支的影响?
这个问题困扰着我几个月,我终于放弃了。
您有1个存储库,其中包含2个命名分支。 A和B.
A发生的变化将不可避免地发生在B.
B上直接发生的变化绝不会发生在A上。
在这样的配置中,将“B”合并为“A”会在存储库中产生严重问题,因为对B的所有更改都显示在A中,就像它们是在A中一样。
从这种情况中恢复的唯一“正常”方式似乎是“退出”合并,即:
hg up -r A
hg backout -r BadMergeRev --parent BadMergerevBeforeOnA
看起来很好,花花公子,直到你决定稍后在正确的方向合并,然后你最终会发生各种令人讨厌的事情,并且在特定分支B上删除/注释掉的代码突然变得没有注意或没有注释。
到目前为止,还没有一个可行的可行解决方案,除了“让它做它的事情,然后解决所有问题”,说实话有点尴尬。
这是澄清问题的图片:
[原始图片丢失]
档案C& E(或更改C& E)必须仅出现在分支b上,而不是出现在分支a上。 这里的版本A9(分支a,revno 9)是问题的开始。
修订版A10和A11是“退出合并”和“合并退出”阶段。
修订版B12是多变的,错误地反复删除了意图不被删除的更改。
这种困境引起了很多挫折和蓝烟,我想结束它。
尝试禁止反向合并可能是一个明显的答案,无论是使用钩子还是使用策略,我发现将其解除的可能性相当高,并且发生这种情况的可能性很大,即使采取对策,你必须仍然认为不可避免地会发生 ,以便你可以解决它。
在模型中我使用了Seperate文件。这些使问题听起来很简单。这些仅代表任意更改,它们可以是一个单独的行。
另外,为了增加对伤害的侮辱,分支A上发生了实质性的变化,留下了常见的问题“分支A的变化与分支B的变化发生冲突,分支B刚刚出现(并且已退出)比如分支A的变化而不是“
所有这些追溯活动解决方案的问题如下:
(我承认,上面的许多内容都有些愚蠢,但它们不受我的控制)。
唯一可行的解决方案是假设人们可以而将做错所有事情,并且有一种方法可以“撤消”这种错误。
答案 0 :(得分:50)
我认为我找到了一个永久修复错误合并的解决方案,并且不需要您手动检查任何差异。诀窍在于回溯历史并生成与不良合并并行的提交。
因此,我们拥有一个存储库,每个维护版本的单个产品都有单独的分支。与问题中提出的情况一样,在早期版本的分支上进行的所有更改(即该版本中的错误修正)都必须最终合并到更高版本的分支。
具体而言,如果在BRANCH_V8上签入了某些内容,则必须将其合并到BRANCH_V9。
现在其中一个开发人员犯了以下错误:他将BRANCH_V9中的所有更改合并到BRANCH_V8中(即合并方向错误)。此外,在糟糕的合并之后,他会在注意到他的错误之前执行一些额外的提交。
所以情况如下图所示。
o BRANCH_V8 - 13 - important commit right after the bad merge | o BRANCH_V8 - 12 - wrong merge from BRANCH_V9 |\ | o BRANCH_V8 - 11 - adding comment on BRANCH_V8 (ie. last known good state) | | o | BRANCH_V9 - 10 - last commit on BRANCH_V9 | |
我们可以按如下方式解决这个错误:
hg update 11
$EDITOR some/file.txt
(这是必要的,因为Mercurial不允许空提交)hg commit -m "generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9"
o BRANCH_V8 - 14 - generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9 | | o BRANCH_V8 - 13 - important commit right after the bad merge | | | o BRANCH_V8 - 12 - wrong merge from BRANCH_V9 |/| o | BRANCH_V8 - 11 - adding comment on BRANCH_V8 | | | o BRANCH_V9 - 10 - last commit on BRANCH_V9
将新生成的头部与发生错误合并的修订版合并,并在提交之前丢弃所有更改。 不要简单地合并两个头,因为你将失去合并后发生的重要提交!
hg merge 12
(忽略任何冲突)hg revert -a --no-backup -r 14
hg commit -m "throwing away wrong merge from BRANCH_V9"
现在看起来像是:
o BRANCH_V8 - 15 - throwing away wrong merge from BRANCH_V9 |\ | o BRANCH_V8 - 14 - generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9 | | +---o BRANCH_V8 - 13 - important commit right after the bad merge | | o | BRANCH_V8 - 12 - wrong merge from BRANCH_V9 |\| | o BRANCH_V8 - 11 - adding comment on BRANCH_V8 | | o | BRANCH_V9 - 10 - last commit on BRANCH_V9 | |
IE中。 BRANCH_V8上有两个头:一个包含坏合并的修复,另一个包含BRANCH_V8上的剩余重要提交,它发生在合并之后。
hg merge
hg commit -m "merged two heads used to revert from bad merge"
BRANCH_V8最终的情况现在已得到纠正,如下所示:
o BRANCH_V8 - 16 - merged two heads used to revert from bad merge |\ | o BRANCH_V8 - 15 - throwing away wrong merge from BRANCH_V9 | |\ | | o BRANCH_V8 - 14 - generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9 | | | o | | BRANCH_V8 - 13 - important commit right after the bad merge |/ / o | BRANCH_V8 - 12 - wrong merge from BRANCH_V9 |\| | o BRANCH_V8 - 11 - adding comment on BRANCH_V8 | | o | BRANCH_V9 - 10 - last commit on BRANCH_V9 | |
现在BRANCH_V8的情况是正确的。剩下的唯一问题是从BRANCH_V8到BRANCH_V9的下一次合并将是不正确的,因为它将在错误合并的“修复”中合并,这是我们在BRANCH_V9上不需要的。这里的技巧是在单独的更改中从BRANCH_V8合并到BRANCH_V9:
详细说明:
hg update BRANCH_V9
hg merge 14
hg commit -m "Merging in last good state of BRANCH_V8"
现在的情况是:
@ BRANCH_V9 - 17 - Merging in last good state of BRANCH_V8 |\ | | o BRANCH_V8 - 16 - merged two heads used to revert from bad merge | | |\ | +---o BRANCH_V8 - 15 - throwing away wrong merge from BRANCH_V9 | | | | | o | | BRANCH_V8 - 14 - generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9 | | | | | | o | BRANCH_V8 - 13 - important commit right after the bad merge | | |/ +---o BRANCH_V8 - 12 - wrong merge from BRANCH_V9 | |/ | o BRANCH_V8 - 11 - adding comment on BRANCH_V8 | | o | BRANCH_V9 - 10 - last commit on BRANCH_V9 | |
hg merge 15
hg revert -a --no-backup -r 17
hg commit -m "Merging in bad merge from BRANCH_V8 and its fix and throwing it all away"
现在的情况 :
@ BRANCH_V9 - 18 - Merging in bad merge from BRANCH_V8 and its fix and throwing it all away |\ | o BRANCH_V9 - 17 - Merging in last good state of BRANCH_V8 | |\ +-----o BRANCH_V8 - 16 - merged two heads used to revert from bad merge | | | | o---+ | BRANCH_V8 - 15 - throwing away wrong merge from BRANCH_V9 | | | | | | o | BRANCH_V8 - 14 - generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9 | | | | +-----o BRANCH_V8 - 13 - important commit right after the bad merge | | | o---+ BRANCH_V8 - 12 - wrong merge from BRANCH_V9 |/ / | o BRANCH_V8 - 11 - adding comment on BRANCH_V8 | | o | BRANCH_V9 - 10 - last commit on BRANCH_V9 | |
hg merge BRANCH_V8
hg commit -m "merging changes from BRANCH_V8"
最终情况如下:
@ BRANCH_V9 - 19 - merging changes from BRANCH_V8 |\ | o BRANCH_V9 - 18 - Merging in bad merge from BRANCH_V8 and its fix and throwing it all away | |\ | | o BRANCH_V9 - 17 - Merging in last good state of BRANCH_V8 | | |\ o | | | BRANCH_V8 - 16 - merged two heads used to revert from bad merge |\| | | | o---+ BRANCH_V8 - 15 - throwing away wrong merge from BRANCH_V9 | | | | | | | o BRANCH_V8 - 14 - generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9 | | | | o | | | BRANCH_V8 - 13 - important commit right after the bad merge |/ / / o---+ BRANCH_V8 - 12 - wrong merge from BRANCH_V9 |/ / | o BRANCH_V8 - 11 - adding comment on BRANCH_V8 | | o | BRANCH_V9 - 10 - last commit on BRANCH_V9 | |
在所有这些步骤之后,您不必手动检查任何差异,BRANCH_V8和BRANCH_V9是正确的,未来从BRANCH_V8到BRANCH_V9的合并也将是正确的。
答案 1 :(得分:2)
在紧要关头,您可以将存储库导出到一堆差异,编辑历史记录,然后将您想要的内容粘合到一个新的存储库中,这样就不会有损坏的风险。对你的例子来说可能不是太糟糕,但我不知道真实的历史是什么样的。
我在执行更简单的操作时引用了此页面:
http://strongdynamic.blogspot.com/2007/08/expunging-problem-file-from-mercurial.html
答案 2 :(得分:2)
好的,首先在与破坏的存储库(hg init)不同的目录中创建一个新的空存储库。现在,将最后一个已知的好版本添加到新存储库中;确保不拉出错误合并,然后做拉出所有内容。在旧存储库中,更新到上一个已知良好版本的A,并执行以下操作:
hg graft r1 r2 r3
其中r1-3是在拙劣合并之后所做的更改。你可能会在这一点上遇到冲突;解决它们。
这应该针对上一个已知良好版本的A 产生新的更改。将这些新更改提取到新存储库中。只是为了仔细检查你没有错过任何东西,做一个针对旧存储库的hg传入。如果你看到除了拙劣的合并和r1-3以外的任何东西,请拉它。
扔掉旧存储库。你完成了。合并根本不在新的存储库中,您永远不必重写历史记录。
答案 3 :(得分:1)
所以你想把B中的一些变更集合并成A?像你一直在做的更改集是一个非常糟糕的主意,因为你已经受苦了。
您应该使用移植扩展,或者使用第三个分支进行常规更改以合并到A和B中。
答案 4 :(得分:1)
经过与freenode上#mercurial的一些有用的人讨论后,mpm提供了一个部分解决方案,似乎适用于我的测试用例(我生成了一个假存储库,试图复制方案)
然而,在我的实际存储库中,由于我不太了解的原因,它仍然不完美。
以下是目前提出的解决此问题的方法的图表:
[原始图片丢失]
现在少要修复的问题,但我仍然需要比较差异(即:b46:b11 vs b46:b8,a43:a10 vs a43:a9)并手动编辑一些变化回来了。
在我获得适用于任何存储库的保证方式之前,不要关闭此问题/接受答案。
任何尝试这种东西的人都应该克隆他们的存储库,然后像沙盒一样玩它。正如您应该使用任何合并过程一样,因为如果出现错误,您可以将其丢弃并重新开始。