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


92

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

我的问题源于以下事实:Mercurial可以采用类似于Subversions / CVS中央存储库的工作方式,并且一切都会正常进行。您可以在同一个分支上进行多次合并,并且不需要无休止的纸屑,包括提交号和标签名。

我知道最新版本的Subversion具有跟踪合并到分支的能力,因此您不会遇到相同程度的麻烦,但是这对他们来说是一个巨大而重大的发展,并且仍然无法完成开发团队的所有工作喜欢做。

所有工作方式都必须有根本的区别。

Answers:


115

在Subversion(和CVS)中,存储库是最重要的。在git和mercurial中,实际上并没有以相同的方式定义存储库的概念。这里的变化是中心主题。

+1

CVS / SVN的麻烦来自于以下事实:这些系统 记得更改的父项。在Git和Mercurial中,一个提交不仅可以有多个孩子,还可以有多个父母!

可以使用的图形工具之一很容易观察到,gitkhg view。在以下示例中,分支#2是在提交A处从#1分叉的,此后已被合并一次(在M处,与提交B合并):

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

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

$ git merge branch-1

并且该工具将自动知道碱基是B,因为它记录在提交M中,即提交#2的先端,并且必须合并在B和C之间发生的任何事情。CVS不会记录此信息,版本1.5之前的SVN也没有。在这些系统中,图形如下所示:

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

其中M只是在A和B之间发生的所有事情的一个巨大的“压缩”提交,应用在M之上。请注意,完成契约之后,就没有留下任何迹线(可能在人类可读的注释中除外)确实起源于,也没有多少次崩溃在一起的,这使历史更加难以理解。

更糟糕的是,进行第二次合并变成了一场噩梦:一个人必须弄清楚什么合并的基础是在第一个合并的时间(和一个具有知道 的是,已经在第一时间合并!),那么目前这信息,以便它不会尝试在M之上重播A..B。在紧密协作中,所有这些工作都非常困难,但在分布式环境中根本不可能。

一个(相关的)问题是无法回答以下问题:“ X是否包含B?” 其中B是潜在的重要错误修复。因此,为什么不将这些信息记录在提交中,因为在合并时就知道了该信息!

P.-S. -我没有SVN 1.5+合并记录功能的经验,但是工作流程似乎比分布式系统人为得多。如果确实如此,那可能是因为-正如上面的评论中所提到的-重点放在存储库组织而不是更改本身上。


6
SVN 1.5+确实会将SVN属性放在合并提交M上,列出它包含的合并提交,换句话说AB。因此,您拥有相同的信息。
西蒙D

有点儿。从技术上讲,SVN的合并跟踪类似于Git所说的“樱桃采摘”,并带有附加的魔术使用户更容易使用。它在语义上与合并时Git,Hg和Bzr所做的不同。我想只要您不关心DAG(eagain.net/articles/git-for-computer-scientists),它在实践中就不会有太大的不同
Damien Diederen

2
糟糕,没有+100按钮。谢谢。
查理·

我假设您正在谈论的SVN 1.5功能是该svn:mergeinfo属性的使用?
MatrixFrog 2011年

@MatrixFrog:是的,这就是svn:mergeinfo作用。
sleske 2011年

12

因为Subversion(至少1.4版及更低版本)无法跟踪已合并的内容。对于Subversion,合并基本上与任何提交相同,而在其他版本控制(如Git)上,记住已合并的内容。


7

Hg不受任何已经提供的答案的影响,提供了卓越的合并功能,因为它在合并更改时会使用更多信息(hginit.com):

例如,如果我稍微改变一个功能,然后再将其移动到其他位置,Subversion不会真正记住这些步骤,所以当需要合并时,它可能会认为新功能突然出现了。而Mercurial会分别记住这些事情:功能更改,功能移动,这意味着如果您也稍微更改了该功能,Mercurial很有可能成功合并我们的更改。

当然,记住最后合并的内容(此处提供的大多数答案都解决了这一点)也是一个巨大的胜利。

但是,由于Subversion 1.5+会以Subversion属性的形式存储其他合并信息,因此这两个改进都值得怀疑:该信息可用,没有明显的理由说明Subversion合并不能像Hg或Git那样成功地实现合并。我不知道是否可以,但是听起来确实像是Subversion开发人员正在解决这个问题。


4

我想这可能部分是因为Subversion具有中央服务器的想法以及绝对的修订时间线。Mercurial确实是分布式的,没有对绝对时间线的引用。这确实允许Mercurial项目形成更复杂的分支层次结构,以按子项目添加功能和测试周期,但是现在团队需要更加积极地掌握合并的最新信息,以保持最新状态,因为他们不能仅仅点击update并完成更新。 。


3

在Subversion(和CVS)中,存储库是第一位的。在git和mercurial中,实际上并没有以相同的方式定义存储库的概念。这里的变化是中心主题。

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


1

我只有Subversion的经验,但我可以告诉您TortoiseSVN中的合并屏幕非常复杂。幸运的是,它们包括一个空转按钮,以便您查看操作是否正确。复杂之处在于要合并到何处的配置。一旦您为合并设置好了,合并通常就可以了。然后,您需要解决所有冲突,然后将合并的工作副本提交到存储库中。

如果Mercurial可以简化合并的配置,那么我可以说这将使Subversion的合并变得100%容易。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.