2.1.5. Commit 规范¶
一个好的 Commit Message 至关重要:
1. 可以使自己或者其他开发人员能够清晰地知道每个 commit 的变更内容,方便快速浏览变更历史
比如可以直接略过文档类型或者格式化类型的代码变更
2. 可以基于这些 Commit Message 进行过滤查找
比如只查找某个版本新增的功能:
git log --oneline --grep "^feat|^fix|^perf"
3. 可以基于规范化的 Commit Message 生成 Change Log
4. 可以依据某些类型的 Commit Message 触发构建或者发布流程
比如当 type 类型为 feat、fix 时我们才触发 CI 流程
5. 确定语义化版本的版本号
比如:
fix 类型可以映射为 PATCH 版本
feat 类型可以映射为 MINOR 版本
带有 BREAKING CHANGE 的 commit,可以映射为 MAJOR 版本
备注
总结来说,一个好的 Commit Message 规范可以使 Commit Message 的可读性更好,并且可以实现自动化。
Commit Message 的规范:
建议你采用开源社区中比较成熟的规范
例如 jQuery、Angular 等
Angular 规范是一种语义化的提交规范(Semantic Commit Messages),所谓语义化的提交规范包含以下内容:
1. Commit Message 是语义化的
Commit Message 都会被归为一个有意义的类型,用来说明本次 commit 的类型
2. Commit Message 是规范化的
Commit Message 遵循预先定义好的规范,比如 Commit Message
格式固定、都属于某个类型,这些规范不仅可被开发者识别也可以被工具识别
在 Angular 规范中,Commit Message 包含三个部分,分别是 Header、Body 和 Footer,格式如下:
<type>[optional scope]: <description>
// 空行
[optional body]
// 空行
[optional footer(s)]
示例:
fix($compile): couple of unit tests for IE9
# Please enter the Commit Message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# ...
Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.
Closes #392
Breaks foo.bar api, foo.baz should be used instead
Header¶
Header 部分只有一行,包括三个字段:
type(必选)、scope(可选)和 subject(必选)
type(必选):
用来说明 commit 的类型。
主要可以归为 Development 和 Production 共两类
1. Development
这类修改一般是项目管理类的变更,不会影响最终用户和生产环境的代码,比如 CI 流程、构建方式等的修改。
遇到这类修改,通常也意味着可以免测发布。
2. Production
这类修改会影响最终的用户和生产环境的代码。
所以对于这种改动,我们一定要慎重,并在提交前做好充分的测试。
备注
如果我们变更了应用代码,比如某个 Go 函数代码,那这次修改属于代码类。在代码类中,有 4 种具有明确变更意图的类型:feat、fix、perf 和 style;如果我们的代码变更不属于这 4 类,那就全都归为 refactor 类,也就是优化代码。
备注
如果我们变更了非应用代码,例如更改了文档,那它属于非代码类。在非代码类中,有 3 种具有明确变更意图的类型:test、ci、docs;如果我们的非代码变更不属于这 3 类,那就全部归入到 chore 类。
scope:
不同项目会有不同的 scope:
1. 项目初期: 我们可以设置一些粒度比较大的 scope,比如可以按组件名或者功能来设置 scope
2. 项目中期: 如果项目有变动或者有新功能,我们可以再用追加的方式添加新的 scope
备注
要强调的是,scope 不适合设置太具体的值。太具体的话,一方面会导致项目有太多的 scope,难以维护。另一方面,开发者也难以确定 commit 属于哪个具体的 scope,导致错放 scope,反而会使 scope 失去了分类的意义。
备注
需要遵循我们预先规划的 scope,所以我们要将 scope 文档化,放在类似 devel 这类文档中。
subject:
commit 的简短描述,必须以动词开头、使用现在时。
比如,我们可以用 change,却不能用 changed 或 changes,而且这个动词的第一个字母必须是小写。
通过这个动词,我们可以明确地知道 commit 所执行的操作。
此外我们还要注意,subject 的结尾不能加英文句号。
Body¶
备注
Header 对 commit 做了高度概括,可以方便我们查看 Commit Message,Body 中说明了具体做了哪些变更。Body 部分可以分成多行,而且格式也比较自由。此外,它还必须要包括修改的动机,以及和跟上一版本相比的改动点。
示例:
The body is mandatory for all commits except for those of scope "docs".
When the body is required it must be at least 20 characters long.
Revert Commit¶
备注
除了 Header、Body 和 Footer 这 3 个部分,Commit Message 还有一种特殊情况:如果当前 commit 还原了先前的 commit,则应以 revert: 开头,后跟还原的 commit 的 Header。而且,在 Body 中必须写成 This reverts commit ,其中 hash 是要还原的 commit 的 SHA 标识。
示例:
revert: feat(iam-apiserver): add 'Host' option
This reverts commit 079360c7cfc830ea8a6e13f4c8b8114febc9b48a.
Commit 相关的 3 个重要内容¶
提交频率¶
两种情况:
1. 只要我对项目进行了修改,一通过测试就立即 commit
比如修复完一个 bug、开发完一个小功能,或者开发完一个完整的功能,测试通过后就提交
2. 规定一个时间,定期提交
这里我建议代码下班前固定提交一次,并且要确保本地未提交的代码,延期不超过 1 天
这样,如果本地代码丢失,可以尽可能减少丢失的代码量
合并提交¶
合并提交,就是将多个 commit 合并为一个 commit 提交:
2 种方式提交代码,你可能会觉得代码 commit 比较多,看起来比较随意
想等开发完一个完整的功能之后,放在一个 commit 中一起提交
可以在最后合并代码或者提交 Pull Request 前,执行 git rebase -i 合并之前的所有 commit
修改 Commit Message¶
有两种修改方法:
1. git commit --amend:修改最近一次 commit 的 message
2. git rebase -i:修改某次 commit 的 message
Commit Message 规范自动化¶
这些自动化功能可以分为以下 2 类:
1. Commit Message 生成和检查功能:
a. 生成符合 Angular 规范的 Commit Message
b. Commit Message 提交前检查
c. 历史 Commit Message 检查
2. 基于 Commit Message 自动生成 CHANGELOG 和 SemVer 的工具
通过下面这 5 个工具自动的完成上面的功能:
1. commitizen-go:
使你进入交互模式,并根据提示生成 Commit Message,然后提交
https://github.com/lintingzhen/commitizen-go
2. commit-msg:
githooks,在 commit-msg 中,指定检查的规则
commit-msg 是个脚本,可以根据需要自己写脚本实现
3. go-gitlint:
检查历史提交的 Commit Message 是否符合 Angular 规范,
可以将该工具添加在 CI 流程中,确保 Commit Message 都是符合规范的
https://github.com/llorllale/go-gitlint
4. gsemver:
语义化版本自动生成工具
https://github.com/arnaud-deprez/gsemver
5. git-chglog:
根据 Commit Message 生成 CHANGELOG
https://github.com/git-chglog/git-chglog
实战¶
pre-commit:
# Copy githook scripts when execute makefile
COPY_GITHOOK:=$(shell cp -f githooks/* .git/hooks/)
参考¶
Conventional Commits 1.0.0-beta.4: https://www.conventionalcommits.org/en/v1.0.0-beta.4/
How to Write a Git Commit Message: https://chris.beams.io/posts/git-commit/
Go Code Review Comments: https://github.com/golang/go/wiki/CodeReviewComments