Conventional Commits
Conventional Commits 1.0.0 规范
概述
Conventional Commits 规范是一种轻量级的提交信息约定。它提供了一套简单的规则,用于创建明确的提交历史,从而更容易在此基础上编写自动化工具。该规范与 SemVer(语义化版本)相辅相成,通过在提交信息中描述特性、修复和重大变更,明确版本变更的类型。
提交信息的结构应如下所示:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
提交信息包含以下结构元素,以便向库的使用者传达意图:
fix
: 修补代码库中的 bug(对应于语义化版本中的 PATCH)。feat
: 引入新功能到代码库(对应于语义化版本中的 MINOR)。BREAKING CHANGE
: 包含 BREAKING CHANGE 脚注,或在 type/scope 后加上!
,表示引入了重大 API 变更(对应于语义化版本中的 MAJOR)。BREAKING CHANGE 可以是任何类型的提交的一部分。- 除
fix
和feat
之外,还允许其他类型,例如:build
,chore
,ci
,docs
,style
,refactor
,perf
,test
等,这些类型在 @commitlint/config-conventional(基于 Angular 规范)中有所推荐。 - 其他类型的脚注(如
BREAKING CHANGE: <description>
)也可以使用,类似于 git trailer 格式。
Conventional Commits 规范并不强制要求额外的类型,除非它们包含 BREAKING CHANGE。可以为提交类型提供一个 scope,以提供额外的上下文信息,scope 用括号括起来,例如:feat(parser): add ability to parse arrays
。
示例
-
含有描述和 BREAKING CHANGE 脚注的提交信息:
feat: allow provided config object to extend other configs BREAKING CHANGE: `extends` key in config file is now used for extending other config files
-
使用
!
以强调重大变更的提交信息:feat!: send an email to the customer when a product is shipped
-
含有 scope 和
!
以强调重大变更的提交信息:feat(api)!: send an email to the customer when a product is shipped
-
含有
!
和 BREAKING CHANGE 脚注的提交信息:chore!: drop support for Node 6 BREAKING CHANGE: use JavaScript features not available in Node 6.
-
不带正文的提交信息:
docs: correct spelling of CHANGELOG
-
带有 scope 的提交信息:
feat(lang): add Polish language
-
带有多段正文和多个脚注的提交信息:
fix: prevent racing of requests Introduce a request id and a reference to latest request. Dismiss incoming responses other than from latest request. Remove timeouts which were used to mitigate the racing issue but are obsolete now. Reviewed-by: Z Refs: #123
规范
文档中的关键词“必须”、“不能”、“需要”、“应当”、“不应当”、“建议”、“可以”、“可选”等应按 RFC 2119 中的描述进行解释。
- 提交信息必须以类型开头,该类型由名词组成,例如
feat
,fix
等,后面可以跟一个可选的 scope、可选的!
,以及必需的冒号和空格。 - 当提交添加新功能到应用程序或库时,必须使用
feat
类型。 - 当提交修复应用程序的 bug 时,必须使用
fix
类型。 - 类型后可以提供一个 scope。scope 必须是描述代码库某部分的名词,用括号括起来,例如:
fix(parser):
。 - 类型/scope 前缀后的冒号和空格后面必须紧跟一个描述。描述是代码更改的简短摘要,例如:
fix: array parsing issue when multiple spaces were contained in string
。 - 可以在简短描述后提供更长的提交正文,以提供关于代码更改的附加上下文信息。正文必须在描述后空一行开始。
- 提交正文是自由形式的,可以包含任意数量的换行分隔段落。
- 可以在正文后空一行提供一个或多个脚注。每个脚注必须包含一个单词标记,后面跟一个
:<space>
或<space>#
分隔符,接着是一个字符串值(这受 git trailer 约定的启发)。 - 脚注的标记必须用
-
代替空白字符,例如Acked-by
(这有助于区分脚注部分和多段正文)。BREAKING CHANGE 是一个例外,它也可以用作标记。 - 脚注的值可以包含空格和换行符,并且解析必须在下一个有效的脚注标记/分隔符对出现时终止。
- 重大变更必须在提交的类型/scope 前缀中指明,或作为脚注条目。
- 如果作为脚注包含,重大变更必须包含大写的
BREAKING CHANGE
,后跟冒号、空格和描述,例如:BREAKING CHANGE: environment variables now take precedence over config files
。 - 如果在类型/scope 前缀中包含,重大变更必须通过在冒号前立即加上
!
指示。如果使用!
,则可以在脚注部分省略BREAKING CHANGE:
,并且提交描述应用于描述重大变更。 - 提交消息中可以使用
feat
和fix
以外的类型,例如:docs: update ref docs
。 - 组成 Conventional Commits 的信息单元对于实现者来说不区分大小写,
BREAKING CHANGE
除外,后者必须大写。 - 当用作脚注标记时,
BREAKING-CHANGE
必须与BREAKING CHANGE
同义。
为什么使用 Conventional Commits
- 自动生成变更日志。
- 自动确定语义版本号(基于已提交的提交类型)。
- 向团队成员、公众和其他利益相关者传达变更的性质。
- 触发构建和发布流程。
- 让人们更容易地为你的项目做出贡献,通过允许他们探索更有结构化的提交历史。
常见问题
在初始开发阶段,我该如何处理提交信息?
我们建议你按已经发布产品的方式进行。通常有人,即使是你的同事软件开发人员,也在使用你的软件。他们会想知道修复了什么,破坏了什么等等。
提交标题中的类型是大写还是小写?
可以使用任何大小写,但最好保持一致。
如果提交符合多种提交类型怎么办?
尽可能返回并进行多次提交。Conventional Commits 的一部分好处在于它能够驱使我们进行更有组织的提交和 PR。
这是否会阻碍快速开发和快速迭代?
它阻碍了以无序方式快速行动。它有助于你在长期内跨多个项目和多样化的贡献者中快速移动。
Conventional Commits 会不会导致开发人员限制他们进行的提交类型,因为他们会考虑所提供的类型?
Conventional Commits 鼓励我们进行更多的某些类型的提交,如修复。除此之外,Conventional Commits 的灵活性允许你的团队自行设定提交类型,并随时间改变这些类型。
这与 SemVer 有何关系?
fix
类型提交应转换为 PATCH 版本。feat
类型提交应转换为 MINOR 版本。包含 BREAKING CHANGE 的提交,无论类型如何,应转换为 MAJOR 版本。
我该如何为 Conventional Commits 规范的扩展(例如 @jameswomack/conventional-commit-spec)设定版本?
我们建议使用 SemVer 来发布你自己的扩展规范(并鼓励你进行这些扩展!)。
如果我不小心使用了错误的提交类型怎么办?
- 当你使用了规范内但不正确的类型,例如
fix
而非feat
:
在合并或发布错误之前,我们建议使用git rebase -i
编辑提交历史。发布后,根据你使用的工具和流程,清理方式会有所不同。 - 当你使用了规范外的类型,例如
feet
而非feat
:
在最坏的情况下,如果提交没有符合 Conventional Commits 规范,这不是世界末日。只是意味着基于规范的工具将忽略该提交。
我的所有贡献者都需要使用 Conventional Commits 规范吗?
不需要!如果你使用基于 squash 的工作流,Git 主要维护者可以在合并时清理提交信息——这样不会增加普通提交者的工作量。一种常见的工作流程是让你的 git 系统自动 squash pull request 的提交,并为主要维护者提供一个表单来输入正确的 git 提交信息以进行合并。
**Conventional Commits 如何处理回
滚提交?**
回滚代码可能很复杂:你是要回滚多个提交吗?如果回滚一个特性,下一个发布版本应该是补丁吗?
Conventional Commits 没有明确规定回滚行为。相反,我们将灵活的类型和脚注留给工具作者,以开发他们的回滚处理逻辑。
一种推荐的方法是使用 revert
类型,并在脚注中引用被回滚的提交 SHA:
revert: let us never again speak of the noodle incident
Refs: 676104e, a215868
git commit -m "feat: 新增用户注册功能"
git commit -m "fix: 修复用户注册时的表单验证错误"
git commit -m "docs: 更新 API 使用文档"
git commit -m "style: 统一代码格式,增加缺少的分号"
git commit -m "refactor: 重构用户服务逻辑,提升代码可读性"
git commit -m "perf: 优化用户查询接口的响应速度"
git commit -m "test: 增加用户注册功能的单元测试"
git commit -m "chore: 更新项目依赖到最新版本"
git commit -m "build: 修改 webpack 配置以支持最新的 babel"
git commit -m "ci: 修改 CI 配置文件以使用新的环境变量"
git commit -m "revert: 回滚到提交 abc123"
git commit -m "config: 更新项目配置文件以适应新环境"