作为一名老菜鸟,没想到初入新团队第一次提交代码就翻了车:版本分支作为集成分支,可咱们目前针对集成分支没有配置编译检查,推送代码后部署失败,定位后发现是编译失败导致的,笔者内心慌的一匹,为了避免研发经理投来鄙视的眼神,需要第一时间解决问题并通过 cherry pick 将其同步到 develop 分支,从那时起这种开发模式就对咱造成了不可磨灭的创伤。
这究竟是一种什么样的开发模式 (分支模型) 呢?
- 首先,当 v4.2.1 版本启动研发,版本负责人会在 Gerrit 上从 develop 分支拉一个远程分支 v4.2.1;
- 然后,相关研发人员基于远程分支 origin/v4.2.1 创建一个本地分支 v4.2.1;
- 接下来,将代码推送到远程仓库中的 v4.2.1 分支,同时在 Gerrit 中将相关提交 cherry pick 到 develop 分支;
- 最后,当 v4.2.1 版本冒烟通过后,向测试部发起提测,BUG 修复完成后推送到远程仓库中的 v4.2.1 分支同时在 Gerrit 中再次将对应提交 cherry pick 到 develop 分支。
分支的主要目的就是隔离,为什么在研发过程中要将版本分支中的每一个提交通过 cherry pick 同步到 develop 分支呢?笔者以为这种开发模式主要有四个弊端。
- 在版本研发过程中,有些研发人员是没有相应版本的研发任务的,那么他们的代码只需要与 develop 分支打交道即可,也就是说此时 develop 分支是一直向前演进的,分支基线不一样了,发生冲突的可能性也就大了,冲突多了,等待也就多了,研发效率也就下去了;
- 有时研发人员忘记将代码同步到 develop 分支,当从 develop 分支拉取下一版本分支时,上一版本中该研发人员所提的代码就缺失了;
- 下一版本分支究竟应该从上一版本分支拉取,还是从 develop 分支拉取呢?目前两种情况都有,没有一个明确的约束规则,头疼;
- 这些版本分支的生命周期过长,以至于现在远程仓库中已经有了 50+ 分支了,难看。
如何破局呢?咱们可以基于 TBD (Trunk Based Development) 和 git-flow 分支模型来搞,这两种方案相较于原生版本都有一些改动。
方案一
不要版本分支,就直接把 develop 分支作为主干分支,测试完成就打一个版本 tag。同时要定义一个约束规则:如果当前版本 tag 还未打,那么与版本无关的代码尽量先本地暂存一下,不允许直接提交与合并;此外,由于咱们流水线打包部署需要持续 15 分钟左右,因此尽量将本地提交 squash 为一个提交,这与 TBD 所提倡的小步快跑原则是不相符的,但也没办法,基础配套跟不上。
方案二
引入 master、develop、feature 和 hotfix 这四个分支,分支间代码的同步要严格遵从逐级合并原则,它们的职责如下所示。
- master 即发布分支,是一种长期存在的分支,版本 tag 就是在这里打的;此外,不允许直接提交代码到该分支,该分支只有 develop 分支和 bugfix 分支可以合并进来;
- develop 即集成分支,是一种长期存在的分支;develop 分支从 master 分支切出。
- feature 即特性分支 (本地分支),一旦 feature 分支合并到 develop 分支后,可以将其删除;
- hotfix 即热修复分支 (本地分支),hotfix 从 master 分支拉出,一旦 hotfix 分支合并到 master 分支后,也可以将其删除了;hotfix 分支中的内容必须同步到 develop 分支,以确保修复的 BUG 集成到下一个版本的开发中。
下面咱来缕一缕具体的流程。
- 当 v4.2.1 版本启动研发,相关研发基于 develop 分支创建本地特性分支 (如 feature_vpc_crud),任务完成后,将本地 feature_vpc_crud 分支中的提交 squash 为一个提交;
- 切换到 develop 分支,将 feature 分支内容合并到当前 develop,然后推送到远程仓库中的 develop 分支,发起评审、合入和部署;
- v4.2.1 版本中的所有特性均推送到 develop 之后,发起提测;提测过程中涉及的 BUG,只需要与 develop 分支交互即可;
- v4.2.1 版本测试通过,需要将 develop 分支合并到 master 分支,同时在 master 分支打 v4.2.1 tag;
- 如果 v4.2.1 在线上出现 BUG,相关 BUG 责任人基于 master 分支 v4.2.1 tag 创建本地 hotfix 分支;然后将 hotfix 合并到 master 分支,同时需要将 hotfix 同步到 develop 分支。
写这篇文章的动机其实是昨晚的一次研发管理宣贯,提到了不允许向 release 分支直接提交代码啥的。说的没问题,可笔者单纯好奇是否具备引入 release 分支的条件?如果引入了 release 分支,那就必须为 release 分支搞条流水线;相较于 develop 流水线中的单元测试、代码扫描和构建镜像等功能点外,release 流水线还要有一个推送镜像的能力,我不确定咱们能否做到。
欢迎大家批评指正!