版本控制系统工具:Git/Subversion/CVS/hg对比区别比较优缺点选择开源分布式

1.1 起步 – 关于版本控制

关于版本控制

什么是版本控制?我为什么要关心它呢?版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。在本书所展示的例子中,我们仅对保存着软件源代码的文本文件作版本控制管理,但实际上,你可以对任何类型的文件进行版本控制。

定義

一個版本控制系統 Version Control System (VCS),通常有以下功能

  1. 建立 Repository (儲存庫),用來保存程式碼。
  2. 方便散佈程式給團隊,有效率協同開發 z
  3. 記錄誰改變什麼、在什麼時候、因為什麼原因 z
  4. Branch(分支),可因不同情境分開開發
  5. Tag(標籤) 重要里程碑,以便參照

那麼,什麼東西要存進Repository呢? 簡單來說,就是所有跑起來這個專案需要的東西,包括所有原始碼、範例設計檔、文件等等。而像是暫存檔、log 檔案、build files 等編譯後的產物則不需要存進 Repository

如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能)。采用版本控制系统 (VCS)是个明智的选择。有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态。你可以比较文件的变化细节,查出最 后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。使用版本控制系统通常还意味着,就算你乱来一气把整个项目 中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。但额外增加的工作量却微乎其微。

本地版本控制系统

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单。不过坏处也不少:有时候会混淆所在的工作目录,一旦弄错文件丢了数据就没法撤销恢复。

为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异(见图 1-1)。


图 1-1. 本地版本控制系统其中最流行的一种叫做 rcs,现今许多计算机系统上都还看得到它的踪影。甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 rcs 命令。它的工作原理基本上就是保存并管理文件补丁(patch)。文件补丁是一种特定格式的文本文件,记录着对应文件修订前后的内容变化。所以,根据每次 修订后的补丁,rcs 可以通过不断打补丁,计算出各个版本的文件内容。

集中化的版本控制系统

接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这 已成为版本控制系统的标准做法(见图 1-2)。


图 1-2. 集中化的版本控制系统这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

事分两面,有好有坏。这么做最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。要 是中央服务器的磁盘发生故障,碰巧没做备份,或者备份不够及时,就会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端偶然 提取出来的保存在本地的某些快照数据就成了恢复数据的希望。但这样的话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。本地版本控制系 统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

分布式版本控制系统

于是分布式版本控制系统( Distributed Version Control System,简称 DVCS )面世了。在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来 的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份(见图 1-3)。


图 1-3. 分布式版本控制系统更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

Subversion是一个自由,开源的版本控制系统。在Subversion管理下,文件和目录可以超越时空。与CVS, Subversion 等不同的是Git采用了分布式版本库的方式,不必服务器端软件支持,使源代码的发布和交流极其方便。究竟哪个更好些呢?

Subversion 属于集中式的版本控制系统

●每个版本库有唯一一个“官方地址”,每个用户都从这个唯一地址获取代码、数据;

●获取代码库的更新,也只能连接到这个唯一的代码库,同步以取得最新数据;

●提交必须有网络连接(非本地版本库);

●提交需要授权,如果没有授权,提交失败;

●提交并非每次都能够成功。如果有其他人先于你提交,会提示“改动基于过时的版本,先更新再提交”… 诸如此类;

冲突解决是一个提交速度的竞赛:手快者,先提交,平安无事;手慢者,后提交,可能遇到麻烦的冲突解决。

Git属于分布式的版本控制系统

●众生平等,每个检出(checkout)的版本库,或者更准确的说每个克隆(clone)的版本库都是平等的;

●你可以从任何一个版本库的克隆来创建属于你自己的版本库,同时你的版本库也可以作为源提供给他人,只要你愿意;

●获取版本库的更新,可以来自任何源;

●你可以从张三那里获得上游的改动,包括张三自己的提交;你也可以从李四那里获得上游的改动,也可能包括李四的提交;

●提交完全在本地完成。无须别人给你授权,你的版本库你作主;

●当然你在你的版本库中的改动是否别人愿意合并到他们的版本库则是另外的一回事了;

●提交总是会成功,因为提交是在本地进行的么;

●甚至基于旧版本的改动也可以成功提交,提交会基于旧的版本创建一个新的分支 ;

●冲突解决不再像是SVN一样的提交竞赛,而是在需要的时候才进行合并和冲突解决 ;

●Subversion的提交竞赛,在多人协作开发时,提交经常被打断;

●Git的每个用户就好像工作在独立的 Feature Branch(功能分支)中 ;

●Git的提交不会被打断,直到你的工作完全满意了,PUSH给他人或者他人PULL你的版本库;

●合并会发生在PULL和PUSH过程中,不能自动解决的冲突会提示您手工完成;

●Git也可以模拟集中式的工作模式;Subversion只有一种集中式的工作模式;

●所有人都和服务器同步,提交直接到服务器上;

●Git也可以模拟集中式的工作模式 ;

●Git版本库统一放在服务器中;

●可以为 Git 版本库进行授权:谁能创建版本库,谁能向版本库PUSH,谁能够读取(克隆)版本库;

●团队的成员先将服务器的版本库克隆到本地;并经常的从服务器的版本库拉(PULL)最新的更新;

●团队的成员将自己的改动推(PUSH)到服务器的版本库中,当其他人和版本库同步(PULL)时,会自动获取改变;

●Git 的集中式工作模式非常灵活;

●你完全可以在脱离Git服务器所在网络的情况下,如移动办公/出差时,照常使用代码库;

●你只需要在能够接入Git服务器所在网络时,PULL和PUSH即可完成和服务器同步以及提交;

●Git提供rebase命令,可以让你的改动看起来是基于最新的代码实现的改动;

●Git有更多的工作模式可以选择,远非 Subversion可比。

对于软件开发者或者往大了说,有知识管理或者数据管理需要的数码人,是否使用版本控制系统,肯定已经不再是一个问题。但 是选用什么版本控制系统呢?这真是一个问题。我会告诉我的大部分客户,您可以仍旧选择Subversion作为主要的版本控制工具(CVS早已被我们淘汰 了,见附:SVN和CVS的比较),但是分布式版本控制系统,在特定场合诸如:异地协同开发、移动办公/开发、涉密项目的封闭式开发都有着各种不同的应 用。如果采用类似我们公司的开源开发模式或者是内部开源模式,那么 Git 可能是您的首选。这篇博文以我们群英汇自己公司的版本库变迁历史,和网友共享…SubversionSubversion 是群英汇支持的最重要的产品,我们服务的大多数客户,都或多或少的选择了我们的版本控制服务。群英汇为客户提供Subversion版本控制服务,从培训、应用部署、系统整合到售后服务、技术支持。我们公司的部分项目使用了Subversion版本控制系统,如:·             pySvnManager:托管在SourceForge上·             FreeMind-MMX: 托管在SourceForge上·             WordPress的CoSign-SSO插件:位于官方的Subversion库中我们公司内部的开发在2007年以前,也主要使用Subversion,但是之后,我们的代码库逐渐的向分布式版本控制系统迁移:·             先是Hg:Hg是水银的化学元素符号,全称为Mercurial。·             后来是Git:Git 是 LinusTorvalds 继Linux后的又一个伟大发明,为全人类的另一个伟大贡献Hg/MercurialHg走入我们的视线,是因为我们研究的项目都一个一个脱离Subversion阵营,转向Hg,使用Hg作为各自项目的版本控制工具。其中一个我们主要研究的项目是:MoinMoin维基。使用Hg后,困扰我的问题迎刃而解,就是:·             我们的软件开发模式是基于成熟的开源软件进行定制。项目的原始代码库称为上游,我们自己的代码库称为下游;·             使用Subersion,我们采用Subversion的Vendor分支(或称卖主分支)来管理我们的代码·             一但上游软件软件出现新的版本,我们代码的迁移就成了最让人头痛的事情,可能好几天都不能搞定;Hg可以很好的解决这个问题,原因在于:·             Hg是分布式版本控制工具,整个代码库都在本地,浏览变更历史速度超快,实际上是本地访问,不再受制于网络。这样我们就可以更快的建立和上游版本库的同步,尽早尽快的解决代码合并问题,而不是要等到新版本发布;·             Hg的最佳拍当MQ!简直就是为我们的开发模式所设计的。Subversoion的卖主分支和MQ相比就好像马车和火箭的对比。·             Hg简单,并且使用习惯和Subversion非常相似,这也是为什么我们公司的版本控制系统在转向 Git 后,仍有部分项目在使用 Hg的原因群英汇的Hg开源代码库:·             http://bitbucket.org/ossxp_com/Git有了Hg,为什么还要用git?·             和Subversion代码库同步的需要。o                虽然svn可以镜像远程代码库,但镜像库不能提交o                Hg不支持分支,因此无法完全克隆一个Subversion代码库o                Git有着完备的分支支持,可以将远程svn库镜像为一个本地的git库,而且可以提交甚至远程提交·             Git速度更快。如果你用过git和hg,你就会对我说的有所感觉:o                Hg提交/克隆/push/pull,我经常对自己无所事事 而感到恼怒,感觉就像傻子一样,完成了多少?1%还是99%?o                Git速度超快不说,整个过程有着详尽的提示,真是体贴备至。·             Git+Topgit很好的支持上下游的协同开发o                Hg的MQ虽然很好,但是Git有Topgit,而且Git的rebase功能更成熟o                MQ可能更适合单人开发,但是没有办法对补丁之间建立依赖关系o                Topgit采用分支来管理补丁,而且可以在分支之间设置依赖,可以是代码更整洁群英汇的开放Git代码库:·             群英汇在github上的开源代码 (请使用 firefox浏览器)·             我们自己网站上的gitweb演示:http://git.ossxp.com/·             我们项目管理平台大多数项目也是和git版本整合:Redmine项目参考阅读:·             Why Git is Better than X·             Version Control System Comparison·             Version control systems comparison·             CVS vs Starteam附:SVN和CVS版本控制比较(淘汰CVS的理由)SVN 和 CVS 同为开源的集中式版本控制工具。随着 CVS 的一天一天老去,越来越多的缺陷被暴露,SVN 正是被设计用于替代 CVS 的。§                 几个GB甚至十几个GB的 CVS 库的问题:§                         分支代价大,创建一个里程碑需要的时间?§                         CVS创建里程碑/分支一直是这么慢么?§                 目录和文件名的版本控制§                         如何重命名的?以破坏历史为代价的重命名?§                 file base 的 VCS,不支持 transaction§                         为什么tag在CVS那么重要?──file base§                 认证方式单一,安全性差§                 二进制文件支持脆弱,易破坏§                         忘记 -kb ?§                 CVS代码维护停滞,停止演进。第三方支持工具少

GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。如果你是一个具有使用SVN背景的人,你需要做一定的思想转换,来适应GIT提供的一些概念和特征。所以,这篇文章的主要目的就是通过介绍GIT能做什么、它和SVN在深层次上究竟有什么不同来帮助你认识它。

那好,这就开始吧…

  1. GIT是分布式的,SVN不是:这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。如果你能理解这个概念,那么你就已经上手一半了。需要做一点声明,GIT并不是目前第一个或唯一的分布式版本控制系统。还有一些系统,例如Bitkeeper, Mercurial等,也是运行在分布式模式上的。但GIT在这方面做的更好,而且有更多强大的功能特征。GIT 跟SVN一样有自己的集中式版本库或服务器。但,GIT更倾向于被使用于分布式模式,也就是每个开发人员从中心版本库/服务器上chect out代码后会在自己的机器上克隆一个自己的版本库。可以这样说,如果你被困在一个不能连接网络的地方时,就像在飞机上,地下室,电梯里等,你仍然能够提 交文件,查看历史版本记录,创建项目分支,等。对一些人来说,这好像没多大用处,但当你突然遇到没有网络的环境时,这个将解决你的大麻烦。同样,这种分布式的操作模式对于开源软件社区的开发来说也是个巨大的恩赐,你不必再像以前那样做出补丁包,通过email方式发送出去,你只需要创建一个分支,向项目团队发送一个推请求。这能让你的代码保持最新,而且不会在传输过程中丢失。GitHub.com就是一个这样的优秀案例。有些谣言传出来说subversion将来的版本也会基于分布式模式。但至少目前还看不出来。
  2. GIT把内容按元数据方式存储,而SVN是按文件:所 有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。如果你把.git目录的体积大小跟.svn比较,你会发现它们差距很 大。因为,.git目录是处于你的机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签,分支,版本记录等。
  3. GIT分支和SVN的分支不同:分支在SVN中一点不特别,就是版本库中的另外的一个目录。如果你想知道是否合并了一个分支,你需要手工运行像这样的命令svn propget svn:mergeinfo,来确认代码是否被合并。感谢Ben同学指出这个特征。所以,经常会发生有些分支被遗漏的情况。然而,处理GIT的分支却是相当的简单和有趣。你可以从同一个工作目录下快速的在几个分支间切换。你很容易发现未被合并的分支,你能简单而快捷的合并这些文件。
  4. GIT没有一个全局的版本号,而SVN有:目 前为止这是跟SVN相比GIT缺少的最大的一个特征。你也知道,SVN的版本号实际是任何一个相应时间的源代码快照。我认为它是从CVS进化到SVN的最 大的一个突破。因为GIT和SVN从概念上就不同,我不知道GIT里是什么特征与之对应。如果你有任何的线索,请在评论里奉献出来与大家共享。更新:有些读者指出,我们可以使用GIT的SHA-1来唯一的标识一个代码快照。这个并不能完全的代替SVN里容易阅读的数字版本号。但,用途应该是相同的。
  5. GIT的内容完整性要优于SVN:GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。