正好这周公司大群里因为代码分支管理有个小小的争论,所以就先顺着这个话题往下写。当然,从技术的角度看,***的结论总是没有哪个方式是对的,哪个方式是错的。所以一切还是要看使用的人或团队。就想屠龙刀落入不同的人手里威力是完全不同的。
Git分支管理策略
Git的分支管理策略,通常的做法有两大“派系”:Git One Track以及Git flow。当然很多人也会混用这两种方式。但是需要澄清一下的是,分支管理不是为了团队“分猪肉”用的,而是参照团队的开发习惯,管理方式做的选择。前面的文章也提过,一个Scrum Team***的规模在7个上下。千万别因为团队规模比较大,为了简单管理,让一个大的团队分出多个分支,然后让不同的小组各自去开发。如果是这样,在同一个产品上(***在同一个可运行的包上)做代码合并,将是个考验你心脏能力的时候。
团队的切分
我们总会遇到需要开发一个比较大的产品的时候,如唯品会要做个订单系统,不可能由7个开发+测试就能搞定的。那么是否组织一个几十人的团队一起做呢?我个人的理解是,还是7人的原则,先从产品入手,将一个大的产品想办法拆分成多个小的产品,不同的小产品间有清晰的接口,这样以小产品的规模来考虑组建团队。每个小产品的团队就可以各自考虑自己的代码分支管理策略了,同时让小产品变成一个可以独立运行的交付物,可以独立做到自包含、自测试,从而做到团队自管理。
Git One Track
One Track通俗来讲,就是整个Scrum Team基本都是围绕Dev分支(或一个版本分支)在开发。无论是每个新的特性也好,修复bug也好,都是在这一个分支上。当然对于同时需要维护多个版本的时候(不是多个特性)的时候,我们需要在多个版本上开发。不过这里需要强调的是,什么时候开出一个版本分支出来需要谨慎,因为当需要修复一个问题或增加一个新的特性的时候就需要人工在不同的分支上都做一次。***的做法是,当一个版本基本稳定下来,从产品的角度看这个版本只是进入维护周期的时候,就可以开出一个新的版本分支。或者是***的代码都是在Dev分支上,当一个版本进行维护期时就开出一个维护分支出来。下图为one track的示意图。
one track
One Track***的特点是:
- Scrum Team都是工作在一个分支上
- 管理简单,通过一个Jenkins的job就可以完成CI/CD
- 每次提交代码前的pull都有可能冲突,如果不同的成员工作在相通的文件上的话
- 为减少冲突,操作经验通常是建议经常pull,不可长时间本地工作
- 每次提交都要确保jenkins的build->Test等job都是必须通过
- 每次提交都是小粒度的Task,而不是大段大段的代码。每个小的task都是runnable的,确保测试容易立即跟进
某种程度上,对于版本策略的选择与团队中开发与测试的配合模式有一定的关系
Gitflow
Gitflow 通常有个理念是任何变更都是一个分支,无论是一个feature还是一个hotfix,都应该以分支的方式进行。这种方式也受到不少人推崇。包括很多工具如Sourcetree也是直接内嵌支持。这个方式从管理上似乎是比较干净的,但是实际上容易进入一个误区从而造成代码merge的麻烦更多。具体什么是Gitflow这里就不啰嗦了,可以看看下面这个图:
gitflow
Gitflow的容易造成的误区:
- 按照人来开分支,目的是为了解决人与人开发间的冲突。这样做***的根源在于将工作“分猪肉”,开发间存在某些配合的局限等。
- 需求/设计管理的缺陷造成将每个feature划分的太大,一个feature要做一周甚至一个月,从而造成该分支与主体脱离太久,不同的分支间冲突太大
- 超前规划,通常为了某种目的,不是开发当期发布版本的内容,而是开始做后面几期或更长远的规划的功能。我们有一种说法叫做“不要过度设计”,但是对于开发而言,更要做到“不要过度开发”
Gitflow从管理上还需要注意额外的成本,包括需不需要给每个feature分支配置相关的jenkins的CI/CD,测试的跟进如何配合特别是测试是与开发同步的情况,容易造成团队的冲突太多因为在一个分支上测试是好的,回到主分支的时候有可能需要重新测试或则测试不通过。似乎这种方式更合适自动化测试比较高,或者适合测试与开发是有明显的界限的团队(但是正如我前面文章提到的我是反对开发与测试间的提测的理念的)。
***,还是那句话,没有***的方式,只有最合适的方式,一切都要看团队的磨合。
版本的管理
无论什么样的开发模式,什么样的代码管理策略,***都是要发布版本的。所以版本的管理尤为重要。但是这里有个误区,版本管理通常被认为是发布。其实版本管理更多是体现在发布后如何推广、如何维护、如何为下一个版本奠定基础的。就是因为很多人误以为版本管理就是一次发布,所以为了避免升级管理等麻烦,总是希望能发布一个稳定的版本就可。然后就有了一个比较可笑的问题,什么时候是“***一个版本”。
如果从产品生命周期来看,所谓的“***一个版本”则意味着产品即将走向“灭亡”。而真正富有生命力的产品则是体现在了版本不断的推陈出新上。
那么什么是版本管理呢?我的理解是体现在以下几个方面
- 每个版本都能体现一个明确的目标,具体完成什么的功能,或者达成某方面的改进如性能KPI等(或者如SRE上所说的KPO)
- 每个版本都应该有对应的推进计划。因为每次有的新版本总会遇到保守的团队问“是否已经有人用过了?是否是稳定的了?”但是如果没有先行者做尝试,没有友好用户做小白鼠,那么这个问题将是无解的。所以,每次出版本都需要有合适的先行推广的对象,以某种方式推进他们做***次的尝试,当然以什么方式就考验产品团队各显神通了。
- 要留一手。看似每次发布一个版本,但是实际上从版本管理的角度你需要手里有一个“回退版本”。毕竟不是每个版本都能如愿成为稳定版本的,所以为了避免无可用版本,在发布推广版本的时候需要有明确的版本回退策略。这个对于提供开发框架的产品尤为重要。如果出现兼容性的改动,很可能是无版本可用的,这个风险必须谨慎对待。
- 多个版本的维护。既然为了避免风险需要推广、试用多个版本,那么同时也会带来副作用,那就是生产上同时运行着多个版本,对于维护、支持等造成一定的压力包括时间、人力和成本等。所以在通过不同的版本的试用后,需要明确出某个可以稳定的版本,并推动升级将版本归拢到该稳定版本上来。一般这种做法叫做“版本基线归拢”。
- 对于Scrum模式下,我们更强调每个sprint都应该有个可以运行的版本。但是是否每个版本都需要去正式发布出来给大家用呢?其实不是,在操作上可以针对每个迭代发布版本,但是真正推送给大家使用可以根据各方面的情况决定。如有可能功能只是实现一小块未完整(不代表不可运行,只是实现场景未完整),则该版本只是内部版本。
- 对于版本的监控问题。特别是通用软件如基础框架软件等的使用上,一定需要有某种手段监控出来有多少个版本正在生产上运行。同时能立即找出对应的版本的使用者。这样当出现问题的时候,能***时间找到使用者做处理。同时也能很好的计划出下个版本谁是最合适的试用者。我们的做法是通过埋点的方式将信息落到文件,再汇集到APM软件上做查询和展示。
版本号的管理
似乎这个没什么需要说的,不就是定个版本号码如1.0等不就可以了么?其实这个问题,我们部门内部还是有过不少的争论的。主要问题体现在了是用3位编码格式还是4位编码格式。虽然本质上不会有大的区别,大多体现在了人的心理上的区别上。如1.0.1和1.1.0,大多数人还是觉得1.0.1变化小些使用上能更安全些。实际上,有可能反而是1.0.1变化更大些,因为定义这个版本号的人,本身就有误导他人的意味在。所以对于版本号的格式的使用上,还是有比较明确的规则信息比较好。我们目前的操作规则如下,供大家参考:
- 以3位的编码方式管理, x.y.z。
- X代表大版本变化,不同的大版本间可以是不兼容的。如1.0.0和2.0.0是不兼容的。
- Y代表是feature版本,这个版本变化说明有新的特性引入,不同的版本间相同的特性是兼容的。
- Z代表hotfix版本,解决的是bug,不会出现任何新的功能。不同的版本间是完全兼容的。
多版本造成的坑
为了避免风险,同时维护着多个版本却也同时存在这另外一个风险,那就不同版本间的兼容性风险。如一个客户端与服务端的程序,不同的客户端版本与服务端版本间的兼容性就有可能会造成问题。所以在一定时间后,版本收拢很重要。我们就曾经遇到过不同的API版本间造成了OOM的问题。对于多个版本的维护,测试同学在设计测试点的时候也是需要作为一个重要方面考虑。当然如果DevOps做的比较***的,可能终是维护一个版本在线上。但是当公司的业务部门多,同时业务开发节奏完全不一致的时候,想维护一个统一的版本是极其困难的,没有一个强有力的推动力是不可能做到,或许需要CTO这个层次的管理者来推动。
升级路径
在同时维护着多个版本的时候,需要明确升级路径策略,让使用者有个清晰的认识版本变更应该往哪里走,也让维护者同时思考什么样的版本维护是***的。如我们一个产品的升级路径如下:
1.0.10 ->1.1.1
1.0.10 ->1.1.2
1.0.10 ->1.1.3
1.1.1 ->1.1.2
1.1.1 ->1.1.3
有了明确的升级路径策略后,测试的同学也是要跟进设计不同的路径的测试点,从而避免因为多版本带来的各种坑。
【本文是51CTO专栏作者“VIPDOCKER-了哥 ”的原创文章,如需转载请通过51CTO与作者联系】