如何取消 Mercurial 中的合并并稍后与该分支重新合并?

发布于 2024-10-01 22:19:22 字数 223 浏览 4 评论 0原文

我有两个分支,default 和branch1。我们团队中的一个人错误地将branch1 与default 合并。 Branch1 中的内容尚未准备好与默认值合并(它包含构建和部署环境的重大修改)。

我们用“hg backout”进行了实验,取消合并(不确定这是正确的方法)。然后,默认情况下会删除branch1 中的更改,这很好,但我们无法与branch1 重新合并。

我们应该如何解决这个问题呢?

I have two branches, default and branch1. By mistake one person in our team merged branch1 with default. The content in branch1 is not yet ready to merge with default (it contains a major rework of the build & deploy environment).

We did an experiment with 'hg backout', backing out the merge (not sure this is the right way to do it). Then the changes from branch1 gets deleted on default, which is fine - but we can not remerge with branch1.

How should we solve this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

五里雾 2024-10-08 22:19:22

这里有很多场景你可能想要这样做,我会将每个场景作为标题,以便你可以找到适合你的场景。请注意,我仍在学习 Mercurial,如果我说错了、使用了错误的术语、可以做得更好等等,我希望得到指点。

没有进一步的更改,合并而不共享(没有推/拉)

程序员已经合并,但没有做任何其他事情,也没有以任何方式与任何人共享更改

在这种情况下,只需丢弃本地克隆,并从安全存储库获取新的克隆。

合并之上的本地更改,而不是共享

程序员已合并,并基于该合并继续工作。应保留合并后的变更集,但应删除合并本身。更改(合并+以下更改集)尚未与任何人共享

在这种情况下,我将执行以下四种操作之一:

  1. 尝试使用 REBASE 扩展,这会将更改集从一个位置移动到另一个位置。如果变更集基于合并时引入的代码更改,则必须执行一些手动工作来协调差异。
  2. 尝试使用 MQ 扩展来拉取要保留到补丁队列中的变更集,然后将它们推回到不同的位置。然而,在基于合并的更改方面,这将具有与 REBASE 扩展相同的问题。
  3. 尝试使用 TRANSPLANT 扩展将更改从一个位置“复制”到另一个位置。尽管如此,仍然存在与前两个​​相同的问题。
  4. 再次进行这项工作,可能需要借助比较工具来获取我想要丢弃的变更集中所做的更改,并在正确的位置重新进行它们。

要摆脱合并变更集+所有以下变更集,有几个选项:

  1. 在 MQ 扩展中使用 strip 命令

    hg strip <合并变更集的哈希值>
    
  2. ,并指定导致合并但不包括合并的变更集的哈希值。本质上,通过从损坏的克隆拉取到新克隆来创建新克隆,并避免拉入您不需要的合并。

    hg 克隆损坏 -r <第一个父级的哈希值>; 。
    hg pull 损坏 -r <第二个父级的哈希值>
    

合并推送给其他人,控制克隆

程序员已推送到主存储库,或其他人,或从程序员存储库中提取的某人。但是,您(如在开发人员组中)可以控制所有存储库,例如,您可以在完成更多工作之前与每个人联系和交谈

在这种情况下,我会看看步骤 1 或 2 是否可以可以做,但是可能需要在很多地方做,所以这可能涉及很多工作。

如果没有人完成基于合并变更集的工作,我将使用步骤 1 或 2 进行清理,然后推送到主存储库,并要求每个人从主存储库获取新的克隆。

合并推送,你无法控制克隆

程序员推送了合并集,你不知道谁将拥有合并变更集。换句话说,如果您成功地从您的存储库中根除它,那么仍然拥有它的人的杂散推送会将其带回来。

忽略合并变更集并在两个分支中工作,如下所示尽管这从未发生过。这将留下一个悬空的头。稍后,当您合并两个分支时,您可以对该头进行空合并以摆脱它。

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

只需继续在两个分支中工作:

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

然后合并这两个分支,即您想要的真正合并:

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

然后您可以进行空合并以摆脱悬空的头。不幸的是,除了通过 TortoiseHg 之外,我不知道如何做到这一点。它有一个复选框,我可以在其中放弃其中一个分支的更改。

使用TortoiseHg,我将更新到我想要保留的合并(最上面的小写m),然后选择并右键单击下面悬空的合并头,然后选中“放弃合并目标(其他)修订版的所有更改” :
放弃目标的更改

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.

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. 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. This will, however, have the same problem as the REBASE extension in terms of changes based on the merge
  3. Try to use the TRANSPLANT extension to "copy" the changes from one location to another. 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

    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.

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.

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. 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":
discard changes from target

灼痛 2024-10-08 22:19:22

我们用“hg backout”进行了实验,取消合并(不确定这是正确的方法)。然后,默认情况下会删除branch1 中的更改,这很好 - 但我们无法与branch1 重新合并。

我使用 backout 来取消合并。您不能重新合并,但您可以“取消取消合并”,即当您想要重新合并时,您可以在“取消合并变更集...”提交上进行“hg backout”,然后再次合并分支。

例子:

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

We did an experiment with 'hg backout', backing out the merge (not sure this is the right way to do it). Then the changes from branch1 gets deleted on default, which is fine - but we can not remerge with branch1.

I use backout for merge cancel. You can not remerge, but you able to "backout backout merge", i.e. when you want remerge, you make 'hg backout' on "Backed out merge changeset ..." commit and then merge branch again.

Example:

  7     M       remerge
  6   /   \
  5   *   |     hg backout 3 (backout backout)
  4   |   *     fix error 
  3   *   |     hg backout 2
  2   M   |     fail merge
    /     \
  1 *     *
    |     |
漫漫岁月 2024-10-08 22:19:22

感谢大家的宝贵意见!由于我们急于解决问题,而且我们的团队对 Mercurial 还比较陌生,因此我们使用了一个非常务实的解决方案。

在我们的存储库服务器上,我们创建了一个新存储库,然后克隆旧存储库,直到合并之前的修订版。然后将新克隆推送到服务器,并将新链接发送给所有人。幸运的是,我们是一个很小的开发团队。

也许不是解决问题的最简洁的方法,但它有效:)

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.

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

柏林苍穹下 2024-10-08 22:19:22

你无法真正很好地撤销合并。 IMO,处理这个问题的最佳方法就是放弃合并并继续合并之前的变更集链,留下一个悬空的头(可以剥离)。如果合并后发生了其他变化,它们可以重新基于新的“好”头。

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). If other changes have happened since the merge, they can be rebased onto the new "good" head.

清旖 2024-10-08 22:19:22

此答案假设您已经推送了

这将导致(至少一个)未解决的问题,具体取决于您刚刚忘记的内容。更多取决于谁刚刚从哪个分支推送。

我喜欢 HG 并热衷于使用它,但是当他们的分支想法与(按设计)故意不可变的历史相结合时,可能会让某人抓狂。

出于这个原因,我通常在进行分支合并之前克隆存储库的备份(本地)。我总是在拉之前检查一下。

Eric Raymond 正在研究,它或多或少与 DVCS 无关,可以(希望)提供帮助情况就像你所描述的那样,但我认为他在接下来的一两周内不会完全实现 HG 支持。尽管如此,它可能还是值得一看的。

但是,只有在没有人使用“ooopsie”提示的情况下才有用。

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.

I usually clone a backup (locally) of the repo prior to doing a branch merge, for just this reason. 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. Still, it might be worth watching.

But, only useful if nobody has pulled the 'ooopsie' tip.

沧笙踏歌 2024-10-08 22:19:22

我有这个确切的问题。一位同事意外地将我的分支合并到默认分支中,而它仍然不完整。最初,我只是取消了合并,这似乎工作正常,直到我想将我的分支合并到默认分支中以进行保存。我需要的文件在合并时被标记为删除。

解决方案是一路回到我最初的退出,修复了我同事的错误,然后退出那个退出。这阻止了文件被标记为已删除,并让我成功地将我的分支合并到默认分支。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文