Mercurial合并策略与Git合并策略

7
我已经使用git好几年了,最近为了某个项目切换到了Mercurial。过去6个月里,我通过命令行学会了如何使用Mercurial。
可能只是我的想象,但是我觉得Mercurial在合并方面要差得多,并且导致的冲突文件更多。我经常将默认分支合并到我的特性分支中,有时它会做一些非常奇怪的事情,并且无法自动合并看起来应该可以视觉上很好地合并的文件 - 例如,在同一行上没有更改等等。
我已经做了相当多的研究,看看合并算法可能有什么不同,但运气不佳。大多数文章都是人们关于git和Mercurial工作原理的观点和信息,而没有太多关注合并算法本身以及差异的平实语言示例。
我总是使用良好的合并策略,并沿着树向上合并,而且从不在合并到默认(hg)/主管(git)分支之前向下合并到远程,以确保没有冲突。
到目前为止,我在研究中发现:
1)Mercurial不能合并或存在与多个父项合并的问题。我不确定有人会处于这种情况,但也许这很常见?
这是真的吗?这会在日常开发中更经常地导致合并冲突吗?
2)Mercurial不支持章鱼合并,而Git支持。
对于章鱼合并,我说“谁在乎!”这不是必要的。
除此之外,合并算法似乎同等创建?是否有可能改变合并算法?是否有任何很好的文章介绍这个问题?
如果您发布像k3diff、p4merge和meld这样的合并工具的信息,您将错过重点 - 我想了解冲突解决之前的自动合并策略的信息。
感谢任何有用的参考和/或信息!

1
你的#1和#2有什么不同?合并多个父节点的操作称为八爪鱼合并。 - max630
你能提供一些例子吗? - max630
1
@max630:我非常确定他的意思是“多个合并基地”,而不是“多个父节点”,这是我在我的回答中解决的问题。 - torek
有趣话题上的好问题。 - ryanwc
我发现关注行尾、自动格式化和空格很重要。从考虑你的IDE到操作系统,都可能影响git程序对字面数据的解释。我建议针对Mac程序、Windows程序和多OS软件项目采取不同的步骤。例如,在Mac和Windows之间共享的项目上,Git的auto-crlf设置=true效果不佳。自此发布以来,我并没有切换回Mercurial进行类似问题或首选项选项的分析。 - TheJeff
1个回答

12
1)Mercurial无法合并或存在与多个父级合并的问题。我不确定某人是如何陷入这种情况的,但也许这很常见吗?这是真的吗?在日常开发中,这会更经常导致合并冲突吗?
不是真的——至少不是宣称的那样,这似乎有点毫无意义。
进行基于提交图的合并时,底层问题涉及找到最低公共祖先或LCA。在中,总是有单一的LCA,因此在三方合并中它是明显的输入:它是通常基础提交、左侧/本地/ --ours提交、右侧/远程/ --theirs操作的基础。
然而,在提交DAG中,可能会有多个LCA节点。Mercurial的默认解决方案是任选一个。Git的默认解决方案是选择所有并合并它们,使用-s recursive策略。这个“内部”合并结果是一个单一的最终提交,Git然后使用它作为合并基础。您可以使用-s resolve覆盖此操作以执行与Mercurial相同的操作:任选一个,然后将其用作基础。
Mercurial有数个实验性的替代合并策略(例如,BidMerge),但没有像Git的四个-s策略一样“开箱即用”。多重合并基点主要发生在某人执行“交叉合并”时。参见How do criss-cross merges arise in Git?。在某些工作流中,这绝对不会发生,而实际上这并不常见。即使没有八爪鱼合并,任何八爪鱼合并都可以模拟成一系列成对合并。它们特别适合炫耀。因为Mercurial和Git使用不同的算法来跟踪文件名,所以它们的合并算法并不相同。问题在于:一旦你拥有三个三向合并的输入,谁说基本中的文件路径/ f就是左侧的path2 / f2和/或右侧的path3 / f3中的相同文件?我们应该将哪些文件配对或者如我所说的“识别”它们?
Mercurial通过跟踪清单和记录的目录操作(记录重命名或复制)来跟踪文件标识,而Git则通过内容匹配动态确定文件标识。然而,完全的动态确定在计算上太昂贵了,所以Git会作弊:如果两个文件在base-vs-left或base-vs-right中具有相同的路径,则将这两个文件标识为“相同”的文件。这只留下没有配对的路径名称可以动态识别。
还必须处理哪个路径名在最终结果中使用。在此处,Mercurial让您在合并命令运行时选择,而Git只是将所有名称塞入其索引中,允许稍后延迟选择名称。
但是,一旦适当地标识和命名,合并过程本身就是相同的:找出哪一方更改了哪些文件。如果只有一方更改了一个文件,则使用该方的版本。否则,在三个输入上执行文件级合并(Git在内部称之为低级合并)。这需要计算差异或遵循并组合单个变更集,并且Git和Mercurial都选择直接的“diff base against tip”方法。(由于Git始终存储快照,因此它有点被迫这样做。Mercurial有时存储快照,因此它也有点被迫这样做。)它们的内部差异引擎也不完全相同,因此这也可能产生略有不同的结果。
“是否可以更改合并算法?有没有关于此的好文章?”
是的:Git具有-s参数,而Mercurial在内部全部可插拔。
不,据我所知没有。我正在撰写一本书籍,虽然最近没有积极地在写作,因为有了其他的工作,而且这本书并不是专门针对这个问题的;但理论章节(至少在某种程度上已经完成)提供了适当的背景。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接