内部数据模型根本不同。
从根本上讲,在SVN中,当您查看分支的历史记录时,您只会看到该分支中发生了什么。因此,当您从一个分支合并B
到另一个分支时,分支A
的历史记录A
将包含一个大型提交,其中包含B
自分支以来已明确进行的所有更改。
在SVN的第一个版本中,如果必须再次将分支合并B
到分支中A
,则必须手动指定B
要合并的分支修订版本范围,以避免将相同的修订合并两次。聪明的开发人员当然会使用诸如“在B:1234中合并”的提交消息。
SVN 1.5“修复”了这个问题。但这并没有改变从根本上应用合并的方式。它仅向分支添加了一些额外的元数据A
,从而使SVN知道版本1234已被合并,从而使SVN能够自动选择正确的版本范围。
但是,对于基本上不支持跟踪已合并内容的数据模型,此解决方案基本上是一种解决方法。
合并两个分支是一个相对简单的示例。但是想像一下这种更复杂的情况
A
从创建分支trunk
,并在此处进行一些提交
B
从A
这里创建分支并在此处进行一些提交
- 在做了几提交
trunk
和A
- 合并
B
成trunk
- 合并
A
成B
- 合并
A
成trunk
- 合并
B
成trunk
(这不应该真正做任何事情)
使用元数据模型正确处理此问题变得非常复杂(我不知道SVN是否确实能够正确处理此情况,并且我不愿意对其进行测试)。
在git中处理这种情况非常简单。
在git中,每次提交时,代表该提交的内部对象都包含对前一个头部的引用。当您在一个分支中合并时,提交包含对要合并的所有分支的前一个头的引用(您可以在git中一次合并多个分支)
因此,当您在git中检查单个提交的历史记录时,您可以看到所有历史记录,可以看到它何时被分支,何时被合并,还可以看到分支和合并之间的两个分支的历史记录。
因此,当合并已部分合并的分支时,确定已合并的内容和未合并的内容非常简单。
我没有使用Mercurial的经验,但是我怀疑它的内部工作原理与git类似。
因此,从根本上来说,对于SVN来说,使分支便宜是一个设计目标。但是在git中,使合并便宜是一个设计目标。
最后,上一次我使用SVN时,它无法处理合并,在一个分支中重命名文件,然后在另一个分支中修改文件。