为什么Mercurial中的分支和合并比Subversion更容易?

在Subversion或CVS中处理多个合并到分支机构中仅仅是必须经历的事情之一。 在Mercurial(也可能是其他任何分布式系统)中跟踪分支和合并是非常容易的,但我不知道为什么。 其他人知道吗?

我的问题源于这样的事实:使用Mercurial你可以采取类似于Subversions / CVS中央仓库的工作实践,一切都将工作得很好。 你可以在同一个分支上进行多次合并,你不需要用提交数字和标签名称的无尽纸屑。

我知道最新版本的Subversion有能力跟踪分支合并,所以你没有得到相同程度的麻烦,但这是一个巨大而重大的发展,它仍然不会做所有的开发团队喜欢它做。

它们的工作方式必须有根本的区别。

在Subversion(和CVS)中,存储库是首要的。 在git和mercurial中,存储库的概念实际上并不一样, 这里的变化是中心主题。

+1

CVS / SVN的麻烦来自于这些系统记得父母的变化。 在Git和Mercurial中,不但可以有多个孩子,还可以有多个父母!

这可以很容易地使用graphics工具之一, gitkhg view 。 在以下示例中,分支#2在提交A处从#1分叉,并且自此合并了一次(在M处,与提交B合并):

 o---A---o---B---o---C (branch #1) \ \ o---o---M---X---? (branch #2) 

注意A和B有两个孩子,而M有两个父母 。 这些关系被logging在存储库中。 假设分支#2的维护者现在想合并来自分支#1的最新更改,他们可以发出如下命令:

 $ git merge branch-1 

并且该工具会自动地知道该基础是B – 因为它被logging在提交M,即#2的提示的祖先,并且它必须合并在B和C之间发生的任何事情.CVS不logging该信息在版本1.5之前也没有SVN。 在这些系统中,graphics如下所示:

 o---A---o---B---o---C (branch #1) \ o---o---M---X---? (branch #2) 

其中M只是A和B之间发生的所有事情的一个巨大的“压扁的”承诺,应用于M之上。请注意,在完成契约之后, 没有任何剩余的痕迹 (除了潜在的人类可读的评论),其中M没有发生过,也没有发生过多less次的承诺,使历史变得更加难以逾越。

更糟糕的是,执行第二次合并变成了一场噩梦:在第一次合并时必须弄清楚合并基础是什么(并且必须 知道首先合并了),然后提出信息传递给工具,这样它就不会尝试在A之上重放A..B。所有这些在密切协作的情况下足够困难,但在分布式环境中根本不可能。

一个(相关的)问题是没有办法回答这个问题:“X是否包含B? 其中B是潜在的重要错误修复。 那么,为什么不把这个信息logging在提交中呢,因为它在合并时是已知的

P.-S. – 我没有使用SVN 1.5+合并loggingfunction的经验,但是工作stream程似乎比分布式系统更有人气。 如果情况确实如此,那可能是因为 – 正如上述评论所提到的那样 – 重点放在知识库的组织上,而不是变化本身。

因为Subversion(至less版本1.4及以下版本)没有跟踪合并的内容。 对于Subversion来说,合并与其他版本控制(如Git)中的任何提交基本相同,已合并的内容将被记住。

由于没有任何已经提供的答案,Hg提供了卓越的合并能力,因为它在合并变更时使用更多的信息( hginit.com ):

例如,如果我稍微改变了一个函数,然后把它移动到别的地方,Subversion并没有真正记住这些步骤,所以当它合并的时候,可能会认为一个新的函数出现了。 Mercurial会分别记住这些事情:函数改变,函数移动,这意味着如果您也稍微改变了这个函数,那么Mercurial更有可能成功地合并我们的更改。

当然,记住上次合并的内容(这里提供的大部分答案都是这个问题)也是一个巨大的胜利。

然而,两种改进都是有问题的,因为Subversion 1.5+以颠覆属性的forms存储了额外的合并信息:这些信息可用,没有明显的理由说明为什么Subversion合并不能像Hg或Git那样实现合并。 不过,我不知道它是否确实如此,但听起来像颠覆开发者正在解决这个问题。

我想这可能部分是因为Subversion有一个中央服务器的概念以及绝对的修订版本。 Mercurial是真正的分布式,没有这样的绝对时间线的参考。 这确实允许Mercurial项目通过子项目形成更加复杂的分支层级以添加特征和testing周期,但是团队现在需要更积极地保持最新的合并以保持当前的状态,因为它们不能只是更新并完成它。

在Subversion(和CVS)中,存储库是首要的。 在git和mercurial中,存储库的概念实际上并不一样, 这里的变化是中心主题。

我没有多less考虑如何实现,但是我的印象(基于痛苦的经验和大量的阅读)是,这种差异使合并和分支在非基于仓库的系统中变得更容易。

我只有Subversion的经验,但我可以告诉你,在TortoiseSVN合并屏幕是非常复杂的。 幸运的是,他们包括一个干运行button,这样你就可以看到你是否做得对。 复杂性在于你想要合并到哪里的configuration。 一旦你得到了合并设置合并一般情况下罚款。 然后你需要解决任何和所有的冲突,然后提交你的合并工作副本到版本库。

如果Mercurial可以使合并的configuration更容易,那么我可以说,这将使Subversion合并100%。