程序锅

  • 首页
  • 分类
  • 标签
  • 归档
  • 关于

  • 搜索
基础知识 Etcd LeetCode 计算机体系结构 Kubernetes Containerd Docker 容器 云原生 Serverless 项目开发维护 ELF 深入理解程序 Tmux Vim Linux Kernel Linux numpy matplotlib 机器学习 MQTT 网络基础 Thrift RPC OS 操作系统 Clang 研途 数据结构和算法 Java 编程语言 Golang Python 个人网站搭建 Nginx 计算机通用技术 Git

Git | Git Commit 规范

发表于 2021-07-03 | 分类于 Git | 0 | 阅读次数 2627

1. Commit Message 的重要性

  • 可以使自己或者其他开发人员能够清晰地知道每个 commit 的变更内容,方便快速浏览变更历史,比如可以直接略过文档类型或者格式化类型的代码变更。
  • 可以基于这些 Commit Message 进行过滤查找,比如只查找某个版本新增的功能:git log --oneline --grep "feat|fix|^perf"。
  • 可以基于规范化的 Commit Message 生成 Change Log。
  • 可以依据某些类型的 Commit Message 触发构建或者发布流程,比如当 type 类型为 feat、fix 时我们才触发 CI 流程。
  • 确定语义化版本的版本号。比如 fix 类型可以映射为 PATCH 版本,feat 类型可以映射为 MINOR 版本。带有 BREAKING CHANGE 的 commit,可以映射为 MAJOR 版本。

总结来说,一个好的 Commit Message 规范可以使 Commit Message 的可读性更好,并且可以实现自动化。

2. 规范

2.1. 应该有的样子

社区已有多种 Commit Message 的规范了,例如 JQuey、Angular 等,这些规范的关系如下所示

而不管什么样的规范,个人认为一个好的 Commit Message 从结构上应该由以下三个部分组成:

  • 主题

    主题应该只有一行,是对你 commit 的总结。这个句子应该用祈使句的语气,以大写字母开头,不以句号为结束符,并且字数应该少于等于 50 。

    这个主题句子可以很好地填充 “This commit will ......” 这个句子,比如 “add new neural network model to back-end”。

  • 正文

    正文应该包含了 commit 的要点,通过正文可以了解更改的详细信息。在正文中你应该详细地阐述 commit 所做的改变,以及阐述你这么做的上下文,比如解释为什么做出这样的改变,为什么选择使用这种方式去实现你的改变,以及其他可以理解这个 commit 的背后思考过程。同时没有必要重复阐述那些通过 diff 命令就可以看出来的改变,也没有必要一行一行的进行解释。一定要专注于更高级的细节,这些细节是通过读代码不好发现的。总的来说,正文内容的目标是提供这么改变的上下文,这个上下文主要包括修改的东西和目标。

    另外对于一些很小的 commits 来说,比如 “fixing a typo” 这种的,那么就可以不需要正文了,因为主题句中已经提供了足够多的信息了。

  • 结束语

    结束语应该是 commit message 的最后一行。这一行中你可以放一些关于 commit 的有用的 meta-data。比如 Github issue numbers,co-author names 和额外的链接。这些可以帮助你找到跟这个 commit 有关的重要信息。

2.2. Angular 规范

Angular 规范在功能上能够满足开发者 commit 需求,在格式上清晰易读,目前也是用得最多的。Angular 规范是一种语义化的提交规范(Semantic Commit Messages),语义化的提交规范包含两方面:

  • 语义化:Commit Message 都会被归为一个有意义的类型,用来说明本次的 commit 类型。
  • 规范化:Commit Message 遵循预先定义好的规范,比如 Commit Message 格式固定、都属于某个类型,这些规范不仅可被开发者识别也可以被工具识别。

下面是 Angular 规范的一个例子:

Angular 规范的 Commit Message 包含了三部分:Header、Body、Footer,格式如下所示。其中 Header 是必需的,Body 和 Footer 都是可以省略的。其中 Header、Body、Footer 之间必须要有空行。

<type>[optional scope]: <description>
// 空行
[optional body]
// 空行
[optional footer(s)]

2.2.1. Header

Header 部分只有一行,包含了三个字段:type(必选)、scope(可选,有的话需要用 () 括起来)和 description(subject,必选)。<type>[optional scope] 后必须紧跟冒号,冒号后面必须紧跟空格。

  • type 字段,这个字段用来说明 commit 的类型。

    Angular 规范中常见的 type 如下图所示,其中这些 type 大致可以归为两大类:

    • Production:这类修改会影响最终的用户和生产环境的代码。所以对于这种改动,我们一定要慎重,并在提交前做好充分的测试。比如,在做 code review 的时候,如果遇到 Production 类型的代码,一定要认真 Review,因为这种类型,会影响到现网用户的使用和现网应用的功能。
    • Development:这类修改一般是项目管理类的变更,不会影响最终用户和生产环境的代码,比如 CI 流程、构建方式等的修改。遇到这类修改,通常也意味着可以免测发布。

    如何确定一个 commit 所属的 type 呢?可以通过下面这张图来确定。

    • 如果我们变更了应用代码,比如某个 Go 函数代码,那这次修改属于代码类。在代码类中,有 4 种具有明确变更意图的类型:feat、fix、perf 和 style;如果我们的代码变更不属于这 4 类,那就全都归为 refactor 类,也就是优化代码。

      有冲突后的 commit 可以使用 refactor。

    • 如果我们变更了非应用代码,例如更改了文档,那它属于非代码类。在非代码类中,有 3 种具有明确变更意图的类型:test、ci、docs;如果我们的非代码变更不属于这 3 类,那就全部归入到 chore 类。

    Angular 的 Commit Message 规范提供了大部分的 type,在实际开发中,我们可以使用部分 type,或者扩展添加我们自己的 type。但无论选择哪种方式,我们一定要保证一个项目中的 type 类型一致。

  • scope 字段,scope 是用来说明 commit 的影响范围的,它必须是名词。

    显然,不同项目会有不同的 scope。在项目初期,我们可以设置一些粒度比较大的 scope,比如可以按组件名或者功能来设置 scope;后续,如果项目有变动或者有新功能,我们可以再用追加的方式添加新的 scope。

    这里想强调的是,scope 不适合设置太具体的值。太具体的话,一方面会导致项目有太多的 scope,难以维护。另一方面,开发者也难以确定 commit 属于哪个具体的 scope,导致错放 scope,反而会使 scope 失去了分类的意义。

    在指定 scope 时需要遵循我们预先规划的 scope。除此之外,我们要将 scope 文档化,放在类似 devel 这类文档中。比如下面这样

    参考:https://github.com/marmotedu/iam/blob/master/docs/devel/zh-CN/scope.md

  • subject 字段,即 description 部分。

    subject 是 commit 的简短描述,必须以动词开头、使用现在时(比如,我们可以用 change,却不能用 changed 或 changes)。这个动词的第一个字母必须是小写,通过这个动词,我们可以明确地知道 commit 所执行的操作。此外,subject 的结尾不能加英文句号。

2.2.2. Body

Body 部分是对本次 commit 的更详细描述,是可选的。

Body 部分可以分成多行,而且格式也比较自由。Body 中需要包含修改的动机,以及跟上一版本相比的改动点。

2.2.3. Footer

Footer 部分用来说明本次 commit 导致的后果,是可选的。

在实际应用中,Footer 通常用来说明不兼容的改动和关闭的 Issue 列表,格式如下所示:

BREAKING CHANGE: <breaking change summary>
// 空行
<breaking change description + migration instructions>
// 空行
// 空行
Fixes #<issue number>
  • 不兼容的改动:如果当前代码跟上一个版本不兼容,需要在 Footer 部分,以 BREAKING CHANG: 开头。后面跟上不兼容改动的摘要。之后空一行,来说明变动的描述、变动的理由和迁移方法。示例如下所示:

    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.
    
  • 关闭的 Issue 列表:关闭的 Bug 需要在 Footer 部分新建一行,并以 Closes 开头列出,例如:Closes #123。如果关闭了多个 Issue,可以这样列出:Closes #123, #432, #886。

    Change pause version value to a constant for image
    
    Closes #1137
    

2.2.4. 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.

2.2.5. 其他

  • 为了使 Commit Message 在 GitHub 或者其他 Git 工具上更加易读,往往会限制每行 message 的长度。根据需要,可以限制为 50/72/100 个字符,这里我将长度限制在 72 个字符以内(也有一些开发者会将长度限制为 100,你可根据需要自行选择)。
  • 为了更好地遵循 Angular 规范,建议你在提交代码时养成不用 git commit -m,即不用 -m 选项的习惯,而是直接用 git commit 或者 git commit -a 进入交互界面编辑 Commit Message。这样可以更好地格式化 Commit Message。

3. Commit Message 规范自动化

有一定的规范之后,我们可以使用一些工具,来自动化地做以下这些事情:

  • Commit Message 生成和检查功能:生成符合 Angular 规范的 Commit Message、Commit Message 提交前检查、历史 Commit Message 检查。
  • 基于 Commit Message 自动生成 CHANGELOG 和 SemVer 的工具。

可以通过以下几个工具自动完成上面的功能:

  • commitizen-go(https://github.com/lintingzhen/commitizen-go):使你进入交互模式,并根据提示生成 Commit Message,然后提交。
  • commit-msg:githooks,在 commit-msg 中,指定检查的规则,commit-msg 是个脚本,可以根据需要自己写脚本实现。这门课的 commit-msg 调用了 go-gitlint 来进行检查。
  • go-gitlint(https://github.com/llorllale/go-gitlint):检查历史提交的 Commit Message 是否符合 Angular 规范,可以将该工具添加在 CI 流程中,确保 Commit Message 都是符合规范的。
  • gsemver(https://github.com/arnaud-deprez/gsemver):语义化版本自动生成工具。
  • git-chglog(https://github.com/git-chglog/git-chglog):根据 Commit Message 生成 CHANGELOG。

4. 规范推荐网址

https://www.conventionalcommits.org/en/v1.0.0-beta.4/

5. Commit 相关的 3 个重要内容

除了 Commit Message 规范之外,在代码提交时,我们还需要关注 3 个重点内容:提交频率、合并提交和 Commit Message 修改

5.1. 提交频率

在实际项目开发中,如果是个人项目,随意 commit 可能影响不大,但如果是多人开发的项目,随意 commit 不仅会让 Commit Message 变得难以理解,还会让其他研发同事觉得你不专业。因此,我们要规定 commit 的提交频率。

进行 commit 的时候一般分为两种情况:

  • 只要我对项目进行了修改,一通过测试就立即 commit。比如修复完一个 bug、开发完一个小功能,或者开发完一个完整的功能,测试通过后就提交。
  • 我们规定一个时间,定期提交。这里我建议代码下班前固定提交一次,并且要确保本地未提交的代码,延期不超过 1 天。这样,如果本地代码丢失,可以尽可能减少丢失的代码量。

5.2. 合并提交

上述两种方式提交代码,可能会导致代码 commit 比较多,看起来比较随意。另外,有时候想等一个功能开发完成之后,将所有 commit 放在一个 commit 中。这个时候可以在最后合并代码或者提交 pull request 前,可以使用 git rebase -i <commit ID> 将若干个 commit 合并为一个 commit。

如果有太多的 commit 需要合并的话,可以尝试撤销过去的 commit,然后重新提交一个新的 commit。但是需要说明的一点是,除了 commit 实在太多的时候,一般情况不采用这种方法,比较粗暴,而且之前提交的 commit message 都得重新提交一遍。

$ git reset HEAD~3
$ git add .
$ git commit -am "feat(user): add user resource"

合并提交的建议:在把新的 commit 合并到主干的时候,最好只保留 2-3 个 commit 记录。

5.3. 修改 Commit Message

有时候我们希望修改某次 commit message,那么有以下两种方式:

  • git commit --amend:修改最近一次 commit 的 message;
  • git rebase -i:修改某次 commit 的 message。

需要注意的是:

  • Commit Message 是 commit 数据结构中的一个属性,如果 Commit Message 有变更,则 commit ID 一定会变,git commit --amend 只会变更最近一次的 commit ID,但是 git rebase -i 会变更父 commit ID 之后所有提交的 commit ID。

  • 如果当前分支有未 commit 的代码,需要先执行 git stash 将工作状态进行暂存,当修改完成后再执行 git stash pop 恢复之前的工作状态。

卷死我
dawnguo 微信支付

微信支付

dawnguo 支付宝

支付宝

  • 本文作者: dawnguo
  • 本文链接: /archives/6
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# Git # 计算机通用技术
操作系统 | 文件系统之基于 inode 的文件系统
容器 | Containerd 完整介绍
  • 文章目录
  • 站点概览
dawnguo

dawnguo

215 日志
24 分类
37 标签
RSS
Creative Commons
© 2018 — 2025 程序锅
0%