Gitflow 太繁琐?为什么不自动化呢

2,321 阅读9分钟

导读

对于一个 4~5 人以上的研发团队来说,协作沟通所产生的成本一般已经开始对效率产生了影响,而且这种影响会随着人数的增加呈指数性增长。Git 协作明显就具有这种特性,所以业内也出现了各种 Git 的工作流来试图解决这个问题。比较著名的有 GitflowGitHub FlowGitLab Flow

笔者在综合调研之后,基于 Gitflow 的思想,结合 PR/MR 模式提出了一套方案,并且将每一个步骤节点都脚本化,做到了一条命令就可以完成复杂的操作。现整理成文,希望给大家做一个参考。

本文会先介绍思路,具体的脚本在后面,心急的读者也可以直接去看脚本,再回来看理论。不过要强调一下,理论是一定要看的,因为处理冲突等情况会使脚本中断,虽然已经在注释里尽量写清楚了,但是如果没有充分理解背后的思路,在处理异常状况时还是容易出错。

正文

思路

Gitflow 的主要思路就是利用分支的流转规则来让协作变的有序,减少混乱,而且已经有了配套的工具 gitflow-avh。但是它有一点不太符合现代的开发流程,就是没有 PR/MR 的概念(二者分别是 GitHub 与 GitLab 的特色),而是采用分支直接合并的形式。这对于 Code Review、权限控制、CI/CD 控制等是不利的。所以笔者这个方案的思路说白了就是 Gitflow + PR/MR 的结合,取二者的优点。

需要哪些分支

既然是用分支管理,我们就先来从本质上,也就是日常开发的场景上来分析一下我们都需要哪些分支。项目迭代通常是:开发 => 提测 => Debug => 上线,中间还有可能穿插进高优需求hotfix。由此可以得出以下结论:

  1. 需要一个(甚至多个)分支与生产环境完全对应,以随时处理 hotfix 的情况,推荐 master
  2. 需要一个分支聚合日常开发的所有内容,保持最新的代码,以方便所有协作者同步代码,推荐 develop
  3. 在 Debug 后处于上线 ready 的状态下,有时候需要等待上线窗口期,这时上线用的分支需要冻结。甚至提测的时候就有可能已经开始了下一轮开发,然后抽空 Debug。为了不阻塞下个迭代的日常开发,就不能占用 develop 分支。这时就需要一个专门上线用的分支,推荐 release。
  4. 当出现线上紧急 bug,需要马上修复并上线时,不适合直接在 master 上直接操作,所以需要一个临时分支来处理,推荐 hotfix/xxx(临时)
  5. 除了以上 4 种分支外,最关键的就是每个人的日常开发分支,这时候到底是每个人只用一个分支(以人为单位),还是每个人用多个分支(以 feature 为单位)就需要探讨了。目前业内比较通用的做法是以 feature 为单位的临时分支,用完即删,下文会有调研,推荐 feature/xxx(临时)
  6. 最后,在提测后的 Debug 阶段,建议使用 bugfix 分支来与 feature 分支进行区分,推荐 bugfix/xxx(临时)

以上的分支也是参考了 gitflow-avh 设计的,尽量保证与已有工具的契合。从需求的角度确定了我们需要哪些分支,接下来就是制定各分支之间的流转规则来保证有序了。

分支流转规则

一图胜千言,先上图。

image.png

分支名性质说明操作权限
master永久- 要保持与线上内容的强一致性,即任何变化都要触发线上部署;
- 只接受 hotfix 和 release 的 PR;
Merge:上线负责人、Supervisor
develop永久- 保存当前最新开发成果的分支;
- 只接受 feature 的 PR,只能合并到 release;
- release 和 master 有变动时要及时 rebase 同步变化;
Merge:所有研发人员,但需要 1 人以上的 CR 才能合并 Other:TL
release/xxx临时/永久- 测试验收、灰度用的分支,必须保证功能完整性与一定的稳定性;
- 只接受 develop 和 bugfix 的 PR;
- 只能从 develop 切,只能合并到 master;
- master 有变动时要及时 rebase 同步变化;
Merge:所有研发人员,但需要 1 人以上的 CR 才能合并 Other:TL
feature/xxx临时- 提测前开发功能用的分支,理论上一个功能对应一个分支;
- 只能从 develop 切,只能合并到 develop。
-
bugfix/xxx临时- 提测后修复 bug 的分支;
- 只能从 release 切,只能合并到 release;
-
hotfix/xxx临时- 紧急修复线上 bug 的分支;
- 只能从 master 切,只能合并到 master;
- 该分支可以手动部署到任意环境进行验证,部署前记得进行周知,防止部署冲突。
-

另外,还需要遵守以下规则:

  1. 所有分支合并操作均使用 PR 的形式,并需要 Code Review 后才能合并(通过 github 设置实现)。
  2. 所有合并建议采用 rebase 方式,保证所有分支的流程逻辑线性。
  3. 只要 release 分支有变动,develop 就要同步 rebase release;
  4. 只要 master 有变动,develop、release 就要同步 rebase master; 注: 如果用 merge 方式,git log 会保证时间逻辑线性。举个例子,在修复完 hotfix 然后同步回 develop 时,如果是 merge,hotfix 的提交会在 git log 的最顶端,即在所有新 feature 提交的上面。如果是 rebase,hotfix 的提交会在所有新 feature 的下面。理论上后者更符合流程逻辑。

这么多规则,看着就晕,作为程序员,“”是必须的品质,所以接下来,我们就把它半自动化。

半自动脚本

既然要用脚本实现,有一个问题是必须要解决的,那就是关于 PR/MR 的操作如何用命令行完成。GitHub 提供了命令行工具 gh,安装后可以解决这个问题。GitLab 暂时还没有解决方案,不过应该通过 url 或者其他方式也应该可以实现,有时间的话再研究下。所以以下的脚本的执行前提是使用 GitHub 管理代码并安装了 gh

(2022.02.17 按,Gitlab 版已完成,详见 Gitflow 太繁琐?为什么不自动化呢——Gitlab 版

Feature Start

  • 开始开发一个 feature 的适合运行下列命令。功能其实很简单,就是新切一个分支。
git checkout develop && git pull -r && git checkout -b feature/xxx

Feature Submit

  • 该命令只需要在完成 feature 开发后执行一次即可;
  • 后续的修改,只需要把 feature 分支 push 到远程即可,不需要再执行此命令;
  • 执行过程中若出现冲突,重新执行全部命令。
git checkout develop && git pull -r && \
git checkout feature/xxx && git pull -r && git rebase develop && \
git push --set-upstream origin feature/xxx --force-with-lease && \
gh pr create --fill --base develop

Feature Finish

  • Code Review 完成,PR 处于可合并状态时,可执行下列命令;
  • 该命令只能有 develop 合并权限的人来执行,不过通常 develop 的合并权限都会开放给所有人。
gh pr merge feature/xxx -rd

Bugfix Start/Submit

命令同 Feature,做如下改变:

  • feature/xxx 替换为 bugfix/xxx
  • develop 替换为 release

Bugfix Finish

  • 合并之后记得同步 develop。注意,执行同步命令的同学需要有 develop 的 push 权限;
  • 若出现冲突,是执行 develop rebase release 时产生的,处理完冲突后 push develop 即可;
  • 可触发自动部署测试环境的 CI/CD
gh pr merge feature/xxx -rd && \
# 同步,以下命令需要有 develop 的 push 权限
git checkout release && git pull -r && \
git checkout develop && git pull -r && \
git rebase release && git push --force-with-lease

Hotfix Start/Submit

命令同 Feature,做如下改变:

  • feature/xxx 替换为 hotfix/xxx
  • develop 替换为 master

Hotfix Finish

  • 合并之后记得同步 release、develop。注意,执行同步命令的同学需要有两个分支的 push 权限;
  • 若出现冲突,需要仔细查看信息,确定到底是在 release 还是 develop 合并时出现的,处理完冲突后 push 相应分支,然后执行未执行的命令即可,通常最多只需处理一次冲突。
  • 可触发自动部署线上环境的 CI/CD
gh pr merge hotfix/xxx -rd && \
# 同步,以下命令需要有 release、develop 的 push 权限
git checkout master && git pull -r && \
git checkout release && git pull -r && git rebase master && git push --force-with-lease && \
git checkout develop && git pull -r && git rebase release && git push --force-with-lease

UAT Submit

git checkout develop && git pull -r && gh pr create --fill --base release

UAT Finish

  • 命令同 Bugfix Finish,只需要把第一个命令改一下。 注意:参数不是 -rd,不要错把 develop 分支给删了,建议设置分支保护。
gh pr merge develop -r && \
# 其他命令、权限同 Bugfix Finish

Deploy Submit

  • 理论上上线一定要产品、测试、技术负责人确认才可以
git checkout release && git pull -r && gh pr create --fill --base master

Deploy Finish

  • 命令同 Hotfix Finish,只需要把第一个命令改一下。 注意:参数不是 -rd,不要错把 release 分支给删了,建议设置分支保护。
gh pr merge release -r && \
# 其他命令、权限同 Hotfix Finish

结语

有了以上脚本,每次到了需要 Git 协作的节点找到相应的命令修改下分知名,在命令行里执行一下就行了。不用再怕切分支或提交 PR 前忘了同步,造成冲突的情况了。

实际上,本文的脚本是经过简化后的版本,没放上来主要是不想增加这边文档的复杂度,让大家能聚焦在理解思想上。完整版已经放到了 github - git-workflow 上,具有更多更强大的能力,比如:

  • 自动创建符合规范的分支;
  • 自动创建 PR,并提取 commit list 作为 body 内容,让每个 PR 都具有的优雅的可读性;
  • PR 合并之后,自动删除本地和远程的分支,并自动做功能分支的同步;
  • Hotfix、Deploy 合并后,会自动触发:version 的更新、打相应版本的 tag、生成 CHANGELOG、发布一个 RELEASE、同步功能分支代码

更进一步,已经将这些命令封装成了一个脚本文件,模仿并优化了 gitflow-avh 的交互方式,大大简化了操作。有兴趣的同学可以查看一下项目的 README,有比较详细的用法说明,顺便点个 star 就更好了。

另外,在写脚本的过程中,积累了一些比较实用的 shell 命令,放到了 Shell 难学?那是因为你没找到场景 一文中,欢迎品鉴。

“谨记,你是在寻找最好的答案,而不是你自己能得出的最好答案。”——Ray Dalio