【问题标题】:How can I back out a merge in Mercurial and later remerge with that branch?如何退出 Mercurial 中的合并,然后与该分支重新合并?
【发布时间】:2011-05-08 08:07:36
【问题描述】:

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

我们对“hg backout”进行了实验,取消了合并(不确定这是正确的方法)。然后分支 1 的更改默认被删除,这很好 - 但我们不能与分支 1 重新合并。

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

【问题讨论】:

  • 是否已推送合并,现在已对很多人公开,或者您是否已将损坏包含在可控的存储库列表中?
  • 我不想这么说,但除非没人拉,否则你不能说。
  • 不幸的是,合并被推送到公共存储库,在我们进行任何更改以恢复它之前,有几个人将其撤消。
  • 你不能这样做的想法对我来说似乎很疯狂。您可以从字面上将一个位置的文件复制到另一个位置并提交为新的更改。问题是,这是唯一的方法。

标签: version-control mercurial dvcs


【解决方案1】:

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

没有进一步的变化,合并不共享(没有推/拉)

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

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

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

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

在这种情况下,我会选择以下四种方法之一:

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

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

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

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

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

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

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

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

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

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

程序员推送了mergeset,而你不知道谁将拥有merge changeset。换句话说,如果您成功地将其从您的存储库中根除,那么仍然拥有它的人的误推会将其带回来。

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

  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),然后选择并右键单击下面悬空的合并头,然后选中“放弃合并目标中的所有更改(其他) 修订”:

【讨论】:

  • 你的 HG fu 很强大.. 除了非手绘圆圈之外,你还有 ascii 图表(因此 +1),但图表和圆圈与此无关:)
  • answer #439790 of question #7476481中提到的,期间丢弃更改的方法是:hg merge 4 --tool internal:local
  • 我很长时间以来在 SO 上看到的最彻底的答案。 :)
  • 另一个让我想到这个问题的场景——你已经运行了hg merge,但在你真正提交之前就意识到了你的错误。在这种情况下来自hg merge --help hg update --clean . 做你想做的事
  • This question 解释了如何在命令行上复制 TortoiseHg 的行为。
【解决方案2】:

我们对“hg backout”进行了实验,取消了合并(不确定这是正确的方法)。然后分支 1 的更改默认被删除,这很好 - 但我们不能与分支 1 重新合并。

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

例子:

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

【讨论】:

  • 这看起来很有希望。正是我需要的!我会测试它。
  • 不起作用:“中止:无法退出合并变更集”
  • 是的,它不再起作用了,在最新的 mercurial 版本中禁用了合并提交的回退,我不知道为什么
  • @KonstantinVdovkin 谢谢,这对我有用——“退出合并”!关于您之前的评论,我使用此处的分辨率进行了第一次合并回退:patchwork.mercurial-scm.org/patch/10699
【解决方案3】:

感谢大家的大力投入!由于我们有点急于解决问题,而且我们的团队对 Mercurial 还比较陌生,所以我们使用了一个非常务实的解决方案。

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

也许不是解决问题的最直接的方法,但它确实有效:)

【讨论】:

  • 这不应该被标记为答案,Lasse V. Karlsen 的回应应该是。
  • 当时我们不是这样解决的,但我同意。 Lasses 解决方案是正确的。
【解决方案4】:

您不能真正很好地退出合并。 IMO,处理这个问题的最好方法就是放弃合并并继续合并之前的变更集链,留下一个悬空的头(可以被剥离)。如果合并后发生了其他更改,则可以将它们重新定位到新的“好”头部。

【讨论】:

    【解决方案5】:

    这个答案假设你已经推送了

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

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

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

    Eric Raymond is working on something 或多或少与 DVCS 无关,可以(希望)在您描述的糟糕情况下提供帮助,但我认为他不会在接下来的一两周内完全实施 HG 支持。不过,它可能值得一看。

    但是,只有在没有人提出“ooopsie”提示时才有用。

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-26
        • 2010-09-08
        • 1970-01-01
        • 1970-01-01
        • 2010-09-20
        • 2012-02-07
        • 1970-01-01
        相关资源
        最近更新 更多