前言
不知道你是否会在每次commit的时候都纠结该如何描述,如果有的话,则说明你对git commit的标准不太了解,其实早已有人制定了一个比较规范的git commit标准,叫作 Angular规范 ,在阮一峰老师这篇:Commit message 和 Change log 编写指南 文章中比较详细的记录了相关的细节
但是阮一峰老师这篇文章中缺少对全流程的描述、工具的使用等细节,这对初学者来说会比较困惑,本文就解决这个部分的内容
Commit message 的格式
每次提交,Commit message 都包括三个部分:Header,Body 和 Footer
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
其中,Header 是必需的,Body 和 Footer 可以省略
不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。这是为了避免自动换行影响美观
Header
Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。
-
**type:**用于说明 commit 的类别,只允许使用下面7个标识,最常用!!
- feat:新功能(feature)
- fix:修补bug
- docs:文档(documentation)
- style: 格式(不影响代码运行的变动)
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
如果
type为feat和fix,则该 commit 将肯定出现在 Change log 之中。其他情况(docs、chore、style、refactor、test)由你决定,要不要放入 Change log,建议是不要 -
scope:用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同
-
subject:commit 目的的简短描述,不超过50个字符
- 以动词开头,使用第一人称现在时,比如
change,而不是changed或changes - 第一个字母小写
- 结尾不加句号(
.)
- 以动词开头,使用第一人称现在时,比如
Body
Body 部分是对本次 commit 的详细描述,可以分成多行。下面是一个范例
More detailed explanatory text, if necessary. Wrap it to
about 72 characters or so.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Use a hanging indent
有两个注意点
- 使用第一人称现在时,比如使用
change而不是changed或changes。 - 应该说明代码变动的动机,以及与以前行为的对比
Footer
Footer 部分只用于两种情况。
-
不兼容变动
如果当前代码与上一个版本不兼容,则 Footer 部分以
BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移方法BREAKING CHANGE: isolate scope bindings definition has changed. 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
如果当前 commit 针对某个issue,那么可以在 Footer 部分关闭这个 issue
Closes #234也可以一次关闭多个 issue
Closes #123, #245, #992
Revert
还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以revert:开头,后面跟着被撤销 Commit 的 Header
revert: feat(pencil): add 'graphiteWidth' option
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
Body部分的格式是固定的,必须写成This reverts commit <hash>.,其中的hash是被撤销 commit 的 SHA 标识符。
如果当前 commit 与被撤销的 commit,在同一个发布(release)里面,那么它们都不会出现在 Change log 里面。如果两者在不同的发布,那么当前 commit,会出现在 Change log 的Reverts小标题下面
1. 背景:Git Commit 规范的用途及其在 GitHub Flow 中的位置
以防你不知道 github flow 是什么,你可以先阅读关于github flow的介绍,简单来说在一个标准flow中,每一次的 git commit 的记录应该是清晰符合标准的,这样才方便协作
目前大多使用Angular这个规范,当然这只是一个规范或者说指导,并不是强制的执行标准,不过和其他规范一样,其意义是确保每次提交都具备清晰、规范、易读的描述,这不仅有助于团队协作,也方便后续代码回溯、问题定位和版本管理。良好的提交信息能够让代码仓库的历史更具可读性,减少沟通成本
在 GitHub Flow 中,commit 是开发流程中的关键阶段,通常发生在本地分支开发完成后,将代码推送到远程分支之前。具体位置包括:
- 开发分支编写代码时:每次功能点、修复、重构,都需要对应一条符合规范的 commit。
- Pull Request(PR)创建前:PR 提交的代码通过 commit 反映变更的意图和细节。
- 代码合并时:规范的 commit 信息方便合并历史的审查和版本发布日志的生成。
通过统一 commit 规范,团队成员可以快速理解代码变更的内容和目的,从而提高协作效率和项目质量。
2. 补充:利用工具和 IDE 插件优雅书写和检查 Git Commit
补充阮一峰老师文章:现代编码都是基于IDE,且往往是图像界面操作,所以git commit 的规范化也可以结合IDE进行
编写规范的 commit 信息看似简单,但实际操作中往往会因为格式、内容不规范导致团队沟通障碍。为此,可以借助以下工具和插件提升体验:
- VSCode 插件(入门推荐):
- Git Commit Plugin:自动模板填写,支持类型选择和内容校验
- Conventional Commits:提供格式化建议和提示,避免语法错误
- 多插件组合(进阶):本地环境需要做比较多的配置,详情可参考 约束每一次提交
- **Husky:**自动在 commit 阶段运行 commitlint 检查提交信息格式,防止不规范的提交进入代码库
- _(可选)__lint-staged:_在提交的代码的时候,可以通过 配置其他的 Lint、工具来格式化代码
- **commitlint:**基于规则的 commit message 校验工具,可以根据 Angular 规范定义规则,并结合 Husky 在本地钩子中执行
- Commitizen:一个命令行工具,可以引导开发者按照规范交互式填写 commit 信息,与上述IDE中插件功能一致
合理使用工具可以大幅减少人工检查的成本,让 commit 编写过程更流畅、规范
下面是一个使用 Git Commit Plugin 的示例,其他的插件也差不多




3. 补充:如何优雅生成 CHANGELOG(不完全)
如果你注意观察的话,在一些开源软件中包含一个CHANGELOG文件或者是文件夹,里面描述了每次版本迭代所做出的改变,并且还包括此次更新所关闭的issus等,这是一种比较优雅的方式,但其实这部分的内容很多是基于自动化工具生成,然后再人工进行的校验,其中自动化生成的关键就是需要使用规范的commit标准
自动生成 CHANGELOG 可以提高效率,也保证日志的准确和一致性。常用的工具包括:
- standard-version:基于 commit message 语义自动生成 CHANGELOG,支持版本号自动递增,适合无发布服务器的项目。
- semantic-release:自动根据 commit 类型判断版本号(major、minor、patch),生成 CHANGELOG,并自动发布版本到 npm 或其他平台,适合持续集成环境。
- lerna(多包管理时):支持根据多个包的 commit 生成统一 CHANGELOG。
- GitHub Action:
- 使用
release-drafter自动汇总 PR 标题和 commit 生成 Release Notes。 auto-changelog集成到 CI 流水线自动更新日志。
- 使用
通过这些工具:
- 避免人工写 CHANGELOG 的错误和遗漏。
- 让每次发布都有标准化的变更说明。
- 方便用户和团队查看版本更新内容。
IDE 也有相关插件,结合上述工具可以实现一键生成和预览 CHANGELOG,提升用户体验。
4. Commit 关闭 Issue 的最佳实践及其优点
阮一峰老师提到的通过 commit message 关闭 Issue(例如使用 fix #123)是一种被广泛认可的实践,背后有以下优点:
- 自动关联 Issue 和提交:GitHub、GitLab 等平台支持根据关键字自动关闭对应 Issue,确保 Issue 状态与代码进展同步,减少手动关闭操作
- 提升项目透明度:团队成员和贡献者能快速了解哪个提交解决了哪些问题,提高协作效率。
- 简化发布和回滚流程:通过 Issue 追踪代码变更的上下文,便于后续定位和管理
- CI/CD 流水线集成:自动关闭 Issue 可以触发后续自动化任务,如通知、部署等,优化开发流程。
最佳实践建议:
- 关闭 Issus 是在 PR 的阶段,使用符合平台的标准写法即可触发
- 使用明确的关键字(fix, close, resolve 等)加 Issue 编号
- 每条解决 Bug 或任务的 commit 都要关联对应 Issue
- 保持 commit message 清晰表达解决内容,避免误操作关闭
在github中支持PR模板的用法,创建一个 .github/pull_request_template.md
PR模板示例:
### ✨ What’s Changed
<!--
简要列出本次 PR 中的主要改动点。
推荐使用语义化 commit 风格(feat/fix/refactor/docs/test 等)。
例如:
- feat(login): add email format validation
- fix(auth): handle expired token
- refactor(session): extract common logic
-->
### 🐛 Related Issues
<!--
自动关闭 Issue 的语法:
Fixes #123
Closes #456
如果只是提到,不想自动关闭,用:
Related to #789
-->
Fixes #
### 📋 Additional Context
<!--
补充说明为什么做这些改动,有哪些考虑、上下文信息,是否是链式 PR 的一部分等。
例如:
This PR is the second step of the auth module refactor plan (after #101).
-->
5. 多个 Commit 进行 Squash 时的最佳操作指南
在合并 Pull Request 或整理历史时,通常会用 squash 把多个 commit 合并为一条,例如通过GitHub PR 合并时可直接选择 “Squash and merge” ,其他的平台一般也有类似的选项
这里会涉及到将多条 commit 合并为一条的需求,对于这个需求我没有找到统一的标准,我的个人习惯是使用上一条中的模板格式来进行commit的聚合,即PR内容分为三段表达
- 第一段:简要列出本次 PR 中的主要改动点,依然使用commit 风格(就是之前多次commit的内容汇总)
- 第二段:自动关闭 Issue 的语法
- (可选)第三段:补充说明,上下文信息
- 比如修复 typos、格式调整等小变更,可以合并在主要 commit 中,避免历史冗杂。
如果是在本地进行Squash,可以使用 git rebase -i 进行交互式合并
正确的 squash 习惯让代码库历史更清晰,方便后续维护和回滚
6. (可选)CI/CD 中的 Commit 自动化检查实践(不完全)
CI/CD 涉及到的内容会比较专业,不是短篇幅能说完的,一般在企业中往往会有专门的人进行维护,我对这个部分的内容也不是专业的,这里仅是泛泛而谈,后面等我彻底搞明白并摸索出最佳实践之后再补全
在现代开发流程中,CI/CD 流水线自动检测 commit 信息是否符合规范,是保证项目质量的关键环节。推荐做法:
- 集成 Commitlint 校验:
- 在 CI 环境中运行 commitlint 检查所有提交或 PR 的 commit message
- 配合 Husky 进行本地 pre-commit 钩子,提前拦截不合规范提交。
- 自动生成 CHANGELOG 与版本发布:
- 在流水线中结合 semantic-release 自动判断版本升级类型,生成日志,发布包。
- 通过 CI 流水线保证版本号和日志准确无误。
- 报错反馈机制:
- 当 commit 不合规时,自动中断构建,反馈具体错误,提醒开发者修正,还可以配合bot发送消息
- CI 工具如 GitHub Actions、GitLab CI、Jenkins 都支持此类集成
- 结合代码审核流程:
- 在 PR 审核时,自动检查 commit message,减少人工审核压力
- 支持强制分支保护,禁止非规范 commit 推送到主分支
- 示例流程:
- 开发者本地写 commit,利用 commitizen 和 husky 规范格式
- 提交代码触发 CI
- CI 执行 commitlint 校验。
- 校验失败则反馈,阻止合并
- 校验通过则自动生成版本和日志,完成发布
这种全流程的自动化检查极大提升团队开发效率和代码质量,保障发布流程的可控性和规范性。