如何和/或为什么在Git中合并比在SVN中更好?

时间:2010-03-18 16:32:33

标签: svn git version-control mercurial merge

我在一些地方听说分布式版本控制系统闪耀的主要原因之一是比SVN等传统工具更好地融合。 这实际上是由于两个系统如何工作的固有差异,或者像Git / Mercurial这样的特定的 DVCS实现是否只有比SVN更聪明的合并算法?

7 个答案:

答案 0 :(得分:550)

答案 1 :(得分:28)

历史上,Subversion只能执行直接的双向合并,因为它没有存储任何合并信息。这涉及进行一系列更改并将其应用于树。即使使用合并信息,这仍然是最常用的合并策略。

Git默认使用3向合并算法,其中包括找到要合并的头部的共同祖先,并利用合并两侧存在的知识。这使Git能够更加智能地避免冲突。

Git还有一些复杂的重命名查找代码,这也有帮助。它存储变更集或存储任何跟踪信息 - 它只存储每次提交时文件的状态,并使用启发式方法根据需要定位重命名和代码移动(磁盘存储更多比这更复杂,但它呈现给逻辑层的界面没有暴露跟踪)。

答案 2 :(得分:16)

简而言之,合并实施在Git中比在SVN中更好。在1.5 SVN没有记录合并动作之前,没有用户需要提供SVN没有记录的信息的帮助就无法进行未来的合并。随着1.5它变得更好,实际上SVN存储模型比Git的DAG稍微强大。但是SVN以一种相当复杂的形式存储合并信息,这使得合并比Git花费更多的时间 - 我已经在执行时间内观察到了300个因素。

此外,SVN声称跟踪重命名以帮助合并已移动的文件。但实际上它仍然将它们存储为副本和单独的删除操作,并且合并算法仍然在修改/重命名情况下偶然发现它们,即,在一个分支上修改文件并在另一个分支上重命名,并且这些分支是合并。这种情况仍然会产生虚假的合并冲突,并且在目录重命名的情况下,它甚至会导致无声的修改丢失。 (然后SVN人员倾向于指出修改仍然在历史中,但是当它们不在合并结果中时它们应该出现时没有多大帮助。

另一方面,Git甚至没有跟踪重命名,而是在事后(合并时)将它们计算出来,并且非常神奇。

SVN合并表示也有问题;在1.5 / 1.6中,您可以自动地从主干到分支合并,但是需要在另一个方向上合并(--reintegrate),并使分支处于不可用状态。很久以后他们发现事实并非如此,并且a)--reintegrate 可以自动计算出来,并且b)可以在两个方向上重复合并。

但是毕竟这个(IMHO表示对他们正在做的事情缺乏了解),我会(好吧,我)非常谨慎地在任何非平凡的分支场景中使用SVN,理想情况下会尝试看看是什么Git想到合并结果。

答案中提出的其他观点,因为SVN中分支的强制全局可见性与合并功能无关(但是对于可用性)。此外,'Git存储变化,而SVN存储(不同的东西)'大多不合时宜。 Git在概念上将每个提交存储为一个单独的树(如tar文件),然后使用相当多的启发式来有效地存储它。计算两次提交之间的更改与存储实现是分开的。真实的是,Git以更直接的形式存储历史DAG,SVN执行其mergeinfo。任何试图了解后者的人都知道我的意思。

简而言之:Git使用比SVN更简单的数据模型来存储修订,因此它可以将大量精力投入到实际的合并算法中,而不是试图应对表示=>实际上更好地融合。

答案 3 :(得分:10)

编辑:这主要是解决问题的这部分
这实际上是由于两个系统如何工作的固有差异,或者像Git / Mercurial这样的特定DVCS实现是否只有比SVN更聪明的合并算法?
TL; DR - 这些特定工​​具具有更好的算法。分发具有一些工作流程的好处,但与合并优势正交 结束编辑

我读了接受的答案。这是完全错误的。

SVN合并可能是一种痛苦,也可能很麻烦。但是,忽略它实际上如何运作一分钟。没有Git保留或可以推导出SVN不会保留或可以派生的信息。更重要的是,没有理由保留版本控制系统的单独(有时是部分)副本将为您提供更多实际信息。这两种结构完全相同。

假设你想要做一些聪明的事情" Git在"更好。而且你的事情已被检入SVN。

将您的SVN转换为等效的Git表单,在Git中执行,然后检查结果,可能使用多个提交,一些额外的分支。如果你能想象一种将SVN问题转化为Git问题的自动方式,那么Git没有任何根本优势。

在一天结束时,任何版本控制系统都会让我

1. Generate a set of objects at a given branch/revision.
2. Provide the difference between a parent child branch/revisions.

此外,为了合并它,知道

也很有用(或很关键)
3. The set of changes have been merged into a given branch/revision.

Mercurial,Git和Subversion(现在原来使用svnmerge.py)都可以提供所有三条信息。为了通过DVC更好地展示一些东西,请指出在SVN /集中式VC中没有的Git / Mercurial / DVC中可用的第四条信息。

不要说他们不是更好的工具!

答案 4 :(得分:10)

其他答案中没有提到的一件事,那就是DVCS的一大优势,就是你可以在推送更改之前在本地提交。在SVN中,当我进行一些更改时,我想要检查,并且有人在此期间已经在同一分支上完成了提交,这意味着我必须在我提交之前执行svn update。这意味着我的更改以及来自其他人的更改现在混合在一起,并且无法中止合并(例如使用git resethg update -C),因为没有提交去回到。如果合并非常重要,这意味着在清理合并结果之前,您无法继续处理功能。

但是,对于那些过于愚蠢而无法使用单独分支的人来说,这可能只是一个优势(如果我没记错的话,我们在使用SVN的公司中只有一个用于开发的分支)。

答案 5 :(得分:8)

SVN跟踪文件,而Git跟踪内容更改。它足够聪明地跟踪从一个类/文件重构到另一个类/文件的代码块。他们使用两种完全不同的方法来跟踪您的来源。

我仍然大量使用SVN,但我对使用Git几次感到非常满意。

如果你有时间,可以阅读: Why I chose Git

答案 6 :(得分:6)

刚刚阅读了一篇关于Joel博客的文章(遗憾的是他的最后一篇)。这个是关于Mercurial的,但它实际上讨论了分布式VC系统的优点,例如Git。

  

使用分布式版本控制,   分布式部分实际上不是   最有趣的部分。有趣的是,这些系统考虑的是变化,而不是版本。

阅读文章here