Skip to content

告别 fix bug!拯救Git Commit Log的规范

哈喽,大家好呀,我是呼噜噜,在企业软件开发工作中,常常使用 Git 来管理代码,每当我们对代码进行改动时,都需要通过 git commit 来对代码提交,说明本次提交的目的,什么改动等

但在实际开发中,如果团队没有规定,提交的 commit message 千奇百怪;或者就自己一个人独立开发,那必须"怎么快怎么来",结果项目复杂度上来后,出问题的那一刻,看着提交记录满屏的

"fix bug"

"fix bug"

"fix bug"

...

完全看不出来,每个提交的"fix bug"修改的是什么问题? 再看下提交人 呵 竟然是自己!!! 只能熬夜加班~

所以良好规范的 commit,能够提升提交记录的可读性自动化处理能力,帮助我们review代码,问题排查和版本追溯。还能够通过一些工具(如 standard-version),自动生成版本变动内容,Github 上许多开源项目就是这么处理的。从长远来看,编写良好规范的 commit,可以提高代码维护效率和质量。

Conventional Commits 规范

如今比较流行的Git规范是Conventional Commits,它是一套基于 Git 提交消息的轻量级约定,旨在通过结构化格式提升提交信息的可读性和自动化处理能力。引导开发者在提交时思考并明确表达变更的性质、范围和影响。

这是一套被 Angular、Vue 等顶级开源项目广泛采用的 Git 提交规范,它的核心目标包括:

  • 人类可读:清晰描述提交的意图和影响范围。
  • 机器友好:支持自动化生成 CHANGELOG 和语义化版本(SemVer)。
  • 团队协作:统一提交风格,减少沟通成本。

提交消息的结构应如下所示:

plain
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

type

其中type代表的是提交内容的一种类型,必写,每一种类型都代表着不同的含义,具体的类型取值和含义如下

  1. feat:表示开发一个新的需求特性
  2. fix:表示修复一个 bug
  3. refactor:不是进行 featfix 的代码修改,重构功能
  4. perf:优化相关,比如提升性能、体验
  5. docs:表示是针对文档的修改,并没有修改代码
  6. style:格式修改,不影响代码功能
  7. test:添加测试代码或者修正已经存在的测试功能代码
  8. chore:一些不够影响到源码和测试文件的修改
  9. ci:用于提交CI配置文件和脚本的修改
  10. build:修改会影响构建或者依赖的代码
  11. release:发布新版本
  12. revert:针对之前的一个提交的 回滚
  13. ...

scop

scope,表示commit 影响的范围,可写但推荐,若涉及范围较大,可用 * 代替,比如: route, component, utils...

例如:feat(auth): add JWT authentication,表示在 auth 模块中新增了 JWT 身份验证功能

subject

subject 表示 commit 的概述,必写,标题简述修改,结尾不要有句号

例如:fix: correct typo in README,表示修复了 README 文件中的拼写错误

body

body 表示 commit 具体说明修改的内容, 可以分为多行,可选

例如: feat: 新增用户管理功能

footer脚释,可选,用于记录与提交相关的其他信息,如关联的任务、问题或破坏性变更。它通常以 BREAKING CHANGE: 开头,后跟详细说明。脚注也可以包含引用的 issue 编号或链接

plain
BREAKING CHANGE:
- 更新了 API 接口,删除了 `getUser` 方法,改为 `fetchUser`。
- 需要更新客户端代码以适应新接口。
Closes #123
Review by @zhangsan

重大变更

重大变更 必须 通过在 type/scope 前缀中添加 ! 或在 footer 中使用 BREAKING CHANGE: 来指明。

如果使用了 !,则 BREAKING CHANGE: footer 是可选的,提交描述将用作变更的说明

例如:refactor!(auth): remove deprecated JWT authentication method

注意:这里的 ! 表明这是一个破坏性变更,即使typerefactor

约定式提交规范

  1. 每个提交都必须使用类型字段前缀,它由一个名词组成,诸如featfix,其后接一个可选的作用域字段,以及一个必要的冒号(英文半角)和空格。
  2. 当一个提交为应用或类库实现了新特性时,必须使用feat类型。
  3. 当一个提交为应用修复 bug 时,必须使用fix类型。
  4. 作用域字段可以跟随在类型字段后面。作用有必须是一个描述某部分代码的名词,并用圆括号包围,例如:fix(parser):
  5. 描述字段必须紧接在类型/作用域前缀的空格之后。描述指的是对代码变更的简短总结,例如:fix:array parsing issue when multiplejspaces were contained in string
  6. 在简短描述之后,可以编写更长的提交正文,为代码变更提供额外的上下文信息。正文必须起始于描述字段结束的一个空行后。
  7. 在正文结束的一个空行之后,可以编写一行或或多行脚注。脚注必须包含关于提交的元信息,例如:关联的合并请求、Reviewer、破坏性变更、每条元信息一行。
  8. 破坏性变更必须标示在正文区域最开始处,或脚注区域中某一行的开始。一个破坏性变更必须包含大写的文本BREAKING CHANGE,后面紧跟冒号和空格。
  9. BREAKING CHANGE:之后必须提供描述,以描述对 API 的变更。例如:BREAKING CHANGE: enviroment variables now take precedence over cofig files
  10. 在提交说明中,可以使用featfix之外的类型。
  11. 工具的实现必须不区分大小写地解析构成约定式提交的信息单元,只有BREAKING CHANGE必须是大写的。
  12. 可以在类型/作用域前缀之后,:之前,附加!字符,以进一步提醒注意破坏性变更。当有!前缀时,正文或脚注内必须包含BREAKING CHANGE: description

为什么要使用 Conventional Commits?

  • 我们先回顾一些,常见的提交信息不规范情况以及痛点:
plain
1. 混乱的提交信息是常态:
    `fix bug`(修复了什么 bug?)
    `update`(更新了什么?)
    `asdf`(毫无意义)
    大段无结构描述(难以快速抓住重点)
2.  大型项目/团队的痛点:
    难以从 `git log` 快速理解项目演进。
    定位引入 bug 或特定功能的提交如同大海捞针。
    代码审查 (`code review`) 效率低下。
    自动化流程(如生成变更日志)难以实现。
  • 提交信息的好处:
  1. 自动生成 Change Log:轻松跟踪项目的更改历史和版本更新
  2. 自动确定语义版本更新:根据提交类型自动确定版本更新(fix 对应 PATCHfeat 对应 MINORBREAKING CHANGE 对应 MAJOR
  3. 将变更的性质传达给团队成员、公众和其他利益相关者,更清晰的沟通
  4. 触发自动构建和发布流程
  5. 使开发者更容易理解和遵循项目规范,使开发者更容易为您的项目做出贡献

常用的工具帮助指引更好的落地

  1. Commitizen: 交互式命令行工具,引导用户创建符合规范的提交信息。
  2. Commitlint: 用于校验提交信息是否符合规范,常与 Git Hooks (如 husky) 集成,可以在提交时自动检查规范,确保团队规范落地执行
  3. 自动化版本与 Changelog 工具: 如 semantic-release, goreleaser/chglog
  4. IDE 插件: 主流 IDE (VS Code, JetBrains IDEs 等) 均有插件提供模板、补全和校验支持。

尾语

Conventional Commits 不仅是技术规范,更是团队协作的沟通协议。它可以引导我们的每一次git commit不再是随意的记录,而是对项目演进负责任的、有意义的贡献。

参考:

https://www.conventionalcommits.org/en/v1.0.0


作者:小牛呼噜噜

本文到这里就结束啦,感谢阅读,关注同名公众号:小牛呼噜噜,防失联+获取更多技术干货