在Subversion(和CVS)中,仓库是首要的。在Git和Mercurial中,没有像仓库这样的概念;这里变更是核心主题。
在CVS/SVN中的麻烦来自于这些系统不记得变更的父级。在Git和Mercurial中,一个提交不仅可以有多个子级,还可以有多个父级!
可以很容易地使用其中一个图形工具
gitk
或
hgview
观察到这一点。在下面的示例中,分支#2从提交A处派生出来,此后已经合并了一次(在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
而工具将自动知道base是B--因为它记录在提交M中,这是#2顶点的祖先--并且它必须合并在B和C之间发生的任何事情。CVS不记录此信息,SVN在1.5版本之前也没有记录。在这些系统中,图形看起来像:
o---A---o---B---o---C (branch #1)
\
o---o---M---X---? (branch #2)
其中M只是一个巨大的“压缩”提交,包括从A到B之间发生的所有内容,应用于M之上。请注意,完成后,除了在人类可读的注释中可能存在外,M的来源以及折叠在一起的提交数量都没有留下任何痕迹,使历史变得更加深不可测。
更糟糕的是,执行第二次合并变成了一场噩梦:必须找出第一次合并时的合并基础(而且必须知道已经有了一次合并!),然后将该信息呈现给工具,以便它不会尝试重放A..B到M之上。在密切合作时,所有这些都已经很困难了,但在分布式环境中则根本不可能。
(相关的)问题是没有办法回答问题:“X是否包含B?”其中B是一个可能重要的错误修复。那么,为什么不在提交中记录这些信息,因为在合并时它是已知的!
附言:我对SVN 1.5+合并记录功能没有任何经验,但工作流程似乎比分布式系统更加牵强。如果确实如此,那可能是因为--如上面的评论中提到的--重点放在了仓库组织而不是变更本身上。
svn:mergeinfo
属性吗? - Tylersvn:mergeinfo
所做的。 - sleske