在Mercurial上回退合并 [英] Backing Out a backwards merge on Mercurial

查看:69
本文介绍了在Mercurial上回退合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在不死于痛苦的情况下扭转合并对极化分支的影响?

How do you reverse the effect of a merge on polarised branches without dying of agony?

这个问题困扰着我个月,我终于放弃了.

This problem has been plaguing me for months and I have finally given up.

您有1个存储库,其中有2个命名分支. A和B.

You have 1 Repository, with 2 Named Branches. A and B.

在A上发生的更改将不可避免地在B上发生.

Changes that occur to A will inevitably occur on B.

直接在B上发生的更改绝不能在A上发生.

Changes that occur directly on B MUST NEVER occur on A.

在这种配置中,将"B"合并为"A"会在存储库中产生一个可怕的问题,因为对B的所有更改都像在A中一样出现在A中.

In such a configuration, merging "B" into "A" produces a dire problem in the repository, as all the changes to B appear in A as if they were made in A.

从这种情况中恢复的唯一正常"方法似乎是回退"合并,即:

The only "normal" way to recover from this situation appears to be "backing out" the merge, ie:

 hg up -r A 
 hg backout -r BadMergeRev --parent BadMergerevBeforeOnA 

看上去一切都很好,直到您决定以后以正确的方向合并,并且最终会发生各种令人讨厌的事情,并且在特定分支B上被擦除/注释掉的代码突然变得未被擦除或未注释.

Which looks all fine and dandy, until you decide to merge later in the correct direction, and you end up with all sorts of nasty things happening and code that was erased / commented out on specifically branch B suddenly becomes unerased or uncommented.

到目前为止,除了先解决问题,然后手动解决所有问题"以外,没有可行的可行解决方案,而且说实话有点麻烦.

There has not been a working viable solution to this so far other than "let it do its thing, and then hand fix all the problems" and that to be honest is a bit fubar.

这是一张说明问题的图片:

Here is an image clarifying the problem:

[原始图像丢失]

文件C& E(或更改C& E)必须仅出现在分支b上,而不出现在分支a上. 此处的修订版A9(分支a,修订版9)是问题的开始.

Files C & E ( or changes C & E ) must appear only on branch b, and not on branch a. Revision A9 here ( branch a, revno 9 ) is the start of the problem.

修订A10和A11是回退合并"和合并回退"阶段.

Revisions A10 and A11 are the "Backout merge" and "merge the backout" phases.

修订版B12是无用的,错误地反复删除了不希望删除的更改.

And revision B12 is mercurial, erroneously repeatedly dropping a change that was intended not to be dropped.

这个困境造成了很多挫败感和蓝烟,我想结束这一困境.

This Dilemma has caused much frustration and blue smoke and I would like to put an end to it.

尝试通过钩子或策略来阻止反向合并可能是一个显而易见的答案,我发现将这种情况混为一谈的能力非常高,而且即使采取对策,这种可能性也很可能发生,您必须仍然不可避免地会认为它会发生 ,以便您可以在解决时解决它.

It may be the obvious answer to try prohibiting the reverse merge from occurring, either with hooks or with policies, I have found the ability to muck this up is rather high and the chance of it happening so likely that even with countermeasures, you must still assume that inevitably, it will happen so that you can solve it when it does.

在模型中,我使用了单独的文件.这些使问题听起来很简单.这些仅表示任意更改,它们可能是单独的一行.

In the model I have used Seperate files. These make the problem sound simple. These merely represent arbitrary changes which could be a separate line.

此外,为了加重伤害,分支A进行了实质性更改,这留下了常备问题:使分支A的更改与分支B的更改发生冲突,而分支B的更改看上去(并退出了),看起来就像分支A上的更改,而不是"

Also, to add insult to injury, there have been substantial changes on branch A which leaves the standing problem "do the changes in branch A conflict with the changes in branch B which just turned up ( and got backed out ) which looks like a change on branch A instead "

所有这些追溯解决方案的问题如下:

The problem with all these retro-active solutions is as follows:

  1. 我们有9000次提交.
  2. 因此新鲜克隆需要半个小时
  3. 如果存储库某处中存在一个甚至一个错误的克隆,则很可能它会与原始存储库重新建立联系,并将其遍历再次.
  4. 每个人都已经克隆了这个存储库,而现在,随着正在进行的提交已经过去了几天.
  5. 一个这样的克隆恰好是一个在线站点,因此擦除该克隆并从头开始" ="big nono"
  1. We have 9000 commits.
  2. Cloning freshly thus takes half an hour
  3. If there exists even one bad clone of the repository somewhere, there is a liklihood of it comming back in contact with the original repository, and banging it up all over again.
  4. Everyone has cloned this repository already, and now several days have passed with on-going commits.
  5. One such clone, happens to be a live site, so "wiping that one and starting from scratch" = "big nono"

(我承认,以上许多内容有些愚蠢,但它们超出了我的控制范围).

( I admit, many of the above are a bit daft, but they are outside of my control ).

唯一可行的解​​决方案是那些假设人们可以做错所有事情的解决方案,并且有一种方法可以消除"这种错误.

The only solutions that are viable are the ones that assume that people can and will do everything wrong, and that there is a way to 'undo' this wrongness.

推荐答案

我想我找到了一个永久修复错误合并的解决方案,不需要您手动检查任何差异.诀窍是追溯历史并生成与错误合并并行的提交.

I think I found a solution which permanently fixes the bad merge, and which does not require you to manually check any diffs. The trick is to go back in history and generate commits parallel to the bad merge.

因此,对于单个产品的每个维护版本,我们都有带有单独分支的存储库.像问题中提出的情况一样,对早期版本的分支所做的所有更改(即该版本中的错误修正)最终都必须全部合并到更高版本的分支中.

So we have repository with separate branches per maintained version of a single product. Like the situation posed in the question, all changes made on a branch of an earlier version (ie. the bugfixes for in that version) must all eventually be merged to the branches of the later versions.

特别是,如果在BRANCH_V8上签入了某些内容,则必须将其合并到BRANCH_V9.

So specifically, if something is checked in on BRANCH_V8, it must be merged to BRANCH_V9.

现在,一名开发人员犯了以下错误:他将BRANCH_V9中的所有更改合并到BRANCH_V8中(即,错误方向的合并).此外,在合并失败之后,他会执行一些额外的提交操作,然后才发现自己的错误.

Now one of the developers makes following mistake : he merges all changes from BRANCH_V9 into BRANCH_V8 (ie. a merge in the wrong direction). Furthermore, after that bad merge he performs some extra commits before he notices his mistake.

因此情况如下图所示.

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
| |

我们可以按以下步骤解决此错误:

We can fix this mistake as follows:

  1. 将您的本地目录更新为BRANCH_V8的最后一个良好状态:hg update 11
  2. 创建一个处于最后良好状态的新子级:
  1. update your local directory to the last good state of BRANCH_V8: hg update 11
  2. Create a new child of that last good state :
  1. 更改某些文件$EDITOR some/file.txt(这是必需的,因为Mercurial不允许空提交)
  2. 提交这些更改hg commit -m "generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9"
    现在的情况如下:
  1. change some file $EDITOR some/file.txt (this is necessary because Mercurial does not allow empty commits)
  2. commit these changes hg commit -m "generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9"
    The situation now looks as follows :

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

  • 将新生成的头部与发生错误合并的修订版本合并,并在提交之前丢弃所有更改. 不要简单地合并两个头,因为那样您将失去在合并之后发生的重要提交!

    1. 合并:hg merge 12(忽略任何冲突)
    2. 放弃所有更改:hg revert -a --no-backup -r 14
    3. 提交更改:hg commit -m "throwing away wrong merge from BRANCH_V9" 现在的情况如下:
    1. merge : hg merge 12 (ignore any conflicts)
    2. throw away all changes : hg revert -a --no-backup -r 14
    3. commit the changes : hg commit -m "throwing away wrong merge from BRANCH_V9" The situtation now looks like :
    
    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的剩余重要提交,在合并后立即发生.

    Ie. there are two heads on BRANCH_V8: one which contains the fix of the bad merge, and the other containing the left-over important commit on BRANCH_V8 which happened right after the merge.

    1. 合并:hg merge
    2. 提交:hg commit -m "merged two heads used to revert from bad merge"
    1. merge : hg merge
    2. commit : hg commit -m "merged two heads used to revert from bad merge"

    现在已更正了BRANCH_V8上的情况,看起来像这样:

    The situation in the end on BRANCH_V8 is now corrected, and looks like this:

    
    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的下一次合并将是不正确的,因为它也将在"fix"中合并为不良合并,我们不希望在BRANCH_V9上合并.这里的技巧是在单独的更改中从BRANCH_V8合并到BRANCH_V9:

    Now the situation on BRANCH_V8 is correct. The only problem remaining is that the next merge from BRANCH_V8 to BRANCH_V9 will be incorrect, as it will merge in the 'fix' for the bad merge as well, which we do not want on BRANCH_V9. The trick here is to merge from BRANCH_V8 to BRANCH_V9 in separate changes :

    • 第一次合并,从BRANCH_V8到BRANCH_V9,是错误合并之前BRANCH_V8的正确更改.
    • 在合并错误及其修复程序中进行第二次合并,并且无需检查任何内容,就放弃所有更改
    • 第三次合并来自BRANCH_V8的其余更改.

    详细信息:

    1. 将工作目录切换到BRANCH_V9:hg update BRANCH_V9
    2. 以BRANCH_V8的最后一个良好状态进行合并(即,您为修复错误合并而生成的提交).此合并是类似于任何常规合并的合并,即.冲突应像往常一样得到解决,没有任何东西要扔掉.
    1. Switch your working directory to BRANCH_V9 : hg update BRANCH_V9
    2. Merge in the last good state of BRANCH_V8 (ie. the commit you generated to fix the bad merge). This merge is a merge like any regular merge, ie. conflicts should be resolved as usual, and nothing needs to be thrown away.
    1. 合并:hg merge 14
    2. 提交:hg commit -m "Merging in last good state of BRANCH_V8" 现在的情况是:
    1. merge : hg merge 14
    2. commit : hg commit -m "Merging in last good state of BRANCH_V8" The situation is now :
    
    @    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及其修复程序上的错误合并,并丢弃所有更改:

  • Merge in the bad merge on BRANCH_V8 + its fix, and throw away all changes :

    1. 合并:hg merge 15
    2. 还原所有更改:hg revert -a --no-backup -r 17
    3. 提交合并:hg commit -m "Merging in bad merge from BRANCH_V8 and its fix and throwing it all away" 现在的情况 :
    1. merge : hg merge 15
    2. revert all changes : hg revert -a --no-backup -r 17
    3. commit the merge : hg commit -m "Merging in bad merge from BRANCH_V8 and its fix and throwing it all away" Current situation :
    
    @    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合并剩余的更改:

  • Merge in the left-over changes from BRANCH_V8 :

    1. 合并:hg merge BRANCH_V8
    2. 提交:hg commit -m "merging changes from BRANCH_V8"
    1. merge : hg merge BRANCH_V8
    2. commit : 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也是正确的.

    After all these steps, in which you do not have to check any diff manually, BRANCH_V8 and BRANCH_V9 are correct, and future merges from BRANCH_V8 to BRANCH_V9 will be correct as well.

    这篇关于在Mercurial上回退合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆