Blog Email GitHub

14 Dec 2010
Git与svn的不同

以前写过一个blog:Git初学习,现在读来觉得当初对于git的理解真的很肤浅,现在就来说说git与svn的不同:

  • 分布式。这是git最明显的一个特征,分布式SCM。分布式也就要求,分布式中的每台机都保存了整个代码仓库所需要的所有代码和资源,而不仅仅是当前最新版本。分布式也带来很多好处:可以在离线的情况下版本控制;另外与集中式SCM不同,即使服务器挂掉也无妨,可以采用任何一台机进行恢复。
  • 版本。svn的版本有着revision的概念,版本号是递增的。版本号能够递增,也是因为svn是集中式SCM的缘故。当多个用户同时提交时,svn服务器会将用户之间的提交操作串行。git是分布式SCM,没有递增的版本号,git采用的做法是:在保存到git之前,git将所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引,作为版本号。
  • 储存方式。svn每个版本提交时,保存的是当前版本与上个版本之间的diff。而git提交时,则是快照。比如git commit了文件A和B,则提交完成后,至少创建了5个对象,新的文件BLOB对象A和B;一个记录着目录树内容及其各个文件对应BLOB对象索引的tree对象;一个包含指向tree对象(根目录)的索引和其他提交信息元数据的commit对象。如果当前代码仓库还有文件C,由于文件C并没有修改,所以tree对象中保存的便是上个版本文件C的BLOB对象的索引。但是一旦文件被修改,比如A和B,就会创建一个新的BLOB文件对象,而不是仅仅的快照。git这种做法虽然牺牲了存储空间(现在存储空间很廉价的吧),但是当比较两个版本或者合并分支的时候,速度上会有明显的提升。
  • 真正的分支和tag。使用过svn都知道,svn中的分支和tag都是我们认为赋予的概念,都是通过svn copy复制到另外一个目录,通过目录或者人为命名标记为分支或者tag,并且人为的规定:tag是只读的,不能修改,而实际上可以修改的。而git则实现了真正的创建一个分支很简单,仅仅是创建一个branche对象,其中branche对象包含有指定commit对象的校验和(即版本号),当随着开发的进行,提交新版本时,branche对象直接修改版本号即可。创建tag也是如此,新建一个tag对象,包含指定commit对象的校验和和其他数据信息。这也就是为什么在git下,创建分支和标签为什么这么快的根本原因。