为什么Git比Subversion更好?

393

我使用 Subversion 几年了,相比于 SourceSafe,我更喜欢 Subversion。加上 TortoiseSVN,我实在想象不出还有什么更好的。

然而,越来越多的开发人员声称 Subversion 存在问题,我们应该转向新型分布式版本控制系统,例如 Git

Git 如何改进 Subversion?

30个回答

547

Git并不比Subversion更好,也不比它更差。它只是不同。

最大的区别在于Git是分布式的。想象一下你是一个开发者,你在路上工作,在笔记本电脑上开发,并想要进行源代码控制,以便可以返回之前的版本。

使用Subversion时,你会遇到一个问题:SVN存储库可能在你无法访问的位置(在公司里,而你此时没有互联网连接),因此你无法提交。如果你想要复制你的代码,你必须直接复制/粘贴。

使用Git时,你就不会有这个问题。你的本地拷贝就是一个存储库,你可以对它进行提交并获得所有源码控制的好处。当你重新连接到主存储库时,你可以向它进行提交。

这看起来很不错,但请记住这种方法增加了复杂性。

Git似乎是“新的、闪亮、酷”的东西。它绝不是坏东西(毕竟是Linus为Linux内核开发编写的原因),但我认为许多人跳上“分布式源码控制”列车只是因为它是新的,由Linus Torvalds编写,而实际上他们并不知道为什么/是否更好。

Subversion有问题,但Git、Mercurial、CVS、TFS或其他工具也同样如此。

编辑:所以这篇回答已经一年了,依然产生很多赞,因此我想再添加一些解释。自从写下这篇文章以来的最后一年里,Git获得了很多动力和支持,特别是自从像GitHub这样的网站真正开始流行起来之后。我现在同时使用Git和Subversion,并想分享一些个人见解。

首先,在分散式工作时,Git可能会让人感到非常困惑。什么是远程(remote)?如何正确设置初始存储库(repository)?这是一开始经常遇到的两个问题,特别是与SVN简单的 "svnadmin create "相比,Git的 "git init" 可以带有参数--bare和--shared,这似乎是设置集中式存储库的“正确”方式。虽然有原因,但这增加了复杂性。“checkout”命令的文档对于转换的人非常令人困惑——“正确”的方式似乎是“git clone”,而“git checkout”似乎是用于切换分支。

当你是分散的时,Git真的很出色。我在家里有一个服务器,在路上有一个笔记本电脑,而SVN在这里根本无法正常工作。对于SVN,如果没有连接到存储库,我就无法进行本地源代码控制(是的,我知道SVK或者复制存储库的方法)。而对于Git,那就是默认模式。它是一个额外的命令(git commit在本地提交,而git push origin master将主分支推送到名为“origin”的远程)。

如上所述:Git增加了复杂性。创建存储库的两种模式,checkout与clone,commit与push...您必须知道哪些命令在本地工作,哪些命令与“服务器”一起工作(我假设大多数人仍然喜欢中央“主存储库”)。

此外,至少在Windows上,Git的工具仍然不足。是的,有一个Visual Studio AddIn,但我仍然使用带有msysgit的git bash。

SVN的优点是学习起来要简单得多:有你的存储库,所有更改都针对它进行,如果你知道如何创建、提交和checkout,你就可以开始并且稍后可以掌握分支、更新等内容。

Git的优点是,如果有些开发人员没有始终连接到主存储库,那么它非常适用。而且它比SVN快得多。从我听到的消息来看,分支和合并支持要好得多(这是可以预料的,因为这些是它被编写的核心原因)。

这也解释了为什么Git在互联网上引起如此大的轰动,因为Git非常适合开源项目:只需Fork它,将更改提交到您自己的Fork中,然后请求原始项目维护者拉取您的更改。使用Git,这很简单。确实,试试在Github上使用它,它就像魔术一样。

我还看到了Git-SVN桥接器:中央仓库是Subversion repo,但开发人员在本地使用Git进行工作,然后通过桥接器将更改推送到SVN。

但即使加入了这个冗长的补充,我仍然坚持我的核心信息:Git并不比SVN更好或更差,它只是不同。如果您需要“离线源代码控制”并愿意花费额外的时间学习它,那么它非常棒。但如果您有一个严格集中化的源代码控制,或者因为同事们没有兴趣而努力介绍源代码控制,那么SVN在简单性和出色的工具(至少在Windows上)方面更胜一筹。


70
一辆法拉利并不比一辆现代好,也不比它差。它只是不同而已。(什么?别这样盯着我看……我说错什么了吗?) - F.D.Castel
219
不,你没有。法拉利不切实际、昂贵、油耗大,如果你住在像纽约或巴黎这样的城市,它也不能让你更好地从A点到达B点 - 对于很多地方,我更喜欢现代汽车,因为即使有划痕也不会那么严重。但是每个人都有自己的选择- 法拉利也有(极少数的)优势... - Michael Stum
50
分布式并不是 Subversion 和 Git 之间唯一的区别。除非使用多个仓库,否则它也不会增加任何复杂性。相比于 Subversion,使用 Git 有许多优势,但只有一些微不足道的缺点。人们使用 Git 是因为它好用,而非因为它炫酷。 - sebnow
6
我对Git的经验并没有带来"改变生活的领悟"。在它正常工作时,我认为它是个好工具;但当它出问题时,就会感觉不太成熟。我对调试像Question 1052882那样的问题并不太满意,即使这显然是一个RTFM问题:我仍然认为Git(以及其他分布式版本控制系统)比集中式版本控制系统更加复杂,并且在集中式环境中使用Git是值得考虑的。但再说一遍,我主要是一个Windows开发者,相比于SVN而言,在Windows上的工具还不够成熟。 - Michael Stum
5
你只分析了比较中的分发方面。我来告诉你为什么。因为你只想“分享”代码。Git 和 SVN 不仅如此,你有没有打标签、分支、合并、解决冲突、在分支之间复制补丁?我认为你的分析是有缺陷的。在这些方面,git 是一个非常强大的工具。更不用说 git 能做而 SVN 不能做的事情,比如压缩、剖解、修补、变基、精选等等。 - Martín Schonaker
显示剩余17条评论

145

使用Git,你几乎可以离线做任何事情,因为每个人都有自己的代码库。

创建分支和分支之间的合并非常容易。

即使您没有项目的提交权限,您仍然可以拥有自己的在线代码库,并发布“推送请求”以进行补丁。喜欢您的补丁的每个人都可以将其拉入他们的项目中,包括官方维护者。

轻松地fork一个项目,修改它,同时仍然可以从HEAD分支合并bugfixes。

Git适用于Linux内核开发人员。这意味着它非常快(必须如此),并可扩展到数千名贡献者。Git还使用更少的空间(Mozilla代码库的空间高达30倍)。

Git非常灵活,非常TIMTOWTDI(有多种方法可以做到)。您可以使用任何工作流程,Git都将支持它。

最后,还有GitHub,这是一个托管您的Git代码库的好网站。

Git的缺点:

  • 学习难度较大,因为Git有更多的概念和更多的命令。
  • 修订版本没有像Subversion那样的版本号。
  • 许多Git命令很难理解,错误消息也不够用户友好。
  • 缺乏良好的图形用户界面(如优秀的TortoiseSVN)。

31
学习整个Git可能会更难,但基础知识与SVN几乎相同。直到涉及到更高级的内容,学习难度并不会变得特别大,而且这些高级内容SVN根本就无法实现。 - sebnow
10
对我来说加1。我认为很多开发人员忘记了Git缺少类似TortoiseSVN这样的功能,而不仅仅是开发人员使用版本控制。想到要向我们的非开发人员使用SVN | TortoiseSVN解释(和支持)分布式版本控制,我就不寒而栗! - si618
7
另一个缺点是,你必须拥有完整的存储库副本,无法在部分副本上工作(如果你有大型副本,比如很多企业都会有这个问题)。 - gbjbaanb
3
我热爱Git,但我花了大约六个月的时间每天使用它才真正能够有效地使用它。说实话,我使用msysgit提供的Git Shell(命令提示符),以及从msysgit获取的Git GUI和Gitk,还有TortoiseGit这些组合工具。我认为TortoiseGit非常棒,但我不明白为什么更多人不使用它。我知道,出于各种原因,有些人持有拒绝使用TortoiseGit的态度,其中一些是意识形态上的,而这可能与此有关。TortoiseGit是一个被很好保密的好工具! - Jim Raden
2
我同意。我同时使用SVN和GIT(大约6个月以来)。说实话,我非常喜欢GIT,比我曾经喜欢的SVN更多。只是需要时间去学习它。对我来说最大的飞跃(我看到了光明的时刻:P)是当我终于意识到我不再试图以SVN的方式使用GIT时。然后一切就都明朗了 ;) - Blizz

110
其他回答已经很好地解释了Git的核心功能(非常棒)。但是Git还有许多细节上的优点,可以帮助保持我的生活更加清醒。以下是一些小事情:
  1. Git有一个'clean'命令。 SVN迫切需要这个命令,考虑到它会频繁地在您的磁盘上倾倒额外的文件。
  2. Git有'bisect'命令,很不错。
  3. SVN在每个文件夹中创建.svn目录(Git只创建一个.git目录)。您编写的每个脚本和每个grep都需要编写以忽略这些.svn目录。您还需要一个完整的命令(“svn export”)才能获取一个理智的文件副本。
  4. 在SVN中,每个文件和文件夹都可以来自不同的修订版本或分支。起初,拥有这种自由听起来很好。但实际上,这意味着您的本地检出会有无数种方式被完全搞砸。(例如,如果“svn switch”在中途失败,或者如果您输入了错误的命令)。最糟糕的部分是:如果您遇到某些文件来自某个位置,而另一些文件来自另一个位置的情况,“svn status”将告诉您一切正常。您需要对每个文件/目录执行“svn info”才能发现事情有多奇怪。如果“git status”告诉您一切正常,则可以信任事情确实是正常的。
  5. 您必须在移动或删除某些内容时告诉SVN。Git会自己弄清楚。
  6. 在Git中,忽略语义更容易。如果您忽略了一个模式(例如* .pyc),它将被所有子目录忽略。(但是,如果您真的想仅忽略一个目录中的东西,则可以)。在SVN中,似乎没有简单的方法可以跨所有子目录忽略一个模式。
  7. 另一个涉及忽略文件的项目。Git使得可以拥有“私有”忽略设置(使用文件.git/info/exclude),这不会影响任何其他人。

2
广告7. 使用现代的git,您还可以通过在~/.gitignore中使用core.excludesFile配置变量来拥有每个用户的“私人”忽略设置(请参阅man git-config)。 - Jakub Narębski
3
关于第五条评论:尽管通常情况下是正确的,但有时Git会出错。至少在Subversion中,由于移动或删除引起的问题几乎总是用户自己的问题。虽然自动跟踪移动/删除很好,但我仍然希望能够明确地说明我对存储库中的文件所做的更改,即使我不需要使用它。 - Chris Charabaruk
8
@Chris: 你可以明确地使用 git mvgit rm 命令来完成。 - R. Martinho Fernandes
2
我也希望看到每个工作副本只有一个 .svn 目录的选项,但是为了记录: 对于 #3:大多数工具(默认情况下)会忽略 .svn 目录。 对于 #6:您可以递归地设置属性。 - si618
6
3: 当WC-NG实现时,将会在这里有一个单独的“.svn”目录,用于SVN 1.7。 1: 要获得SVN清理,您需要在当前工作副本上进行“导出”操作。 5: 如果重命名文件,Git是否能够识别并保留历史记录,或是将其视为在目录中添加和删除?这并不容易。 6/7: SVN拥有每个用户客户端设置的全局忽略配置。 - gbjbaanb
显示剩余4条评论

56
"Why Git is Better than X"介绍了Git与其他SCMs之间的优缺点。
简单来说:
  • Git跟踪内容而不是文件
  • 分支轻量化且合并,我是说真的很容易
  • 它是分布式的,每个存储库基本上都是一个分支。与Subversion相比,我认为它更容易同时和协作开发。它还可以使离线开发成为可能。
  • 不强制任何工作流程,如上面链接的网站所示,使用Git有许多工作流程可选。可以轻松模仿Subversion样式的工作流程。
  • Git存储库的文件大小比Subversion存储库要小得多。只有一个".git"目录,而不是数十个".svn"存储库(请注意,Subversion 1.7及更高版本现在像Git一样使用单个目录)。
  • 暂存区非常好用,可以让您看到要提交的更改,提交部分更改并执行各种其他操作。
  • 存储在进行“混沌”开发或仅想在还在做其他事情(在另一个分支上)时修复错误时非常宝贵。
  • 您可以重写历史记录,这对于准备补丁集和修复错误(发布提交之前)非常有用
  • …等等。

也存在一些缺点:

  • 目前还没有很多好的GUI可用。Git是新技术,而Subversion已经存在了很长一段时间,因此正在开发一些接口。其中一些好的包括TortoiseGitGitHub for Mac
  • 目前不支持部分检出/克隆存储库(我读到正在开发中)。但是,有子模块支持。 Git 1.7+支持稀疏检出
  • 学习可能会更困难,尽管我没有发现这种情况(大约一年前)。Git最近改进了其界面,非常用户友好。

在最简单的使用情况下,Subversion和Git基本上是一样的。它们之间的区别不太大:

svn checkout svn://foo.com/bar bar
cd bar
# edit
svn commit -m "foo"

git clone git@github.com:foo/bar.git
cd bar
# edit
git commit -a -m "foo"
git push

Git最擅长的是分支和与他人合作工作。


8
你说GIT跟踪内容而不是文件。我发现SVN也这样做:我刚刚对一个文件进行了更改并保存了。 SVN显示该文件为红色(已更改)。然后我在编辑器中执行了撤消操作并重新保存了文件。即使文件已更改(更改日期更新),SVN也将状态更新为绿色(未更改),但SVN识别到内容与原始内容没有更改。 - awe
SVN是否跨文件追踪更改? - Seun Osewa
12
@awe,这被称为文件跟踪。尝试重命名文件或手动将其移动到其他位置[由于新的路径/名称而是一个新文件]:SVN会知道这是同一文件并保留您对它所做的以前无数次修订吗?我想不会。 - Filip Dupanović
TortoiseGit - http://code.google.com/p/tortoisegit/ | Git 1.7 稀疏检出 - http://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.7.0.txt - Zaz

54

12
Linus的演讲很有趣。他狠狠地批评了集中式版本控制系统,如Subversion和CVS。不过,Randal Schwartz的http://www.youtube.com/watch?v=8dhZ9BXQgc4演讲更具建设性、更丰富、更有说服力。 - bendin
2
这个也非常不错。它来自于 Git 提交者之一,他解释了许多高级功能,例如将大型提交拆分成较小的提交。http://www.youtube.com/watch?v=j45cs5_nY2k - schoetbi
我喜欢那个Linus Torvalds的视频,但他暗示git是分布式的,而不是集中式的,这是错误的。它可以以分布式方式或集中式方式使用。您可以有一个中央仓库,每个人都像在SVN中一样提交代码。只是你不必这样做。 - Tyler
@MatrixForog: 我认为在这种情况下,“分散式”不是“集中式”的_相反_,而是一个超集。就像“移动”和“不动”一样--仅因为某物是“移动的”并不意味着它不能静止不动。 - Tikhon Jelvis

26

这个技术是分布式的。基准测试表明,它的速度要快得多(由于其分布式的性质,像差异和日志等操作都是本地操作,因此在这种情况下速度自然会非常快),而且工作文件夹也更小(这仍然让我感到惊讶)。

当你使用Subversion或其他客户端/服务器版本控制系统时,你实际上是通过“检出”版本在你的计算机上创建工作副本。这代表了仓库看起来的某个时间点的快照。你可以通过更新来更新你的工作副本,并通过提交来更新仓库。

使用分布式版本控制,你没有快照,而是拥有整个代码库。想要查看3个月前的版本差异?没问题,3个月前的版本仍然在你的电脑上。这不仅意味着事情要快得多,而且如果你与中央服务器断开连接,你仍然可以执行许多你习惯的操作。换句话说,你不仅拥有给定版本的快照,而是整个代码库。

你可能认为Git会占用大量硬盘空间,但根据我看到的一些基准测试,它实际上占用更少的空间。别问我怎么回事。我的意思是,它是由Linus创建的,他对文件系统也有一些了解。


1
Git相对于Subversion在存储完整仓库时占用更少的磁盘空间的原因是,Subversion为了使'svn diff'(与上一个版本的比较)能够正常工作,会存储"原始副本"。而Git仓库则是经过压缩和增量处理的。 - Jakub Narębski
3
我不觉得Git的“工作文件夹”(即仓库)比SVN的工作副本小,因为即使是SVN仓库也比SVN工作副本小。 - R. Martinho Fernandes

22

我喜欢关于分布式版本控制系统的以下几点:

  1. 你可以提交不完整的内容,因为只有在发布之前其他人才看不到它们。发布时间与提交时间不同。
  2. 由于这一点,你可以更频繁地提交。
  3. 你可以合并完整的功能性。该功能性将拥有自己的分支。所有该分支的提交都与该功能性相关。虽然CVCS也可以实现,但DVCS是默认的。
  4. 你可以搜索你的历史记录(找到一个函数何时改变)
  5. 如果有人搞乱了主要仓库,你可以撤销拉取操作而无需修复错误。只需清除合并即可。
  6. 当你需要在任何目录中使用源代码控制,只需运行:git init .,然后你就可以提交、撤销更改等操作了。
  7. 它快速(即使在Windows上也是如此)。

对于相对较大的项目来说,最主要的原因是第3点所带来的改进的沟通。其他点则是美好的额外收获。


我认为第一点的意思是“除非你发布(或推送),否则其他人看不到它们”。 - jackr
“你可以提交有问题的东西。”这是我考虑从svn转向git的主要原因。我总是讨厌在开发一个复杂的代码块时,没有版本控制系统的安全网(仅仅因为我的修改还不起作用,所以我不能提交)。 - András Szepesházi

15

有趣的是:我在 Subversion 仓库中托管项目,但通过 Git Clone 命令访问它们。

请阅读使用 Git 在 Google Code 项目上开发

虽然 Google Code 原生支持 Subversion,但您可以轻松地在开发过程中使用 Git。搜索“git svn”表明这种做法已经很普遍了,我们也鼓励您尝试一下。

在 Svn 仓库上使用 Git 有以下好处:

  1. 我可以在多台机器上进行分布式工作,提交和拉取它们之间的更改
  2. 我有一个集中的备份/公共 svn 仓库供他人检出
  3. 他们可以自由地使用 Git 进行开发

3
这有点过时了,谷歌现在使用Mercurial,所以不需要这个hack了。 - Sam Saffron
@Sam,除非你喜欢Git和/或不喜欢Mercurial。 - Tyler

11
这里的所有答案都是预期的、以程序员为中心的,但如果你的公司在源代码之外使用版本控制怎么办?有很多文档并不属于源代码,但从版本控制中受益,应该与代码紧密结合而不是在另一个CMS中。大多数程序员不是孤立工作的,我们作为团队的一部分为公司工作。
考虑到这一点,在Subversion和git的客户端工具和培训方面比较易用性。我无法想象有哪种分布式版本控制系统会更容易使用或向非程序员解释。我希望被证明是错误的,因为那样我就能评估git,并且有希望得到需要版本控制而不是程序员的人们的接受。
即使如此,如果管理层问我们为什么要从集中式转向分布式版本控制系统,我也很难给出诚实的答案,因为我们没有这个需求。
免责声明:我早期(大约v0.29)对Subversion产生了兴趣,所以我显然有偏见,但自那时以来我为工作的公司提供了支持和鼓励,他们正在受益于我的热情。我怀疑在许多软件公司中都是这样发生的。随着如此多的程序员加入git车队,我想知道有多少公司会错过在源代码之外使用版本控制的好处?即使你为不同的团队使用单独的系统,你也会错过一些好处,比如(统一的)问题跟踪集成,同时增加维护、硬件和培训要求。

2
“大多数程序员不是孤立工作的”似乎暗示会计师/市场人员必须使用存放源代码的同一仓库。我看不出这样做的好处;我的一些前公司想要在这方面实现标准化,但最终都失败了。我认为这种简单化的方法对于经理来说可能很好,但对于程序员团队来说却是一种过度简化 - 因此将它们统一起来会导致糟糕的妥协。 - inger
2
@inger 我认为你不能说“这是唯一有效的理由”,据我所知,Subversion的工具支持要比Git优秀得多,例如TortoiseSVN和与Visual Studio和Java IDE(如Eclipse)的集成。这可能对你来说不是问题,但对我们来说肯定是问题。我没有在我的答案中提到它,因为这是一个单独的问题。 - si618
非程序员本来就会遇到Subversion的问题。最好给他们一个实际的文档发布应用程序,它具有版本控制,而不是使用svn-GUI。为什么不在wiki中编写文档并进行修订。甚至有一些由git驱动的维基百科,使用git作为数据存储。程序员应该拥有最适合工作的工具,那就是git或Hg,因为它们具有工作流程的自由。 - Benbob
1
@Keyo,是的,非程序员理解Subversion需要时间,但我认为他们理解git或Hg会需要更长时间。如果Wiki得到维护,那么它们很棒,但根据我的经验,如果文档与源代码相关,开发人员更有可能维护它们。我同意Inger的观点,即符合此类别的文档并不多,但它们确实存在。有趣的是你说git/Hg是最好的工具,这是一个笼统的陈述,可能并不适用于所有情况,git和Hg是否像SVN一样具有良好的集成? - si618
例如,我是指集成到Windows(TortoiseSVN)和Visual Studio(AnkhSVN)。所有的开发者都喜欢使用命令行而不是漂亮的GUI或IDE吗?我的意思是,我认为你不能断言Git/Hg是最好的工具,因为如果人们不喜欢VCS客户端,他们不会使用这个工具,无论它能为你的工作流程带来多少自由。 - si618
显示剩余2条评论

9

Subversion仍然是一个更为常用的版本控制系统,这意味着它具有更好的工具支持。几乎任何集成开发环境(IDE)都有成熟的SVN插件,并且还有一些良好的资源管理器扩展可用(例如TurtoiseSVN)。除此之外,我必须同意Michael的观点:Git并不比Subversion更好或更差,它只是不同。


但是现在,经过几年广泛使用 git 的经验后,我必须反驳自己:Git比Subversion好得多。至少一旦你克服了Git不友好的语法。 - neu242

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接