我们在日常开发工作中提到的 Workflow 通常是指通过 Git(版本控制工具)实现的分布式版本控制(distributed revision control),它允许多名软件开发者,在不同的网络环境下,参与同一个软件开发项目。
这种工作模式,比集中式版本控制具有分布式的特性与增量版本的明显优势,已经成为行业内主流版本管理方法。
Git 除了最基本的推拉代码,还包括分支、tag、commit,其背后有很多最佳实践,例如:
这些最佳实践的集合被称为工作流(Workflow)。
Git 在 2005 年诞生,最初目的是为了更好地管理 Linux 内核开发而设计。Git 最初只是作为一个可以被其他前端包装的后端应用而开发的,但后来 Git 内核已经成熟到可以独立地进行版本控制。
仅有版本控制功能还不足以胜任代码托管工作,随后一款基于 Git 的在线源代码托管服务平台 GitHub 于 2008 年 2 月上线。
随着 2007 年持续集成(Continuous Integration)和 2009 年 DevOps 概念的流行,一站式 DevOps 研发平台 GitLab 于 2011 年诞生。
近年来,Workflow 基于各类平台快速发展。
用于 Linux 的内核版本管理工具 Git 推荐的工作流是 Git flow,源代码托管平台 GitHub 推荐的是 GitHub flow,而 DevOps 研发平台 GitLab 的,则是 GitLab flow。
以上 3 个工作流并不存在好坏之分,只要可以帮助有效管理并行开发的软件版本、实现团队高效协同的,就是好的 Workflow。每个团队都应该基于不同类型的应用开发场景,选择最适合自己的。
点击👉获取一对一咨询服务,选择合适的workflow,让研发工作事半功倍~
Git flow 面向多版本长期维护和多版本同时发的开发模式,比如框架(Spring 2 和 3 共存)、编程语言(Node.js 18 LTS 和 19 共存)、开放 API(v1 和 v2 共存)、多客户定制版。
Git flow 并行开发模式非常复杂,作者本人也在 2020 年宣布其「不适合持续交付」。
并行开发模式如下图:
图 1:Git flow 并行开发分支模型
图中每个分支都有不同的使用场景和用途:
功能分支(Feature):开发人员以功能名称命名一个分支,独立于其他分支进行开发工作,完成开发后合并入共享开发分支。
共享开发分支(Develop):用于集成多个功能分支,一个版本全部功能开发完成后,可以拉出发布分支进行发布,而共享开发分支可以继续进行下一个版本的开发工作。
发布分支(Release):用于保存发布过程中产生的代码修改,发布后会将代码合并到共享开发分支和主分支。
热修复分支(Hotfix):当某个正式版本出现紧急 bug 需要修复时,从主分支的对应版本拉出 Hotfix 分支,进行紧急修复,发布后,合并回主分支。
主分支(Master):用于保存所有发布的版本。
做为一个代码托管平台的分布式版本管理模型,GitHub flow 相对简单很多。
其经历过多个版本更迭,V1.0:主干开发、主干发布,V2.0:分支开发、主干发布。作为托管平台,GitHub Flow 对团队约束性较低,难以在团队内形成规范,适合人数较少的开源项目
图 2:GitHub flow 分支模型(上图为 V1.0,下图为 V2.0)
作为一站式 DevOps 平台,GitLab 在分布式版本管理的能力与 CI/CD 能力,已有较多完善功能,且在并行开发模型和研发治理方面的能力都相对比较成熟。
图 3:GitLab 与 GitHub 功能成熟度比较
在持续集成方面,GitLab 推出了一系列功能保障主干分支的代码质量:
图 4:GitLab CI/CD 模式
GitLab flow 有三种推荐的 flow 模式:
以环境分支为例:
图 5:环境分支模型
每个分支使用场景如下:
对应以上三种主流 flow,基本可以覆盖各类不同复杂度的项目。
图 6:主流工作流复杂度对比
但,这全面了吗?
如果我的企业,既需要敏捷快速迭代(如 GitHub Flow),也需要一定的研发规范、确保安全可控(如 GitLab Flow)呢?
极狐 GitLab 研发团队根据多年实践经验,推出了「极狐 flow」(JiHu flow),既简单易上手(对应上图,复杂度为 2),又兼具团队研发规范性,非常适合在规范保障基础上、强调敏捷创新、快速迭代的项目。
分支模型如下图:
图 7:极狐 flow 分支模型
图 8:JiHu flow 全景图
正则表达式(如果是小型项目,可省略 develop 分支):
main|develop|(\d+\-(feature|bugfix|hotfix)\-[A-Za-z0-9]+)
分支示例:
master:主分支
develop:共享开发分支
1-feature-sms-deng-lu:需求分支
2-bugfix-sms-repeat:缺陷分支
3-hotfix-register-failed:热修分支
其中数字为需求/缺陷的 ID,所以应当先创建需求/缺陷,再写代码,杜绝「口头加需求」、「口头报 bug」的情况。通过需求分支和合并请求草稿功能,可以方便地为需求人员创建需求分支,暂存代码修改。
使用极狐 GitLab 创建需求/缺陷应使用「feature|bugfix|hotfix」开头,可以一键创建符合规范的分支,开发人员再也不用为分支命名发愁。另外中文需求(issue)可自动转化为拼音分支名,例如:Feature:SMS 登录变为 1-feature-sms-deng-lu。
feature 和 bugfix 分支来自 develop,完成开发后应合并到 develop,且在合入后自动删除 feature 和 bugfix 分支,减少过多的分支数量。
hotfix 分支来自 main,完成开发后应合并到 main,且在合入后自动删除 hotfix 分支。
发布时,将功能代码从 develop 合并到 main,合并后不会删除分支。
如果是小型项目,无 develop 分支,则 feature、bugfix 和 hotfix 分支都来自 main,也会合入到 main,合并后自动删除多余分支。
推荐使用快进式(Fast-forward)合并,而不推荐使用常规合并(产生一条冗余 commit)。
如果 commit 有多条调试记录,则应压缩为一条,不得强制使用压缩。
可通过极狐 GitLab「设置 → 合并请求」进行设置:
所有的公共分支都必须被保护,包括公共开发分支 develop。
常见错误:保护了 master,而未保护 develop,大家随意提交 develop,最后 develop 合并到 master,导致未经审核的代码进入生产环境。
可通过极狐 GitLab「设置 → 仓库 → 受保护分支」进行限制:
禁止将修改代码直接合入分支,必须通过合并请求,由至少另一位开发者进行代码评审,同意后才可合并。
评审必须在合并之前,合并后、上线后的评审只能称为「技术分享」,而非「代码评审」。
只在临时分支(feature、bugfix、hotfix)合并到公共分支时进行评审,而不评审公共分支的互相合并(比如 develop 合并到 main,单向合并减少评审工作量)。
可通过极狐 GitLab「设置 → 合并请求 → 合并请求批准」实现代码管控:
业务代码中应使用规范扫描工具和配置文件,必须配置本地钩子 .Git/hooks/pre-commit 执行扫描,进行强制检查代码规范。
如果项目配置了持续集成流水线,则应该用和本地一致的代码规范进行检查,持续集成流水线必须成功,才可以合并,这也是安灯实践的要求。
代码评审提出的评审建议,需要全部解决,才可以合并。
Git commit 采用 Angular 规范,正则表达式:
(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert): #\d+ .+
正确示例:
feat: #1 sms 登录
fix: #2 sms repeat
fix: #3 register failed
英文前缀固定,后半部分可以写汉字等多种语言的文字。
其中数字为需求/缺陷的 ID,所以必须先创建需求/缺陷,再写代码,杜绝「口头加需求」、「口头报 bug」的情况。
可通过极狐 GitLab「设置 → 仓库 → 推送规则」中,设置正则表达式进行限制:
Git commit 时读取了 Git config user.name 与 user.email,推送到服务器时必须至少校验 email,杜绝「个人邮箱推送到公司项目」的情况。
可通过极狐 GitLab「设置 → 仓库 → 推送规则」进行验证:
禁止提交第三方包(比如 jar、node_modules、vendor)、编译打包结果(比如 apk、exe、zip),以及任何大于 4MB 的文件。
建议使用 .Gitignore 进行配置,或者可通过极狐 GitLab「设置 → 仓库 → 推送规则」进行限制:
采用 npm 和语义化规范,版本号不使用 v 前缀,而 Git tag 使用 v 前缀,避免纯数字导致的问题,正则表达式:
v(\d+\.){1,2}\d+
示例:
v0.1
v1.2.0
v2.0.0
当提取 Git tag 用作 Docker、maven、npm 等版本号时,应在使用时去除 v 前缀,比如:
https://Github.com/nodejs/node/releases/tag/v19.1.0
docker pull node:19.1.0
maven se.bjurr.violations:violations-maven-plugin:1.50.4
推荐使用 GitOps 进行部署,即:
多个需求的代码合并之后,在上线之前可能会遇到一个需求代码有严重问题,来不及修复的情况,或者尚未到达业务部门的发布时间(发布会、节日促销等)。此问题不应该从 git 角度解决,因为无论是剔除代码,还是需求分支迟迟不合并,两者的成本都比较高。此时推荐使用功能开关(Feature Flags)。
功能开关可以实现「AB 测试」和「先部署,后发布」。研发人员提前部署,将产品功能发布的权力,交给业务部门,提高了协作效率。
通过以上 10 个实践,希望帮助所有创新类型的产品进行快速迭代,而又不必牺牲规范性与质量。如果是内部使用产品也可以进一步简化分支模型,只使用 master 分支进行功能开发和版本发布即可。