从早期的diff和patch命令,再到1985年出现的第一个大规模使用的版本控制系统CVS,再到2000年面世的集中式版本控制系统的集大成者SVN,以及目前最广为人知的分布式版本控制系统的代名词Git(2005年面世),版本控制系统领域山头林立,大咖云集。
遁入IT行业多年,从最开始的VCS,到后来的SVN,到TFS,再到Git,用过的版本控制系统也算不少了。时至今日,无论是大公司还是创业团队,Git俨然是首选,SVN不知不觉被人为的贴上了“落后”的标签。作为一名猎奇心极强的青年,我曾多次自问,Git到底好在哪里?“Git是分布式的,每个客户端都是一个完整的代码仓库”,“当你没网的时候,你还可以继续愉快的提交代码”......然而这些教课书上的答案并没有令我心悦诚服。我也曾试图到“知乎”去寻求高论,可结果仍然不过是官方的复述。
回头想象,我们使用SVN的场景。
责职说明:
Trunk:用于各版本开发提交代码
TAG:用于记录和保存每个release/milestone的代码
Branch:用于bug fixing
过程说明:
项目开始时,创建Trunk,开始1.0.0开发
所有小组成员都往Trunk中提交代码
当1.0.0开发完成后,创建一个标签:Tag1.0.0
Tag1.0.0测试完成后,部署到服务器
开发小组开始新版本1.0.1开发,继续提交代码到Trunk中
1.0.1开发完成,创建Tag1.0.1,测试完后部署到服务器
开发小组开始新版本1.0.2开发,继续提交代码到Trunk中
1.0.1运行中发现bug,需要紧急修复 -> 从Tag1.0.1中创建1.0.1bug-fix Branch
Bug修复代码提交到1.0.1bug-fix Branch,测试通过后,部署到服务器
提交到1.0.1bug-fix Branch的代码合并到Trunk中
And so on……
再想象我们使用Git的方式。
分支职责
master : 最为稳定功能最为完整的随时可发布的代码;
develop : 永远是功能最新最全的分支;
hotfix : 修复线上代码的 bug;
feature : 某个功能点正在开发阶段;
相信但凡使用过SVN和Git的高手对上面的流程都不会陌生,虽然上面的描述也许不够严谨,但是却也粗略的反映出我们日常的操作方式。
仔细分析,你会发现其实在团队内部使用Git和使用SVN似乎没有大多的区别。虽然Git本地有完整的代码仓库,但是我们还是要推送到远端,这跟SVN直接提交到远端的中央仓库从结果来看没有根本区别。当断网的时候,通过Git虽然我们可以提交到本地仓库,但是构建工具支持的还是从远端仓库拉取代码进行构建,换而言之,提交到本地其实意义没那么大。
肯定有一些道行高深的朋友要提醒我了,Git最大的优点不就是可以任意的创建分支吗?
是的,因为技术实现的区别,导致SVN里每一个分支其实都是一套完整的且独立的目录,创建一个分支,需要将当前分支的内容复制一份到另一个目录,而且因为是集中式,每一个分支都会在服务器存在,导致分支的创建以及合并效率非常低下,而且受限于磁盘容量和IOPS,不可能无限制的创建分支以及在分支上开发;而Git每一个分支其实就是一个引用,它记录的是最近一次提交树的ID,同一份文件只要没有更新,就不会多次存储,因此Git创建分支和合并分支都非常流畅。
嗯,听起来很不错?那么问题来了,为啥用过Git的人,对于“Git比SVN好在哪里”回答的那么不确定呢?
作为用过几款版本控制系统的“砖家”,我认为相比SVN,Git有两点核心优势,其一是对多分支的友好支持;其二就是与远程仓库完全对等的开发者个人仓库,这也是关键。
我们先说说多分支的友好支持。
其实多分支开发模式本身是针对多人协作开发单体应用的情境而提出来的,在这种模式下,如果大家都挤在同一个分支,经常会出现合并冲突,解决起来往往一身汗水。而现今微服务开发大行其道,传统的单体应用被按照一定的内在规则拆分成多个微服务,每一个微服务同一时间一般只有一个人在开发维护,因此,几乎不存在合并冲突,而且因为是单人负责,那么负责人可以对接收到的需求进行合理的规划,迭代开发,因此,也不需要开设很多的功能分支去应对,一般固定的develop—>qa—>master分支,毕竟多个分支同时开发虽然听起来很酷,当你合并起来,就会发现远没有那么轻松了,合并分支出错的事情可不鲜见。因此,在如今的开发风潮下,Git“多分支友好支持”的特性并没有被施展开来,而少量的分支SVN也是可以应付的。
我们再谈谈Git最引以为傲的【与远程仓库完全对等的开发者个人仓库】,也就是分布式特性。
在开始这个问题之前,我们先谈谈企业和开源社区的区别。
企业的本质是管理,管理的本质是集中控制,目的是尽可能让实际符合预期,减少不确定性。社区的本质是交流(注意是交流而不是协作,协作是多个平等个体为某一个预设目标而开展的工作,目的是收敛而明确的;而交流则是多个平等个体以开放的心态进行沟通,不需要明确的目标),交流的本质是尽可能让实际超出预期,寻求更多的意外收获。
管理分为两个维度,一是正向引导,包括规范,流程,文化等,另一个就是风险防范。
源码作为公司的资源之一,而且是实现业务目标的重要资源,从正向来说,公司都会制定一套源码使用的规范,从风险防范来说,一些公司会针对不同的角色限定源码的访问权限。因此,公司根本不需要有与远程仓库完全对等的开发者个人仓库,即使使用了Git,这些功能其实也是被忽略的,你想想不是嘛?
开源社区则不然。社区的本质是交流,在开源社区,交流的则是承载了开发者理念的源码。因此,核心开发者希望自己的代码仓库被更多人的fork,希望自己的理念或成果可以影响更多的人,而对于通过fork创建了个人仓库的开发者而言,一方面他可以自己维护自己的仓库,独立的演进,增加自己认为好的想法,同时也可以将这种想法申请合并到核心开发者的仓库,一旦被接受,那么他的理念或成果将继续流传下去。甚至某些开发者还可以再次将自己的仓库开源出去,期待被别人fork。于是形成了环绕在核心开发者周围的外延式的以源码为媒介的放射状交流圈,并且圈子还在不断的扩散,围绕某些节点又有新的圈子形成。开源社区这种 “特性功能自治,共性功能共享”的特点,非常契合Git的本地仓库和远程仓库既可独立又可合并的特性。
因此,真正让Git大放异彩的其实还是开源项目。
我们再看看Git的起源。Linux内核最初使用的是BitKeeper作为源码管理工具,后来BitKeeper不再免费提供,Linus于是自己写了个Git,当时Linux社区已经非常热闹,全球各地大量的开发者fork自己的代码仓库,又申请合并到核心仓库。核心仓库内,也是大量的开发人员同时在工作,每人负责不同的模块。这种情况下,Git被设计成【多分支友好】以及【与远程仓库完全对等的开发者个人仓库】也就是自然而然的事情了。
总体来看,Git确实“天生丽质”,然而她的“美”需要在“开源社区”的簇拥下才能尽情的绽放。
领取专属 10元无门槛券
私享最新 技术干货