【问题标题】:Mercurial merge strategy vs Git merge strategyMercurial 合并策略与 Git 合并策略
【发布时间】:2018-09-08 16:25:57
【问题描述】:

我已经使用 git 多年了,最近为了一个项目改用 mercurial。在过去的 6 个月里,我已经通过命令行很好地学会了如何使用 Mercurial。

这可能是我的想象,但在我看来,mercurial 在合并方面要差得多,并且会导致更多冲突的文件。我会经常将默认分支合并到我的功能分支中,它有时会做一些非常时髦的事情,并且无法自动合并看起来应该在视觉上很好地合并的文件 - I.E.同一行等没有变化。

我已经进行了大量研究,以了解合并算法中可能存在的差异,但运气不佳。大多数文章都是人们关于 git 和 mercurial 如何在幕后工作的观点和信息,而没有过多关注合并算法本身以及优点/缺点以及差异的简单语言示例。

我总是使用良好的合并策略并通过树向上合并,并且在没有先合并到远程以确保没有冲突的情况下永远不会向下进入 default(hg)/master(git) 分支。

到目前为止,我在研究中发现的是:

1) Mercurial 无法合并或存在与多个父级合并的问题。我不确定有人会如何陷入这种情况,但也许这很常见?

这是真的吗?这会在日常开发中更频繁地导致合并冲突吗?

2) Mercurial 不支持章鱼合并,而 git 支持。

对于章鱼合并,我说“谁在乎!”,这不是必需的。

除此之外,似乎合并算法是平等创建的?是否可以更改合并算法?有没有这方面的好文章?

如果您发布有关 k3diff、p4merge 和 meld 等合并工具的信息,那么您就没有抓住重点 - 我想要在解决冲突之前获得有关自动合并策略的信息。

感谢您提供任何有用的参考和/或信息!

【问题讨论】:

  • 您的#1 与#2 有何不同?与多个父母合并是章鱼合并。
  • 你能提供一些例子吗?
  • @max630:我很确定他在第 1 项中的意思是“多个合并基础”,而不是“多个父母”(这就是我在回答中提到的)。
  • 关于一个有趣话题的好问题。
  • 我发现注意行尾、自动格式化和空格很重要。从考虑你的 IDE 到你的操作系统,到处都会影响 git 程序对文字数据的解释。我会为 mac 程序、windows 程序和多操作系统软件项目推荐不同的步骤。例如,Git 的 auto-crlf 设置 = true 在 mac 和 windows 之间共享的项目上效果不佳。自从这篇文章以来,我还没有切换回 mercurial 来分析类似的问题或偏好选项。

标签: git merge mercurial


【解决方案1】:

1) Mercurial 无法合并或存在与多个父级合并的问题。我不确定有人会如何陷入这种情况,但也许这很常见?

这是真的吗?这会在日常开发中更频繁地导致合并冲突吗?

不,这不是真的——至少像声称的那样,这似乎有点毫无意义。

进行基于提交图的合并的根本问题与找到Lowest Common Ancestor or LCA 有关。在树中,总是有一个 LCA,所以它是三路合并的明显输入:它是通常的基本提交中的基础,左侧/本地/--ours 提交,右侧/远程/--theirs 操作。

然而,在一个提交 DAG 中,可能有多个 LCA 节点。 Mercurial 对此的默认解决方案是或多或少任意选择一个。 Git 的默认解决方案是使用-s recursive 策略选择all 并合并它们。这种“内部”合并会产生一个最终提交,然后 Git 将其用作合并基础。您可以覆盖它以执行 Mercurial 使用 -s resolve 执行的相同操作:或多或少任意选择一个,并将其用作基础。

Mercurial 有几个实验性的替代合并策略(参见,例如,BidMerge),但没有一个是“开箱即用”的,这与 Git 的四个 -s 策略不同。

多个合并基础主要发生在某人进行“交叉合并”时。请参阅How do criss-cross merges arise in Git? 在某些工作流程中,这应该永远不会发生,而在实践中它并不那么普遍。

2) Mercurial 不支持章鱼合并,而 git 支持。

对于章鱼合并,我说“谁在乎!”,这不是必需的。

没错。任何章鱼合并都可以通过一系列成对合并来模拟。不过,它们特别适合炫耀。 :-)

除此之外,似乎合并算法是平等创建的?

不,因为 Mercurial 和 Git 使用不同的算法来跟踪文件名。这里的问题是:一旦你有了三路合并的三个输入,谁说 base 中的文件 path/to/f 与 @987654331 是 same 文件@ 在左侧和/或 path3/f3 在右侧?我们应该配对哪些文件,或者识别我喜欢这样称呼它?

Mercurial 对此的回答是通过 manifest 和记录的目录操作(记录的重命名或复制)跟踪文件身份,而 Git 的回答是通过内容匹配动态确定文件身份。但是,完全动态确定在计算上过于昂贵,因此 Git 作弊:如果两个文件在 base-vs-left 或 base-vs-right 中具有 same 路径,则将这两个文件标识为“相同” “ 文件。这只会留下没有配对的路径名来动态识别。

还必须处理在最终结果中使用哪个路径名。在这里,Mercurial 让您在合并命令运行时进行选择,而 Git 只是将 所有 名称填充到其索引中,从而允许之后延迟名称选择。

不过,一旦正确识别和命名,合并过程本身是相同的:找出哪一方更改了哪个文件。如果只有一方更改了文件,请使用该方的版本。否则,对三个输入进行 文件级别 合并(Git 在内部将此称为 低级别 合并)。这需要计算差异或跟踪和组合单个变更集,Git 和 Mercurial 都选择直接的“diff base against tip”方法。 (因为 Git 总是存储快照,所以这种方式有点强制。Mercurial 有时 存储快照,所以它也是强制的。)不过,它们的内部差异引擎也不相同,所以这也可以产生一些不同的结果。

是否可以更改合并算法?有没有这方面的好文章?

是的:Git 有 -s 参数,Mercurial 内部都是可插拔的。

没有,据我所知。我正在为book 工作,除了这些天我没有积极地工作,从事不同的工作,而且不是专门针对这些;但是理论章节(至少在某种程度上接近完成)给出了适当的背景。

【讨论】:

    猜你喜欢
    • 2020-11-21
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多