猪齿鱼实践之持续交付中的分支管理与版本控制
现在越来越多的项目使用Git作为版本控制的工具,通过Git进行分支和Tag管理,大多数情况这个过程都由手工完成,缺乏相应的规范,对于分支和版本号的控制也很随意,出现这样的情况往往是大家对软件交付过程中的软件版本控制不够重视,“只要确保软件是最新的版本即可”,甚至是项目管理的漏洞或者缺陷。其实软件的版本控制以及分支管理贯穿于整个软件产品的生命周期,日常的项目管理对于开发团队能否有节奏且顺利的交付软件也很重要。
的确!频繁的冲突搞的开发人员头晕脑胀,例如,一次项目在代码合并时出现了冲突,导致整个项目组挨个排查,花费了大半天的时间,影响开发效率还浪费资源;开发人员随意创建分支,各种不规范的合并使得Git Graph线条杂乱无章,完全看不出来主干发展的脉络;提交信息混乱,不知道这次提交是因为什么,实现了什么功能 ,解决了什么问题。
本文并不是一篇技术文章,其中也没有让别人耳目一新的观点或者论述。本文是为我们这些希望进行简单、有效地协作的人准备的。任何参与到软件开发的人,无论承担何种角色,都可能对其感兴趣——毕竟每个人都会用到分支和合并。本文将结合Choerodon猪齿鱼为大家阐述如何进行方便有效的分支管理和版本控制,以及如何选择适合自身的版本控制模型。
如何来解决这些问题呢?
有经验的老司机可能会说,“建立规范”。
是的,只有建立规范,才能抑制不好的事情继续在项目组蔓延。至于建立什么样的规范?我们不妨先制定一个目标。
目标
- 简单——所有的团队成员每天都会使用这些模式,所以相关规则和程序必须要简单明了。
- 灵活——可选择不同的分支管理模型,例如GitFlow、GitLabFlow或者GitHubFlow,甚至自定义。
- 可视化——界面化比命令行更安全可控,将分支管理模型的规则和约定固化到系统中。
- 需求与代码关连——分支需要和具体的任务需求关连。
作为一个有经验项目管理者,或者产品负责人,你一定会思考一个问题:我们项目组在开发过程中应如何管理分支?不错,分支管理将和项目组开发人员日夜伴随,如果采用了一个不合适的分支管理模型,那么可以想象兄弟们得多么的痛苦。
Okay,那么就从分支管理模型开始……
分支管理规范
GitFlow、GitHubFlow等都是已经被证明很有效的分支管理模型,但是这些更多的是书面的规则、约定,基本上是靠着程序员的自觉性和Git命令一起维持着这个约定,其实无数的经验告诉我们“这很脆弱”。所以,如何使用系统界面化操作将这些规则和约定表示出来,就变得很有意思。
分支管理模型
不要着急,先来看看 Choerodon 猪齿鱼提供的分支模型,Choerodon使用 GitLab 进行分支管理,默认分支为 master。目前支持七种常见的分支类型:
- master:主分支,用于版本持续发布;
- develop:开发分支,即日常迭代使用的开发分支,用于日常开发持续集成;
- feature:特性分支,用于日常开发时切出分支进行单功能开发;
- bugfix:故障修补分支,通常用于修复故障;
- release:发布分支,适用于产品发布、产品迭代;
- hotfix:热修分支,用于产品发布后修复缺陷;
- custom:自定义分支,用户可以自定义需要的分支类型。
注:
- develop是GitFlow分支模型的重要组成部分。
- bugfix旨在与敏捷的问题类型(故障)呼应,用于标识此分支的任务是修复某个故障。
这7个分支就是我们手中的7个魔方,通过这7个魔方的组合可以变化出无尽的分支管理模型,比如GitHubFlow。
GitHubFlow分支模型只存在一个master主分支,日常开发都合并至master,永远保持其为最新的代码。
- 在领到日常开发任务时,基于master创建feature特性开发分支,提交代码后,合并至master并删除feature。
- 在领到修复故障的任务时,基于master创建bugfix故障修补分支,提交代码后,合并至master并删除bugfix。
- 需要发布时,同样需要基于master创建release,生成的应用版本部署在UAT测试环境进行测试,若需要修改则提交至release。
- 产品上线后发现故障需要紧急进行热修复时,则基于tag创建hotfix,将修复的代码提交至hotfix;部署该分支上的版本通过验收后,基于hotfix打出热修版本的tag,如0.8.1。
- 由于新版本的迭代也同时进行,所以需要在hotfix上rebase master,变基至master分支最新的提交,再合并至master并删除hotfix,就可以将本次修改的提交应用至master上。
这个分支模型的优势在于简洁易理解,将master作为核心的分支,代码更新持续集成至master上。根据目前收集到的反应来看,得到了更多的好评,认为GitHubFlow分支模型更加轻便快捷。
如果GitHubFlow不合适,可以使用GitLabFlow或者GitFlow,也可以自行定义规则。这里没有“银弹”,只是相对比较灵活的配置。
分支命名规约
有了分支管理模型,还需要命名规约,不同类型的分支命名方式应该不同,值得庆幸的是,猪齿鱼已经帮你完成了这个步骤。feature、bugfix分支的分支名使用的是关联问题的issue号(在猪齿鱼中打通了需求和代码分支的关连关系),对于release及hotfix,分支名可命名为需要发布的版本号,如0.8.0、0.8.1等。在这里使用到了类似0.8.0这样的版本编号规则,如果你对此不了解,没有关系,在下面将详细的介绍。
提交命名规约
除了分支的名称需要规范,提交的命名也同样如此。不幸,猪齿鱼并没有把这个规则固化到系统中,需要团队共同遵守。
格式为:[操作类型]操作对象名称,如[ADD]readme,代表增加了readme描述文件。
常见的操作类型有:
- [IMP] 提升改善正在开发或者已经实现的功能
- [FIX] 修正BUG
- [REF] 重构一个功能,对功能重写
- [ADD] 添加实现新功能
- [REM] 删除不需要的文件
合并请求
合并请求是开发过程中必不可少的一个环节,其中有如下一些重要的事情要做:
- 代码Review
- 启动CI
- 单元测试
- 代码质量检查
版本号规则
在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的套件越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。
—— Tom Preston-Werner 的《语义化版本2.0.0》
在这里我们不去解读到底什么是“依赖地狱”,大家可以到语义化版本2.0.0中了解。那么,我们的重点是什么呢?在这之前,先了解一下“语义化的版本控制”
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:
1.主版本号:当你做了不兼容的 API 修改,
2.次版本号:当你做了向下兼容的功能性新增,
3.修订号:当你做了向下兼容的问题修正。
先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。
这就是“语义化的版本控制”最核心的规则,当然这不是全部,Tom Preston-Werner还详细的阐述了主版本号、次版本号和修订号的变化递增规则,不过这些规则很长,很复杂。
没有关系,猪齿鱼帮我们做了这些复杂的事情,将“语义化的版本控制”固化到了系统中,简而言之,
- 当进行代码打包时,而非发布新版本
将版本号规则定为年.月.日-时分秒-分支名
。如:2018.7.20-152837-hotfix-0.8.1
,这个时间是当前提交时间。当代码提交到各个分支上时会自动触发CI,生成版本号规则如上所示。
- 当需要发布新版本时,例如如
0.8.0
、0.8.1
- 主版本号:当做了不兼容的 API 修改或功能强大的升级,可以将主版本号的数值增加1。
- 次版本号:当做了向下兼容的功能性新增或是功能上的小迭代,可以将次版本号的数值增加1。
- 修订号:当做了向下兼容的问题修正,但功能上没有很大的变化,可以将修订号的数值增加1。
需求与代码关连
一直以来,需求一般和系统的功能联系在一起,但是与代码关连却不常见,如果能将需求和代码联系在一起,奇妙的化学反应就发生了。
“我们可以追溯到一个用户故事对应了哪些分支,哪几个提交”, “甚至出现了一些BUG,可以找到是哪个分支提交的,当初为了发布XXX新的需求”, “不仅如此,我们通过需求与代码分支关连,能够查看到哪些需求已经部署到了测试环境,那些需求已经部署到了正式环境”, “可以做从业务到代码的整个链条的统计分析…”
…
这一切,猪齿鱼已经帮助项目管理者和程序员实现了。在猪齿鱼的敏捷管理服务中,可以通过用户故事、任务、缺陷等直接一键创建分支,然后,你可以从git checkout -b 开始愉快而又有挑战的一天。不仅如此,也可以在分支管理中,将现有的分支关连到用户故事、任务或者缺陷。
总结
回顾一下我们的目标,简单、灵活、可视化,以及需求与代码关连。版本控制一直都是一件说起来容易,做起来难的事情,但是我们做到了,重要的是猪齿鱼将这些特点和规则固化到了DevOps流程中,让我们忘记复杂易错的操作,把精力放到业务开发上。希望我们的分享能够给大家带来帮助。
本文由猪齿鱼技术团队原创,转载请注明出处