简体   繁体   English

如何在Mercurial中退出合并,然后再与该分支重新合并?

[英]How can I back out a merge in Mercurial and later remerge with that branch?

I have two branches, default and branch1. 我有两个分支,默认和branch1。 By mistake one person in our team merged branch1 with default. 我们团队中的一个人错误地将branch1合并。 The content in branch1 is not yet ready to merge with default (it contains a major rework of the build & deploy environment). branch1中的内容尚未准备好与默认值合并(它包含构建和部署环境的主要返工)。

We did an experiment with 'hg backout', backing out the merge (not sure this is the right way to do it). 我们做了'hg backout'的实验,退出合并(不确定这是正确的方法)。 Then the changes from branch1 gets deleted on default, which is fine - but we can not remerge with branch1. 然后从默认情况下删除branch1中的更改​​,这很好 - 但我们不能使用branch1重新合并。

How should we solve this issue? 我们该如何解决这个问题?

There are many scenarios here where you might want to do this, I'll make each scenario a headline, so that you can find the scenario that fits your case. 在这里有许多场景你可能想要这样做,我将使每个场景成为标题,以便您可以找到适合您情况的场景。 Note that I'm still learning Mercurial, and I'd like pointers if something I say is wrong, using the wrong terminology, could be done better, etc. 请注意,我仍然在学习Mercurial,如果我说错了,使用错误的术语,可以做得更好等,我想指点一下。

No further changes, merge not shared (no pushes/pulls) 没有进一步的更改,合并不共享(没有推/拉)

The programmer has merged, but not done anything else, nor has (s)he shared the changes with anyone, in any way 程序员已合并,但没有做任何其他事情,也没有以任何方式与任何人分享变更

In this case, simply discard the local clone, and get a fresh clone from a safe repository. 在这种情况下,只需丢弃本地克隆,并从安全存储库中获取新的克隆。

Local changes on top of merge, not shared 合并之上的本地更改,而不是共享

The programmer has merged, and continued working based on that merge. 程序员已合并,并继续基于该合并工作。 The changesets that followed the merge should be kept, but the merge itself should be removed. 应保留合并后的更改集,但应删除合并本身。 The changes (merge + following changesets) have not been shared with anyone 尚未与任何人共享更改(合并+以下更改集)

In this case I would do one of four: 在这种情况下,我会做四个中的一个:

  1. Try to use the REBASE extension, this will move the changesets from one location to another. 尝试使用REBASE扩展,这会将更改集从一个位置移动到另一个位置。 If the changesets are based on code-changes that were introduced with the merge, some manual work must be done to reconcile the differences. 如果更改集基于合并引入的代码更改,则必须执行一些手动工作以协调差异。
  2. Try to use the MQ extension to pull the changesets that are to be kept into a patch-queue, then push them back in a different location. 尝试使用MQ扩展来将要保留的变更集拉入补丁队列,然后将它们推回到不同的位置。 This will, however, have the same problem as the REBASE extension in terms of changes based on the merge 但是,就基于合并的更改而言,这将与REBASE扩展具有相同的问题
  3. Try to use the TRANSPLANT extension to "copy" the changes from one location to another. 尝试使用TRANSPLANT扩展程序将更改从一个位置“复制”到另一个位置。 Still, same problem exists as with the first two. 仍然存在与前两个​​相同的问题。
  4. Do the work again, probably with the help of a diffing tool to take changes done in the changesets I want to discard, and re-do them in the correct location. 再次完成工作,可能借助于变换工具在我想要丢弃的变更集中进行更改,并在正确的位置重新执行。

To get rid of the merge changeset + all the following changesets, there's a couple of options: 要摆脱合并变更集+所有以下变更集,有几个选项:

  1. Use the strip command in the MQ extension 在MQ扩展中使用strip命令

     hg strip <hash of merge changeset> 
  2. Clone and pull, and specify the hash of the changesets leading up to, but not including the merge. 克隆和拉取,并指定导致但不包括合并的变更集的哈希值。 In essence, create a new clone by pulling from the damaged clone into a new one, and avoid pulling in the merge you don't want. 实质上,通过从受损的克隆中拉出一个新的克隆来创建一个新的克隆,并避免拉入你不想要的合并。

     hg clone damaged -r <hash of first parent> . hg pull damaged -r <hash of second parent> 

Merge pushed to others, control over clones 合并推送给其他人,控制克隆

The programmer has pushed to master repository, or to someone else, or someone pulled from the programmers repository. 程序员已经推送到主存储库,或推送给其他人,或从程序员库中取出的人。 However, you (as in the group of developers) have control over all the repositories, as in, you can contact and talk to everyone before more work is done 但是,您(如在开发人员组中)可以控制所有存储库,因为在更多工作完成之前,您可以联系并与所有人交谈

In this case, I would see if step 1 or 2 could be done, but it might have to be done in a lot of places, so this might involve a lot of work. 在这种情况下,我会看到步骤1或2是否可以完成,但可能必须在很多地方完成,所以这可能涉及很多工作。

If nobody has done work based on the merge changeset, I would use step 1 or 2 to clean up, then push to the master repository, and ask everyone to get a fresh clone from the master repository. 如果没有人根据合并变更集完成工作,我会使用步骤1或2进行清理,然后推送到主存储库,并要求每个人从主存储库中获取新的克隆。

Merge pushed, you don't have control over clones 合并推送,您无法控制克隆

The programmer pushed the mergeset, and you don't know who will have the merge changeset. 程序员推动了合并集,你不知道谁将拥有合并变更集。 In other words, if you succeed in eradicating it from your repositories, a stray push from someone who still has it will bring it back. 换句话说,如果你成功地从你的知识库中消除了它,那些仍然拥有它的人的偏离推动会把它带回来。

Ignore the merge changeset and work in the two branches as though it never happened. 忽略合并变更集并在两个分支中工作,就好像它从未发生过一样。 This will leave a dangling head. 这将留下一个悬垂的头。 You can then later, when you've merged the two branches, do a null-merge for this head to get rid of it. 稍后,当你合并了两个分支时,可以为这个头做一个空合并来摆脱它。

  M         <-- this is the one you want to disregard
 / \
*   *
|   |
*   *
|   |

Simply continue working in the two branches: 只需继续在两个分支机构工作:

|   |
*   *
| M |       <-- this is the one you want to disregard
|/ \|
*   *
|   |
*   *
|   |

Then later you merge the two, the real merge you want: 然后你合并两个,你想要的真正的合并:

  m
 / \
*   *
|   |
*   *
| M |       <-- this is the one you want to disregard
|/ \|
*   *
|   |
*   *
|   |

You can then do a null-merge to get rid of the dangling head. 然后你可以做一个空合并来摆脱悬空头。 Unfortunately I don't know how to do that except through TortoiseHg. 不幸的是,除了通过TortoiseHg,我不知道怎么做。 It has a checkbox where I can discard the changes from one of the branches. 它有一个复选框,我可以从其中一个分支丢弃更改。

With TortoiseHg, I would update to the merge I want to keep (the topmost, lowercase m), then select and right-click on the dangling merge head below, and then check the "Discard all changes from merge target (other) revision": 使用TortoiseHg,我会更新到我想要保留的合并(最上面的小写m),然后选择并右键单击下面的悬空合并头,然后选中“放弃合并目标(其他)修订版中的所有更改” : 丢弃目标的变化

We did an experiment with 'hg backout', backing out the merge (not sure this is the right way to do it). 我们做了'hg backout'的实验,退出合并(不确定这是正确的方法)。 Then the changes from branch1 gets deleted on default, which is fine - but we can not remerge with branch1. 然后从默认情况下删除branch1中的更改​​,这很好 - 但我们不能使用branch1重新合并。

I use backout for merge cancel. 我使用backout进行合并取消。 You can not remerge, but you able to "backout backout merge", ie when you want remerge, you make 'hg backout' on "Backed out merge changeset ..." commit and then merge branch again. 你不能重新合并,但你能够“退出退出合并”,即当你想要重新合并时,你在“支持合并变更集...”提交上做“hg backout”,然后再次合并分支。

Example: 例:

  7     M       remerge
  6   /   \
  5   *   |     hg backout 3 (backout backout)
  4   |   *     fix error 
  3   *   |     hg backout 2
  2   M   |     fail merge
    /     \
  1 *     *
    |     |

Thanks to everyone for the great input! 感谢大家的大力投入! Since we were kind of in a rush to solve the problem, and our group is relatively new to Mercurial, we used a very pragmatic solution. 由于我们急于解决问题,而且我们的团队对Mercurial来说相对较新,我们使用了非常实用的解决方案。

On our repository server we created a new repository, then we cloned the old repository up until the revision right before the merge. 在我们的存储库服务器上,我们创建了一个新的存储库,然后我们克隆了旧的存储库,直到合并之前的版本。 Then pushed the new clone to the server and sent out the new link to everyone. 然后将新克隆推送到服务器并向所有人发送新链接。 Luckily we are a quite small development team. 幸运的是,我们是一个非常小的开发团队。

Perhaps not the most cosher way to solve the problem, but it worked :) 也许不是解决问题最合适的方式,但它有效:)

I had this exact issue. 我有这个问题。 A coworker accidentally merged my branch into the default branch while it was still incomplete. 当同事仍然不完整时,同事意外地将我的分支合并到默认分支。 Initially I just backed out that merge which seemed to work fine until I wanted to merge my branch into default for keeps. 最初我刚刚退出合并,这似乎工作正常,直到我想将我的分支合并为默认保持。 Files that I needed were being marked for deletion upon merging. 我需要的文件在合并时被标记为删除。

The solution was to go all the way back to my original back out that fixed my coworker's mistake and back out that back out. 解决方案是一直回到我的原始退出,修复了我的同事的错误,然后退出了。 This stopped the files from being marked as deleted and let me successfully merge my branch into default. 这会阻止文件被标记为已删除,让我成功将我的分支合并为默认值。

You cannot really backout a merge nicely. 你不能真的很好地退出合并。 IMO, the best way to handle this would be just to abandon the merge and continue the strand of changesets from before the merge, leaving a dangling head (which can be stripped). IMO,处理这个问题的最好方法就是放弃合并并继续合并之前的变更集,留下一个悬空的头(可以剥离)。 If other changes have happened since the merge, they can be rebased onto the new "good" head. 如果自合并以来发生了其他变化,他们可以重新定位到新的“好”头上。

This answer assumes that you have already pushed 这个答案假定你已经推了

This would result in (at least one) unresolved head, depending on what you just forgot. 这将导致(至少一个)未解决的头部,这取决于您刚忘记的内容。 More depending on who just pushed from what branch. 更多取决于谁从什么分支推出。

I love HG and use it avidly, but their idea of a branch can drive someone batty when coupled with a history that is (by design) intentionally immutable. 我喜欢HG并且热衷于使用它,但是他们对分支的想法可以在与(通过设计)故意不可变的历史相结合的情况下驱动某人。

I usually clone a backup (locally) of the repo prior to doing a branch merge, for just this reason. 出于这个原因,我通常在进行分支合并之前克隆repo的备份(本地)。 I always check before pulling. 我总是在拉前检查。

Eric Raymond is working on something that is more or less DVCS agnostic that can (hopefully) help in situations just like the oops you described, but I don't think he's going to have HG support fully implemented for another week or two. Eric Raymond 正在开发一种或多或少与DVCS无关的东西,可以(希望)帮助你所描述的oops,但我认为他不会在一两周内完全实现HG支持。 Still, it might be worth watching. 不过,它可能值得一看。

But, only useful if nobody has pulled the 'ooopsie' tip. 但是,只有在没有人拉出'ooopsie'小费的情况下才有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM