如何编写清晰的Git commit message


还在为写 Git commit message 头疼吗?还在羡慕别人清晰的提交历史吗?别慌,这篇文章带你彻底搞定 Git commit message,让你和你的团队协作效率瞬间起飞!

想象一下,几个月后你回过头来看自己写的代码,或者更惨,去维护一个“上古项目”,面对一堆 update code 或者 fix bug 这样的提交记录,是不是瞬间血压飙升?

一个好的 commit message 不仅能让你快速了解每次提交的修改内容,更能极大地提升团队协作的效率。 而且,规范的提交信息还能自动化生成项目更新日志(Change Log),简直是懒人福音!

那么,如何编写清晰的 Git commit message 呢?社区里最流行的规范之一就是 Conventional Commits(约定式提交)。 这套规范非常简单,而且功能强大,已经被很多知名开源项目采用。


约定式提交规范长啥样?

别被“规范”两个字吓到,其实它非常简单,格式如下:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

一个 commit message 主要包含三个部分:Header(必需),Body(可选)和 Footer(可选)。

1. Header(标题行)

这是最重要的一部分,也是唯一必需的部分。它又由三个小部分组成:typescopesubject

  • type (类型) [必需]: 用来说明这次提交的类别。 常见的类型有:

    • feat: 新功能 (feature)

    • fix: 修复 bug

    • docs: 只修改了文档 (documentation)

    • style: 代码格式修改,不影响代码逻辑 (比如删除空格、格式化等)

    • refactor: 代码重构,既不是新增功能,也不是修复 bug

    • test: 增加或修改测试用例

    • chore: 构建过程或辅助工具的变动 (比如修改依赖、脚本等)

    • perf: 提升性能的代码更改

    • revert: 撤销之前的提交

    • *划重点:** featfix 类型的提交会自动出现在最终的 Change Log 里。

  • scope (影响范围) [可选]: 用来说明本次提交影响的范围,比如某个模块、某个组件等。 它可以让信息更具体。例如 feat(api)fix(parser)

  • subject (简短描述) [必需]: 对本次提交的简短描述,不超过50个字符。 记住几个原则:

    • 以动词开头,使用现在时态,比如用 add 而不是 addedadds
    • 第一个字母小写。
    • 结尾不加句号。

一个好的 Header 示例:

feat(user): add user registration endpoint

这个标题清晰地告诉我们:这是一个新功能,影响的是用户模块,具体内容是增加了用户注册的接口。

2. Body (详细描述)

如果一次提交的内容比较复杂,只用一行 subject 无法说清楚,那么你就需要 body 部分了。在这里,你可以详细描述代码变动的动机,以及与之前行为的对比。

  • bodyheader 之间必须有一个空行。
  • 每行建议不超过72个字符,以保证在各种工具里都能良好显示。

一个带有 Body 的示例:

fix(api): prevent racing of requests

Introduce a request id and a reference to the latest request.
Dismiss incoming responses other than from the latest request.

Remove timeouts which were used to mitigate the racing issue but are
obsolete now.

footer 部分主要用于两种情况:

  • 重大变更 (Breaking Change): 如果你的代码修改与上一个版本不兼容,就必须在 footer 里注明。以 BREAKING CHANGE: 开头,后面是对变动的描述、理由和迁移方法。
  • 关闭 Issue: 如果这次提交修复了某个 Issue,可以在这里关闭它。例如 Closes #123Fixes #456

一个完整的示例:

feat(api)!: send an email to the customer when a product is shipped

BREAKING CHANGE: The `extends` key in the config file is now used for extending other config files.

Refs: #123

注意到 feat(api)! 中的 ! 了吗?这是重大变更的简写形式,能让变更在提交历史中更加醒目。


案例分析:从“糟糕”到“清晰”

光说不练假把式,我们来看个实际案例。

糟糕的提交历史:

$ git log --oneline
a7b27c2 update
c5d34f1 fix bug
e1f3a9b add user stuff

这样的历史记录,除了提交者本人,恐怕没人能看懂。

清晰的提交历史:

$ git log --oneline
a7b27c2 feat(user): add user profile page
c5d34f1 fix(auth): correct password hashing logic
e1f3a9b docs(readme): update installation instructions

是不是瞬间清晰了很多?通过行首的 type,我们可以快速过滤和查找想要的信息。 比如,只想看新增了哪些功能:

git log --oneline --grep "feat"

懒人必备:自动化工具

“道理我都懂,但就是懒得写这么规范怎么办?” 别担心,社区早就为我们准备好了神器!

  • Commitizen: 一个命令行工具,可以通过交互式问答的方式,引导你生成符合规范的 commit message。再也不用死记硬背 type 类型了!
  • Commitlint + Husky: commitlint 用来检查你的 commit message 是否符合规范,而 husky 则可以让你在 git commit 时自动触发 commitlint 的检查。如果不符合规范,直接就提交失败,从源头上杜绝不规范的 message。

如何配置 (简单示例):

  1. 安装依赖:
    npm install --save-dev @commitlint/config-conventional @commitlint/cli husky
  2. 配置 commitlint (在项目根目录创建 commitlint.config.js):
    module.exports = {extends: ['@commitlint/config-conventional']};
  3. 配置 husky (在 package.json 中添加):
    "husky": {
      "hooks": {
        "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
      }
    }
    通过简单的配置,你的项目就拥有了 commit message 的“守护神”。

总结

编写清晰的 Git commit message 是一项投入产出比极高的开发习惯。它不仅能让你的提交历史清晰易读,还能极大地提升团队协作效率,并为自动化工具赋能。 遵循约定式提交规范,并借助自动化工具,你也能轻松写出专业、漂亮的 commit message。

从今天起,告别模糊不清的 update code,拥抱清晰明了的提交历史吧!


  目录