摘要

本文给大家剖析了一个有趣的现象:IT 业界使用*广泛的版本管理系统 Git,却不被硅谷*的科技公司 Google、Facebook 等垂青的原因。分析了 Google 的版本和分支管理模式、Git 的设计理念和存储结构,为企业 IT 的决策者提供一个版本管理系统技术选项的决策思路。

%title插图%num

背景

版本控制系统(VCS,Version Control System),或叫源码管理系统(SCM,Source Code Management)是几乎所有IT人员都熟悉和每天工作使用的工具。提到 VCS,你会想到哪个工具?估计大部分人都会想到 Git,尤其对于85后年轻一代 IT 人,甚至可能只知道 Git 这一种版本管理工具。

Git 是目前*流行的代码版本管理工具。它*初由 Linux 之父 Linus Torvalds 开发出来,Linus 2007年在某次演讲中提到他开发 Git 的几个准则:

•分布式:代码存储在多个机器、每个副本是平等的、支持离线工作•高性能:每次 commit、branch、log、diff 等操作都非常快•可靠:确保从 Git 签出(Checkout)的代码跟签入(Checkin)的代码完全一致

除了 Git,业界流行的版本控制系统还有 Subversion、Mercurial等。

%title插图%num

问题

Git 是一个非常适合开源社区的优秀的版本管理系统。但包括 Google 和 Facebooke 等多个硅谷巨头都没有采用,微软 Windows 开发团队虽然用 Git,但用的是经过深度改造后的 Git。很奇怪,对不?

其实,Google 公司并非完全没有考虑过采用 Git,Linus 本人在 2007年曾到 Google 公司进行过一次介绍 Git 的演讲,有兴趣的朋友可以参考:Linus 在 2007 年 Google Talk 上介绍 Git。当时 Google 采用一个商业软件 Perforce 作为代码版本管理工具,正为 Perforce 无法继续支持 Google 巨大代码仓库而寻觅替代方案。但*终 Google 选择了基于 Bigtable 自行研发版本管理工具 Piper,而没有采用 Linus 大神开发的、名满天下的 Git。

这到底是为什么呢?

%title插图%num

答案

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

首先,让我们来看看 Git 是否(比其他流行的版本管理工具)更好,甚至*好。以 Git 市占率成为第1前*流行的 Subversion(简称 SVN)来对比。

在美版知乎网站 StackOverflow 上曾经有一个问题《Why is Git better than Subversion?》,被采纳的高赞回答是这样说的:

Git is not better than Subversion. But is also not worse. It’s different.

是的,只是 different。有哪些不同呢?从 Git 官网的介绍和 Subversion 官网的介绍可以看出来:

# Git Subversion
#1 distributed centralized
#2 branching and merging simplicity of its model and usage
#3 small and fast wide variety, from individuals to large-scale
#4 data assurance reliability
#5 open source open source

上表是 Git 和 Subversion 官网强调的几个特性,我们来分析一下:

1.分布式和中心化,Git 和 Subversion 完全不同的思路;对于开源社区(比如 Linux),显然分布式更合理,但对于商业公司,恐怕中心化更方便运维和备份;2.Git 更强调低成本的分支(和合并),Subversong 也支持分支和合并,但更强调简易的模型和易用性;3.Git 强调的是轻量和快(性能),而 Subversion 强调多用途(不仅仅是代码,还支持二进制文件)和规模;4.说法不同本质一致,强调数据的可靠性;代码是 IT 公司的核心资产,可靠性怎么强调都不为过;5.都是开源和免费的软件;

Git 非常适合开源社区

开源社区的核心诉求是开放、自由、共创,因此对版本管理系统的需求是:

1.开发者随时都可以克隆和分叉任意一个代码库;2.开发者都可以在自己的分叉或分支上为所欲为;3.开发者可以按自己意愿把源码存储在任何机器上,不论是自己的 PC 还是 Github服务器;4.开发者可以发起合并回原代码库的请求(Pull Request),而是否接受则由原项目所有者决定。

因此,Linus 设计的 Git 非常强调分布式(Distributed),以满足开源社区的代码存储自由;另外,*低成本的分支(branching)、分叉(fork)和合并(merge),满足开源社区自由分叉代码和合入的需求。

依托 Linus 本人的超级影响力,加上 Git 本身非常适合开源协作的特性,Git 几乎成为开源社区唯一的代码版本管理系统。

Git 并不特别适合企业

然而,Git 并不适合企业,尤其是企业中大型的软件系统。因为企业对源代码管理的诉求截然不同。源代码作为 IT 企业或企业的 IT 部门*核心的资产,管理需求是:

  1. 安全:包括代码权限(代码访问权限可控)和数据安全(不丢失、一致性);
  2. 易用性:简单的代码签出(Check-out)、嵌入(Check-in)、分支、合并等操作;
  3. 多种类的资源版本管理,包括源代码,也包括资源文件(图片、音乐、视频、设计文件等);
  4. 规模:支持数百 GB 甚至 TB 级规模的代码仓库,设想一个数千人的开发团队超过10年代码积累的大型软件,这个规模的代码仓库是完全可能的。

而这,恰恰就是 Google 为例的大型 IT 公司所需求的。Linus 2007年在 Google 的演讲中,2名 Google 员工提出了2个问题:

1.如果你有一个超级超级大的代码库(repository),想用 Git 来管理,还不能让业务中断6个月,你怎么做?2.使用 Git 怎么只 pull 代码库的其中一部分 path?

Linus 大神没有正面回答这2个问题。

事实是:Git 做不到。

Git 之所以无法存储巨大的代码库,也无法clone、pull、push 代码库文件树的某个分支,是由其存储结构和设计理念所制约的,并不是简单增加一个特性就可以解决的。这也是为什么 Google 员工2007年就向 Linus 提出这2个问题,但到今天为止,Git 仍然不能支持的根本原因。(后来版本的 Git 支持通过 filter 和 sparce checkout 只克隆/拉取某些目录的代码,但性能非常低)。

在 Git 对象模型里,所有对象都以 SHA-1 id 表述,包括4类对象:

  1. blob:用于存储文件数据;
  2. tree:可以理解为目录,它指向其他目录或blob;
  3. commit:一棵代码树的提交点;
  4. tag:标记特别的提交(commit),通常用于标记某次发布;

其中,tag 和 branch 只是指向 commit 的一个指针。Git 的核心存储在于前3者。其结构如下图:

%title插图%num

更详细的 Git 存储和访问机制,超出本文的范畴,关注本公众号,我将在未来分享。

源码管理系统的选型取决于研发流程

除了上面所述的考虑因素,源码管理系统的选型*重要的还是取决于研发流程,尤其是分支和版本关联

Google 的分支和版本管理原则包括:

  1. 基于充分测试的主干开发:这意味着并不需要太多分支、代码集中式存储;
  2. 基于大仓源码的主干依赖:就是把所有的模块和子工程都放在同一个代码仓库中,代码间以源码的主干版本为依赖,所以代码仓库会非常巨大。

这2点,都是 Git 无法满足的。

综上所述,Git 并不适合类似于 Google、Facebook 等采用单体代码仓库、主干开发模式的 IT 企业。因此,Google 于2007年自行开发了一套版本管理系统 Piper。可惜 Google 并没有开源出来。

*终结果:Google 在2007年前采用商业软件 Perforce 作为其源码管理系统;2007年后自行研发 Piper 替代;Facebooke 则采用经过深度改造的 Mercurial 系统。

Google 和Facebook 这2个硅谷巨头都没有采用*留下的 Git 来管理源码,根本原因在于其研发流程的核心:

  1.  主干开发;
  2. 基于大仓源码的主干依赖;

%title插图%num

总结

代码版本管理系统的技术选项,对于整个 DevOps 流程的效率和质量有着重要的影响,而且一旦选定,往往迁移成本*大。作为企业 IT 部门的决策者,务必非常审慎的做决策。建议至少从以下维度评估:

  1. 研发流程是主干开发,还是分支开发;
  2. 代码模块之间(包括对公司内部和第三方)的依赖,以制品(编译后的jar、so等二进制或字节码包)还是源代码形式;
  3. 版本发布模式:主干发布、还是分支发布;
  4. 代码的开放程度:是企业全部开放,还是需要局部开发;
  5. 代码的安全要求;

经过多维度的评估,能让企业 IT 的决策者作出更准确的决策。