【干货分享】大话团队的GIT分支策略进化史
作为一名85后的技术男,一转眼10年过去了(一不小心暴露了年龄,虽然我叫18岁fantasy),亲手写代码已经是5年前了,目前主要负责公司的软件产品的规划和设计(所以最近写的东西也主要与设计和产品分析有关)并带着研发团队进行产品落地。偶尔手痒痒写点代码或者和团队讨论一下架构设计啥的,毕竟以前是那么的热爱!
这篇文章主要想写写我所在团队git的使用历程,有些算是回忆吧。~老司机共勉啊~
SVN时代
在刚进公司的时候,那会大家都还在使用svn。代码,原型设计和过程文档都在svn上。大概过了一年,整合svn大小40个G(大概两个千万级项目的代码和文档),每次更新要人命,也给实施团队和方案团队带来了很多困惑,后来就直接把研发从svn上分出来了,但还是svn管理,svn只用来做内部文档管理。
那个时候主要面对项目开发,团队也比较集中,都在北京,项目的特征就是一次性交付,后面有部分变更开发和bug修改。所以从分支上来说基本上就是这样的。
大家都在主分支上开发,然后定时提交,到了上线节点QA把代码checkout下来开始测试。测试完后把bug清单发给研发,研发一顿改,之后提交,QA再回归测试,基本上没问题然后就上线了。
暴露问题:
随着时间的发展,大家有不少时间花在解决冲突上,因为其他人提交了有bug的代码(团队有要求必须自测后提交但,但是自测能力参差不齐),有时候量大了能折腾一上午,基本上最后提交之前都得先本地备份一下,生怕应为冲突而代码丢失了。
引入GIT
随着业务的扩展和团队的发展,北京,武汉,长春都有了研发基地,这种扯皮的事情更多了,并且由于网络的不稳定,很多时候代码提交都出现了问题,通过内部沟通研究,决定将代码管理从svn迁移到公网码云(gitee)上,当时也研究了github之类的。最好考虑还是用了国内的,毕竟还有社区啥的,平时吐个槽看个科技前言新闻也方便。
上了git之后,一开始也只解决了地域问题,大家可以在各自的城市畅通无阻的提交代码了,同时团队也加强了代码审核和自测培训。但是基本上没有分支的概念,那个时候,GIT的使用是这样的。
此阶段解决的问题:
分布式团队,分布式提交。
产生的问题:由于团队要求每天代码必须提交到远程。但是自测结果任然具有不确定,bug还是满天飞,每天一来还是要处理冲突。
引入分支
通过团队讨论,代码每天下班远程提交是必须的,为了防止影响别人,就引入个人分支(团队任务基本上按人按模块分工,前后端不分离),于是就给了每个人或者开发同一个模块的几个人建一个分支(如果同一个分支几个人之间有小矛盾内部自己解决吧),那个时候起名一般按照“项目名_模块名”起名,比如:dxplat_logmgr(下文暂时用git的专用名称feature代替)。每天写完代码,如果还没完成就先提交,然后确定测试完之后再合并到主分支。
解决的问题:
可按地域分布式提交。
可远程提交到自己的分支,不影响主分支。
产生的问题:
项目上线后,一个项目实施(简称A)完之后,另外一个相同业务的项目(B)也中标了,但是需求还不尽相同。并且A项目在质保期,还得修修改改,添添补补。怎么能同时满足这两个项目并发升级上线呢。如果按照以前的方法,就是管你A和B,我就是一个工程,然后最后都是打一个包给你(说到这很多人应该有同感),同时包含A+B。实施人员你去部署吧,上线配置小心点改,A项目改A的参数,B项目改B的参数。
随着时间的推移,同业务域定制的项目越来越多,这样下去不是办法,由于上线时间不一致,主分支都不敢随便提交了,QA正在测试A项目的时候B项目也催的着急,也得提交代码让另外一个AQ测试啊。而且代码也慢慢失控了,改起来别提多费劲了,各种依赖包整的项目臃肿的不行不行的了。
引入release分支
团队讨论之后,决定引入release分支,一个项目上线后,通过master建立release分支用来支撑不同需求的项目,定时选择性的将不同项目里面的模块合并到master,开发人员都基于release做开发,并且这个release会一直保留,因为用户永远都有小心思。同时新的项目来了之后都从mater再创建release去应付新的定制需求。整个开发流程变成下面的情况:
至此这个策略用了至少2年,一直坚持在用。并且对待项目型的开发总体感觉用着还行,网上有人说少了dev分支,团队内部讨论整体感觉对项目型没必要再搞个dev分支,因为项目基本上是瀑布式开发直到上线,中间迭代上先次数基本很少,要上线也是所有需求满足直接上先。但是最后还是用上了。
接着往下发展~
终于公司部分业务产品化了,也面向公众和企业用户了。需求也多了,面对竞争对手也必须快准狠的面对市场了。
总结产品和项目不同的特征如下:
1、项目具有固定周期,项目结项完毕,开发工作也基本结束了,后期修修补补。产品当然也有周期,但是不是客户定的周期,而是企业战略和市场决定。
2、项目基本瀑布式开发,而产品如果竞争激烈,那就必须敏捷迭代,对需求池进行排序,快速跟进。
3、产品和项目都具有可复制特性。但是项目的复制由于客户需求的不同,需求范围有很大的不同,也就是所说的定制化程度高,基本上是方案和设计思想的复制,其他都是大量定制开发。而产品一旦确定用户群和需求痛点这些大方向,基本上是一个线性开发的过程。不断开发迎合市场和企业战略的新需求,废弃没必要和过时的老需求。
云端产品和终端产品的区别:
如果云端产品,那个所有用户都会感知一个版本。而如果是终端产品的话,不同的终端用户群会有不同的产品版本,根据公司策略和客户要求去升级。
那么对于产品化的分支策略,开发需不停的在完成需求池中需求的开发。市场则需根据市场策略上线不同的版本,比如有的功能是技术公关,作为公司与竞争对手的pk点,就不能过于超前上线,以便被抄袭。有的是用户最关心就必须在竞争对手之前上线。
这个时候以前的分支策略问题就来了。必须有一个分支是时刻能上线的代码,而且能记录不同的版本(有的版本上线后有bug,需要修改,但是用户也不需要新功能)。
引入TAG
通过在mater上记录tag来记录每次上市的产品版本,如果这个版本有bug,但是用户当前不需要新的需求,就直接在这个tag上创建临时的分支给用户改bug,改完之后代码将代码合并到master。这个时候我们一般不删除这个临时分支,因为鬼知道后面还有啥bug呢,有点类似于release分支,但是和release不同的是,这个只用来改bug,新的功能开发都必须在mater上。开发流程就变成了这样:
这里面的问题就是QA测试的时候master不能合并新的代码只能改bug。一旦合并新的功能,上线范围就变了,就得重新测试。必须测试完打上tag之后才行。但是有时候公司内部须对全功能进行内部演示和访谈调研,就必须有一个全版本的分钟,而mater作为发布版本,又能随便合并。怎么办呢,就是引入dev分支。
引入DEV分支
具体做法就是创建dev分支,版本上线是,合并到mater,QA从mater上pull代码做测试用于测试上线,有bug建分支改,改完bug,master和dev上都合并。但是这个时候dev上开发的新模块不合并到mater,大家提交还是往dev上提交,内部演示都从dev打包做演示。下次上线依然是提交到mater让QA测试(这一块和网上很多人说的不一样,大家都是从dev上做测试,然后没问题合并到mater)。这样下来分支就变成这样:
有些地方会和网上的会有差别,比如我们是在最后才引入dev分支的。
总结
1、针对项目和产品我们采用了两套策略,项目用release策略,产品用tag策略。
2、另外如果是集中式开发的小团队小项目,只基于mater开发也不是不可,也挺灵活,加上严格的代码审核和自检培训就行了。
3、这里面基本也用到GIT的三种工作流的思想(Git Flow,GitHub Flow,GitLab Flow),加入了自己的一些实践和定制。
关于pull request
对于git中的pull request协作机制,实际应用中也基本没用上,感觉比较适合外包或者开源协作项目(多个不太熟悉的小团队合作开发一个项目)。如果是内部团队,毕竟这种协同机制内部定死也没必要线上处理了。
我们的代码审核时间有时候不在上线前,基本上会周五或者周一由专人进行(一方面审核代码及完善审核规则,一方面培训新人),而并不是提交一个模块就让人审核,这样如果功能点太多,审核人的时间就很零碎。但是上线的功能肯定是审核过了的,而且会有严格的代码测试。
零零碎碎也了很多,欢迎大家一起讨论吧,有问题也欢迎留言提出。