参考内容:

Git工作流实践

Git 工作流程

Git三大特色之WorkFlow(工作流)

Git分支管理策略

使用 Issue 管理软件项目详解

GitLab Issue 创建及使用说明

Git 提交规范

Git 是软件开发活动中非常流行的版本控制器类工具。随着项目时间的拉长、项目参与人员的更替、软件不同特性功能的发布,从开发人员角度看会发现工程的提交历史、分支管理等非常混乱,项目管理者会因为需求迭代、bug 修复、版本发布等活动无法与代码提交历史一一对应而头疼,混乱的管理常常导致故障泄漏给客户,所以一套规范的规范的 git 工作流程是非常有必要的。

Git WorkFlow

WorkFlow 的字面意思即工作流,比喻像水流那样顺畅、自然的向前流动,不会发生冲击、对撞、甚至漩涡。工作流不涉及任何命令,它就是团体成员需要自遵守的一套规则,完全由开发者自己定义。

当下比较流行的三种工作流程分别为:Git FlowGitHub FlowGitLab Flow。它们有一个共同点:都采用功能驱动开发。其中 Git Flow 出现的最早,GitHub Flow 对其做了一些优化,比较适用于持续的版版发布。GitLab Flow 出现的时间比较晚,所以是综合了前面两个工作流的优点制定的。

Git Flow

git-flow 的思路非常简洁,通过 5 种分支来管理整个工程。

分支 周期 说明
master 长期 主分支,用于存放对外发布的版本,任何时候在这个分支拿到的,都是稳定的分布版
develop 长期 开发分支,用于日常开发,存放最新的开发版
feature 短期 功能分支,它是为了开发某种特定功能,从 develop 分支上面分出来的。开发完成后,要再并入 develop
release 短期 预发分支,它是指发布正式版本之前(即合并到 master 分支之前),我们可能需要有一个预发布的版本进行测试。预发布分支是从 develop 分支上面分出来的,预发布结束以后,必须合并进 develop 和 master 分支
hotfix 短期 bug 修补分支,从 master 分支上面分出来的。修补结束以后,再合并进 master 和 develop 分支
git-flow

Github Flow

github-flow 可以认为是 git-flow 的一个简化版,它适用于持续部署的工程,直接将最新的功能部署到 master 分支上,不再操作 develop 分支。同时通过 CI&CD 的使用,不再需要额外的 release 和 hotfix 分支。github 还结合了推送请求(pull request)功能,在合并 feature 分支之前通过PR请求其他成员对代码进行检查。

  1. master分支中的任何东西都是可部署的
  2. 要开发新的功能特性,从 master 分支中创建一个描述性命名的分支(比如:new-oauth2-scopes)
  3. 在本地提交到该分支,并定期将您的工作推送到服务器上的同一个命名分支
  4. 当您需要反馈或帮助,或者您认为分支已经准备好合并时,可以提交一个推送请求(PR)
  5. 在其他人审阅并签署了该功能后,可以将其合并到 master 中,合并后原来拉出来的分支会被删除
  6. 一旦它被合并到 master 分支中,就可以并且应该立即部署
github-flow

github-flow 最大的优点就是简单,非常适合需要持续发布的产品。但是它的问题也很明显,因为它假设 master 分支的更新与产品的发布是一致的,即 master 分支的最新代码,默认就是当前的线上代码。

但实际可能并非如此,代码合入 master 分支并不代表着它立刻就能发布。比如小程序提交审核以后需要等待一段时间才能发布,如果在这期间还有新的代码提交,那么 master 分支就会与刚刚发布的版本不一致。另外还有一种情况就是,有的公司只有指定时间才会发布产品,这会导致线上版本严重落后于 master 分支。

可以发现针对上述情况,一个 master 分支就不够用了,你可能需要在 master 分支之外新建一个 prodution 分支才能解决问题。

Gitlab Flow

因为 gitlab-flow 出现的比较晚,所以它同时具备前面两种工作流的优点,并且又摒弃了它们存在的一些缺点。它的最大原则叫做上游优先(upsteam first),即只存在一个主分支 master,它是所有其他分支的上游。只有上游分支采纳的代码变化,才能应用到其他分支。

gitlab-flow 分为两种情况,分别适用于持续发布和版本发布项目。对于持续发布项目,它建议在 master 分支以外,再建立不同的环境分支。比如,开发环境的分支是 master,预发环境的分支是 pre-production,生产环境的分支是 production。

开发分支是预发分支的上游,预发分支又是生产分支的上游。如果产环境出现了 bug,这时就要新建一个功能分支,先把它合并到 master,确认没有问题,再cherry-pick 到 pre-production,这一步也没有问题,才进入 production。

gitlab-flow 持续发布项目

对于版本发布的项目,建议的做法是每一个稳定版本,都要从 master 分支拉出一个分支,比如 2-3-stable、2-4-stable 等等。发现问题,就从对应版本分支创建修复分支,完成之后要先合并到 master 分支,然后才能合并到 release 分支。版本记录可以通过 master 上的 tag 来记录。

gitlab-flow 版本发布项目

Issue 使用

Git WorkFlow 主要解决了开发人员的问题,但是对项目管理者问题的解决力度不够,比如客户需求的管理、bug 的跟踪等。Github 和 Gitlab 提供的 Issue 功能可以比较好的解决项目的管理问题。

Issue 中文可以翻译为议题事务,是指一项待完成的工作,比如一个 bug、一项功能建议、文档缺失报告等。每个 Issue 应该包含该问题的所有信息和历史,使得后来的人只看这个 Issue,就能了解问题的所有方面和过程。

Issue 起源于客服部门。用户打电话反馈问题,客服就创建一个工单,后续的每一个处理步骤、每一次与用户的交流,都需要更新工单,全程记录所有信息。因此,Issue 的原始功能是问题追踪和工单管理,后来不断扩展,逐渐演变成全功能的项目管理工具,还可以用于制定和实施软件的开发计划。

下面以可以免费使用的 Github Issues 来介绍如何使用 Issue。

创建 Issue

每个 Github 仓库都有一个 Issue 面板,如下图所示是新建 Issue 的界面。左侧输入 Issue 的标题和内容,支持 markdown 语法。右侧分别对应四个配置项,将在下面一一进行介绍。

创建issue

Assignees

Assignee 选择框用于从当前仓库的所有成员之中,指派某个 Issue 的处理人员。

Assignees

Labels

可以为每个 Issue 打上标签,这样方便分类查看和管理,并且能比较好的使用看板进行查看。一般来说一个 Issue 至少应该有两种类型的 Label,即 Issue 的类型和 Issue 的状态(根据需要可打第三种用于表示优先级的 Label),其中 Issue 的状态可以用来构建敏捷看板。

labels

Milestone

Milestone 翻译过来叫里程碑,它的概念和迭代(sprint)或版本(version)差不多。Milestone 是 Issue 的容器,可以很方便的用来规划一个迭代(版本)要做的事情,也能非常方便的统计进度。

Milestone

Projects

Projects 是 Github 2020 年 6 月份提供的功能,它就是项目看板的功能,Gitlab 所提供的类似功能为 Issue boards,感兴趣读者可以自行阅读文档了解。

Projects

PR&MR

至此,可以发现我们可以使用 Issue 管理需求、bug,Milestone 又提供了迭代(版本)的计划管理,通过 Projects 可以创建敏捷看板,用于关注整体项目的进度。前文 Git WorkFlow 从开发者角度提供了项目管理的工作流程,可以思考一下还差什么问题没有解决?

最后剩下的问题是:每一个 Issue 都需要提交代码/文档进行解决,那代码/文档如何与 Issue 进行关联呢?其实无论是 GitHub 还是 GitLab,都可以很方便地在 Issue 上创建分支,在该分支上解决完 Issue 所对应的问题后,提交远程分支即可发起合并请求,在 Github 中称为 Pull request(PR),在 Gitlab 中则叫做 Merge request(MR)。

Git 提交规范

上文已经说了我们可以对每个 Issue 创建分支,既然是分支,那超过一个 commit 是再常见不过的事情了。一些开发人员所写的提交说明常常是fixbug或者是update等非常不规范的说明。

不规范的说明很难让人明白这次代码提交究竟是为了什么。在实际工作中,一份清晰简洁规范的 commit message 能够让后续的代码审查、信息查找、版本回退都更加高效可靠,因为我们还需要对提交说明制定一套规范。

那么什么样的 commit message 才算是符合规范的说明呢?不同团队可以制定不同的规范,此处推荐使用 Angular Git Commit Guide

提交格式指定为提交类型(type)、作用域(scope,可选)和主题(subject),提交类型指定为下面其中一个:

类型 说明
build 对构建系统或者外部依赖项进行了修改
ci 对 CI 配置文件或脚本进行了修改
docs 对文档进行了修改
feat 增加新的特征
fix 修复 bug
pref 提高性能的代码更改
refactor 既不是修复bug也不是添加特征的代码重构
style 不影响代码含义的修改,比如空格、格式化、缺失的分号等
test 增加确实的测试或者矫正已存在的测试

作用域即表示范围,可以是任何指定提交更改位置的内容。主题则包括了对本次修改的简洁描述,有以下三个准则:

  1. 使用命令式,现在时态:“改变”不是“已改变”也不是“改变了”
  2. 不要大写首字母
  3. 不在末尾添加句号

下图是 NocoBase 的 commit message 截图,可供参考

commit_message