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 版本 .. note:: 总结来说,一个好的 Commit Message 规范可以使 Commit Message 的可读性更好,并且可以实现自动化。 Commit Message 的规范:: 建议你采用开源社区中比较成熟的规范 例如 jQuery、Angular 等 .. figure:: https://img.zhaoweiguo.com/knowledge/images/soft-engineerings/standard-commit1.webp 社区中的多种 Commit Message 的规范 Angular 规范是一种语义化的提交规范(Semantic Commit Messages),所谓语义化的提交规范包含以下内容:: 1. Commit Message 是语义化的 Commit Message 都会被归为一个有意义的类型,用来说明本次 commit 的类型 2. Commit Message 是规范化的 Commit Message 遵循预先定义好的规范,比如 Commit Message 格式固定、都属于某个类型,这些规范不仅可被开发者识别也可以被工具识别 .. figure:: https://img.zhaoweiguo.com/knowledge/images/soft-engineerings/standard-commit2.png 遵循 Angular 规范的 commit 历史记录 在 Angular 规范中,Commit Message 包含三个部分,分别是 Header、Body 和 Footer,格式如下:: [optional scope]: // 空行 [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 这类修改会影响最终的用户和生产环境的代码。 所以对于这种改动,我们一定要慎重,并在提交前做好充分的测试。 .. figure:: https://img.zhaoweiguo.com/knowledge/images/soft-engineerings/standard-commit3.webp Angular 规范中的常见 type 和它们所属的类别,你在提交 Commit Message 的时候,一定要注意区分它的类别。 .. figure:: https://img.zhaoweiguo.com/knowledge/images/soft-engineerings/standard-commit4.webp 如何确定一个 commit 所属的 type: .. note:: 1. 如果我们变更了应用代码,比如某个 Go 函数代码,那这次修改属于代码类。在代码类中,有 4 种具有明确变更意图的类型:feat、fix、perf 和 style;如果我们的代码变更不属于这 4 类,那就全都归为 refactor 类,也就是优化代码。 .. note:: 2. 如果我们变更了非应用代码,例如更改了文档,那它属于非代码类。在非代码类中,有 3 种具有明确变更意图的类型:test、ci、docs;如果我们的非代码变更不属于这 3 类,那就全部归入到 chore 类。 scope:: 不同项目会有不同的 scope: 1. 项目初期: 我们可以设置一些粒度比较大的 scope,比如可以按组件名或者功能来设置 scope 2. 项目中期: 如果项目有变动或者有新功能,我们可以再用追加的方式添加新的 scope .. note:: 要强调的是,scope 不适合设置太具体的值。太具体的话,一方面会导致项目有太多的 scope,难以维护。另一方面,开发者也难以确定 commit 属于哪个具体的 scope,导致错放 scope,反而会使 scope 失去了分类的意义。 .. note:: 需要遵循我们预先规划的 scope,所以我们要将 scope 文档化,放在类似 devel 这类文档中。 subject:: commit 的简短描述,必须以动词开头、使用现在时。 比如,我们可以用 change,却不能用 changed 或 changes,而且这个动词的第一个字母必须是小写。 通过这个动词,我们可以明确地知道 commit 所执行的操作。 此外我们还要注意,subject 的结尾不能加英文句号。 Body ---- .. note:: 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. Footer ------ .. note:: Footer 部分不是必选的,可以根据需要来选择,主要用来说明本次 commit 导致的后果。在实际应用中,Footer 通常用来说明不兼容的改动和关闭的 Issue 列表 示例:: BREAKING CHANGE: // 空行 // 空行 // 空行 Fixes # 1. 不兼容的改动:: 如果当前代码跟上一个版本不兼容,需要在 Footer 部分,以 BREAKING CHANG: 开头,后面跟上不兼容改动的摘要。 Footer 的其他部分需要说明变动的描述、变动的理由和迁移方法 BREAKING CHANGE: isolate scope bindings definition has changed and the inject option for the directive controller injection was removed. To migrate the code follow the example below: Before: scope: { myAttr: 'attribute', } After: scope: { myAttr: '@', } The removed `inject` wasn't generaly useful for directives so there should be no code using it. 2. 关闭的 Issue 列表:: 关闭的 Bug 需要在 Footer 部分新建一行,并以 Closes 开头列出,例如:Closes #123。 如果关闭了多个 Issue,可以这样列出:Closes #123, #432, #886。例如: Change pause version value to a constant for image Closes #1137 Revert Commit ------------- .. note:: 除了 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 的工具 .. figure:: https://img.zhaoweiguo.com/knowledge/images/soft-engineerings/standard-commit5.webp 围绕着 Commit Message 实现的一些自动化功能 通过下面这 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