2019杭州云栖大会大咖有约,由阿里巴巴·研发效能部·代码基础技术团队负责人蒋鑫(Git项目贡献者、《Git权威指南》作者)主讲“Go Git:面向未来的代码平台”。专题围绕版本控制系统的历史、现状和未来,尝试回答一个问题:未来的版本控制系统是什么样的?还会是Git么?
以下为精彩视频内容整理:
作为Git项目的贡献者、本地化的国际协调者,主讲人开场给大家奉献了一个小窍门,和一个链接(开源电子书):
- 一个让你超越90%的Git用户的小窍门:如何分析一个开发者在项目中的提交。例如查看某个目录之外的贡献:
- log --author "Author" --no-merges --oneline -- ":(exclude)po/"
- 《Git权威指南》原稿链接:https://github.com/gotgit/gotgit ,已经拥有500个forks和900个stars。
SVN是2000年诞生的,5年之后诞生的 Git 最终超越、替代了SVN。Git 已经快15岁了,目前为止仍然是用户最喜爱的版本控制系统,那么再过15年,Git会被什么替代?
一、 未来——在火星上编码
在电影里,人类已经开始殖民火星。一个大胆的设想,未来人类会在火星上编码!
光速作为难以突破的物理极限,从火星到地球,通讯有至少8 分钟的延迟。在如此长的时延下,使用依赖中央服务器的集中式版本控制工具,这几乎是不可能实现的。由此推断在火星上使用的版本控制系统需要有如下的特性:
- 是分布式的,能够本地克隆以及离线操作。
- 构建一个火星版的CDN,也许是一个好主意。
二、过去——版本控制历史发展脉络
在Git诞生10周年时,Linus Torvalds说Git之所以能够流行,主要原因不是Git速度快,或者它更安全,而是“politics”。
SVN就是一个典型的politically incorrect的版本控制工具。这里的“政治”指的是:SVN不允许所有人向仓库贡献代码,这是因为SVN如果向所有人开放仓库的写授权,代码质量无法控制。
而Git是一个politically correct的版本控制工具。这是因为使用Git,用户如果能够读到一个仓库,就可以将其完整的克隆下来,然后在自己下载的本地仓库中提交代码,并且通过各种手段分享给其他人。
2008年出现的GitHub之所以大获成功, “political correctness”功不可没。GitHub发明的“fork(派生)和pull request”的功能,让协同更加简单,用户只要点几下鼠标,就能完成代码的分享。当前大多数代码平台都拷贝了GitHub的这种协同模式。
但是GitHub的“fork + pull request”模式给用户带来新的苦恼,如何让派生出来的仓库和源仓库保持同步?尤其在公司的内部环境下,用户可信,派生带来的同步成本使得用户通常会舍弃GitHub的派生模式,转而在一个仓库下使用多分支的方式来协同,而这又带来高昂的维护成本,管理混乱。
阿里内部提供了一个集中式的解决方案,仓库不需要派生,也不需要创建多分支进行协同。仓库只有一份,分支也仅有几条,作为开发者像使用正常Git仓库一样进行push,当进行push时,会通过一层过滤器,过滤器的作用是把代码直接变成一个代码审核任务,而不会在仓库中创建任何的可见的多余分支。
此外我们还做了一个配套的命令行工具:git-repo。这个工具,即可以针对单仓库使用,也兼容安卓的repo工具对多仓库项目进行管理。(PS:问答环节一个同学问到多项目用配置文件关联的问题,可以用git-repo来解决。)阿里巴巴开发的这个新颖的工作模式和git-repo将会在2019年年底开源。
未来版本控制系统,类似于阿里巴巴的集中式代码评审,将会成为主流。
三、 现在——大仓库问题
2005年Linux kernel的代码仓库只有不到100M,到目前为止Linux kernel的仓库的代码量已经接近4GB。Windows的代码也放入Git仓库里,大概有300GB。如此大的仓库将会遇到很多问题,有服务端的问题,也有客户端的问题。问题的本质是Git本身的数据结构并不是常见的结构化数据,不是数据库,而是一种半结构化数据,检索速度相对比较慢。
Git已经做了很多的努力。比如:
- 克隆一个仓库,开始的一段时间会显示一个进度,是在计算客户端要接收的对象数,这时服务端正在计算客户要获取的提交范围所包含的所有对象,这个计算的耗时比较长。Git的Bitmap功能就是针对这个问题的优化。
- Git-graph是微软贡献给Git社区的一个新特性。因为在微软的VSTS显示提交历史的界面中会画出一棵树图,用来显示提交与提交的关联以及分支关系。实时渲染这样一棵树会很慢,于是微软开发了辅助的数据结构git-graph。
- Gerrit中的Reftable则是为了解决引用的快速查询问题。
对于大仓库,GC是一个老大难问题。每向仓库进行一次push,仓库里就会有很多推送过去的松散对象,松散对象过多会导致Git访问时的IO非常高,为此Git的解决办法就是用gc命令将松散对象回收到一个一个的pack文件里。增量创建pack包,会出现越来越多的包文件,在索引一个对象时需要遍历每一个pack文件,于是查找对象的时间复杂度就变成M*logN(M为包文件的个数,N为保文件中的对象数)。而选择用git gc完整压缩只生成一个大的pack,则会非常耗时,对于像微软的300GB的代码仓,简直是不可能完成的任务。社区的一个解决方法是multi-index:为多个pack文件创建multi-index索引,将查询对象的时间复杂度降到O(logN)。
同时客户端也有瓶颈。在面对300GB的仓库时,用户可能只需要最新的提交,或者是部分目录下的代码,历史的几百个G的历史数据不需要,那么怎样将其下载下来?Git现有的工具有shallow clone(分层克隆)、sparse checkout(稀疏检出)可以有选择的检出部分文件、目录。Git-LFS是GitHub开源的工具,解决的问题是将二进制数据不存放在仓库里而放在其他系统中,如阿里云的OSS存储里。GVFS是微软开发的,客户端只克隆仓库的元数据,按需下载,这是解决上述问题的一个很好的方案。但是GVFS依赖于Windows操作系统、特殊的文件系统。而Git正在研发的一个叫做partial clone的功能,会实现类似的按需检出的功能。
断点续传也是用户的一个痛点。是指在克隆一半的时候失败了只能从头再开始,解决这个问题是很困难的,因为服务端是有状态的,会计算所要获取的对象并临时打包。阿里下一步会通过客户端解决这个问题。
此外,Web IDE和构建加速领域里都需要涉及克隆、重建仓库中的代码,很耗时。一个理想方案是zero time checkout、FUSE、分布式存储。把仓库里的数据放在云存储里,不需要检出,不需要克隆,以解决这一类需要直接访问代码仓库的场景。
总之,针对大仓库场景,Git有望在近几年实现体验的提升。
四、现在——多“分支”和响应延迟问题
很多Git用户都可能遇到过这样一个问题:在克隆一个分支(引用)非常多的仓库时,往往挂起几分钟,在这几分钟里得不到任何服务端的响应,好像是客户端进程死掉了。这是因为Git 协议1.0(注意协议版本和Git版本概念不同),服务端要告知客户端所有的引用,这个过程是静默的,也就是为什么复杂仓库在连接阶段非常耗时的原因。Git正在开发2.0版本的协议正是为了解决这个问题。
当使用Git Protocol 2.0时,想克隆哪个分支,服务端就会告知这个分支,而不是将所有的分支都返回。此外,客户可能更需要的一个功能是:当仓库克隆下来之后,下次再同步时,希望可以查询到从上次同步时仓库的变化,以便增量下载。这个功能可能通过类似reftable的功能来实现。
五、现在——其它问题
- 安全性
Git正在做从SHA1 到SHA256的迁移,当完成迁移之后,会发现仓库的提交号为40字节的十六进制数字,变成SHA256之后的64个字节的十六进制数字。 - Git的适用范围
Git的主要场景是针对代码等文本文件的版本控制。很多专业领域,如3D建模,不能很好地进行版本控制。Git可通过 clean、smudge 过滤器、diff driver,来扩展版本控制的领域。 - AI
阿里正在做AI方面的探索,主要针对在智能评审、智能搜索、智能运维、质量、安全、提效等领域。
六、未来的代码平台
未来的代码平台:
1.有可能不是Git,但是会非常像Git。
2.是一个分布式的版本控制工具,可以克隆,可以在本地做提交。使用集中式的模式,允许任何人、在任何地点向大仓库里推送任何东西,并且通过结构化数据来提速,使大仓库的性能变得更好。
3.当远程克隆一个仓库时,CDN可以提供帮助使仓库克隆得更快。尤其像中美之间,由于物理、网络差异没办法访问服务的情况下,CDN就会发挥相应的作用。
4.在很多领域,比如Web IDE领域,能够实现代码零耗时的获取。
5.代码智能化。