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

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

我做了很多研究,看看 merge 算法中可能有什么不同,但运气不佳。大多数文章都是关于 git 和 mercurial 如何在幕后工作的人们的意见和信息,并没有过多关注 merge 算法本身和优点/缺点以及差异的简单语言示例。

我总是使用良好的 merge 策略并通过树向上 merge ,并且从不向下 merge 到 default(hg)/master(git) 分支而不先 merge 到远程以确保没有冲突。

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

1) Mercurial 无法 merge 或在与多个父级 merge 时出现问题。我不确定某人如何最终处于这种情况,但也许这很常见?

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

2) Mercurial 不支持八达通 merge ,而 git 支持。

对于 Octopus merge ,我说“谁在乎!”,这不是必需的。

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

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

感谢您提供任何有用的引用资料和/或信息!

最佳答案



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

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

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

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

多个 merge 基地主要发生在某人进行“交叉 merge ”时。请参阅 How do criss-cross merges arise in Git? 在某些工作流程中,这种情况永远不会发生,而且在实践中并不常见。



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



不,因为 Mercurial 和 Git 使用不同的算法来跟踪文件名。这里的问题是:一旦你有了三路 merge 的三个输入,谁说基础中的文件 path/to/f 与左侧的 path2/f2 和/或右侧的 path3/f3 是同一个文件?我们应该配对哪些文件,或者按照我的喜好称呼它?

Mercurial 对此的回答是通过 list 和记录的目录操作(记录的重命名或副本)跟踪文件身份,而 Git 是通过内容匹配动态确定文件身份。但是,完全动态确定的计算量太大,因此Git会作弊:如果两个文件的base-vs-left或base-vs-right路径相同,则将这两个文件标识为“相同”文件。这仅留下没有配对的路径名来动态识别。

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

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



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

不,据我所知。我正在研究 book ,除了这些天我没有积极工作,有一份不同的工作,而且它并不是专门针对这些的;但是理论章节(至少有点接近完成)给出了适当的背景。

10-08 00:29