在它出现之前,我已经看过关于这个主题的几个主题,包括:
我正在寻找为我们的开发小组切换到Mercurial(来自Subversion)。在我这样做之前,我正在做通常的利弊列表。
我的“专业人士”之一是Mercurial的合并优势,但到目前为止,我没有找到令人信服的证据。也就是说,我在HgInit.com上发表声明,我无法核实:
例如,如果我稍微更改一个函数,然后将其移动到其他地方,Subversion就不会真正记住这些步骤,所以当合并时,它可能会认为新功能刚刚出现蓝色Mercurial会分别记住这些事情:函数已更改,函数已移动,这意味着如果您稍微更改了该函数,则Mercurial更有可能成功合并我们的更改。
这将是非常引人注目的功能,但据我所知,这只是热空气。我一直无法验证上述声明。
我创建了一个Mercurial存储库,创建了一个Hello World,然后克隆了它。在一个我修改了函数,提交它然后移动它,然后提交它。在另一个中,我只是在函数中添加了另一个输出行并提交了。
当我合并时,我会得到与使用Subversion相同的合并冲突。
我认为mercurial可以更好地跟踪file renames并且除了合并之外DVCS还有其他优势,但我对这个例子很感兴趣。乔尔斯波尔斯基在这里偏离基地,还是我错过了什么?
我在这方面没有经验,但看起来确实如此,因为Mercurial保留了更多的信息,理论上它可以在合并方面做得更好(如果开发人员也经常进行检查)。例如,我认为Mercurial可以通过比较多个更改来获取上下文更改,例如,我修改函数,签入,移动函数,签入,以及Mercurial将这两个部分关联起来。
但是,Mercurial的合并似乎并没有真正利用添加的信息,并且看起来与Subversion的运行方式相同。这是对的吗?
答案 0 :(得分:6)
据我所知,任何说Mercurial跟踪代码文件大小不足的人都是错误的。它 跟踪文件重命名独立于代码更改,因此如果Dave重命名文件并且Helen更改了文件中的内容,它可以自动执行此操作,但据我所知,Subversion也可以这样做! (CVS不能。)
但是是一种Mercurial的合并逻辑比Subversion更好的方式:它记住冲突解决方案。考虑一下这段历史图:
base ---> HELEN1 ---> merge1 --> HELEN2 -> merge2
\--> DAVE1 ---/ /
\--> DAVE2 ---------/
海伦和戴夫独立做出改变。海伦拉着戴夫的树并合并,然后又做了另一个改变。与此同时,戴夫继续编码而没有费心去海伦。然后海伦又拉了戴夫的树。 (也许Dave正在开发主干开发,Helen关闭了一个功能分支,但她希望定期与主干更改同步。)构建“merge2”时,Mercurial会记住在“merge1”中完成的所有冲突解决方案并且只显示Helen new 冲突,但是Subversion会让Helen从头开始重新合并。 (有些方法可以避免使用Subversion,但它们都涉及额外的手动步骤.Mercurial会为您处理它。)
有关更多信息,请阅读为Merotial和Git现在使用为Monotone和AFAIK开发的mark-merge algorithm。
答案 1 :(得分:1)
AFAIK,SVN在内部进行所有合并 - 合并工具只适用于存在冲突的情况,因为(显然)它需要告诉您并让您解决它。
非冲突案例基于应用补丁 - 即,svn将采取您在修订中所做的更改,并将这些更改应用于目标。 SVN的最新版本(自1.5起)记住了您之前执行的合并,将此信息存储在与目录关联的属性中。与1.5相比,1.6在处理这些属性方面做得更好。
SVN通过比较2个树并对它们进行差异来进行不合并 - see the book - 除非要合并的树不相关,否则它将执行diff-type合并操作(或者指定--ignore-ancestry选项)。发生了什么Here's a brief description。 您可以在合并过去的冲突时看到这一点 - 一旦您解决了棘手的修订合并,svn会记住合并了哪些修订并将再次应用这些更改。你可以通过尝试来证明这一点 - 分支,编辑2个文件,合并以获得冲突。仅在同一行上编辑分支文件,然后合并 - 即使目标文件未更改,它也会弹出冲突,但是因为合并正在对已从分支文件预期更改的行应用更改(即就像补丁一样,显示它认为它将要改变的线应该是什么)。实际上,您没有看到这一点,因为您不会反复拒绝合并更改。
然而,SVN在重命名文件方面表现不佳,因为它将它们跟踪为删除+添加操作。其他SCM做得更好 - 但即使他们也无法确定文件是否被重命名,或者是否被删除和添加,尤其是当该文件也被修改时。 Git使用一些启发式方法来尝试确定这一点,但我看不出它能保证成功。在我们有一个挂钩到文件系统的SCM之前,我认为情况仍然如此。
答案 2 :(得分:1)
两件事:
Mercurial确实有内部代码进行合并,如果内部“预合并”失败,它只会调用外部合并工具。
您链接到the HG Book,它表示没有用于处理冲突的内置工具(与没有内置合并不同)和the Mercurial wiki,其中声明Mercurial会尝试在调用外部程序之前在内部进行合并。
您链接到一个问题,其中my answer给出了Mercurials成功并且Subversion在合并中失败的明确情况。这是使用Mercurial和Subversion中的内部合并代码的开箱即用的比较。