前言
Git每次提交代码时,都要写Commit Message(提交说明),通常情况下,Commit Message应该清晰明了,说明本次提交的目的和具体操作等。然而笔者工作多年来发现,有些公司对Commit Message没有明确的要求,这导致每个人都按自己熟悉的方式提交代码。例如,有些人会写此次代码的修改是基于哪个模块,有些人会写解决了哪些Bug,有些则只写修改了哪个文件,中英文混用等等五花八门的Commit格式,这导致后续的代码维护成本很高,有时候提交人看Commit Message都不知道自己改了什么。
没有统一的提交格式要求,对于代码提交管理,追溯,查阅等都造成了很多麻烦。比如查阅某个业务的修改历史,查阅某个时间段修复了哪些Bug,因为Commit没有统一的格式,就比较难快速获取这些信息。如果在团队中大家遵守一种统一的提交规范提交代码,使用Git命令就可以非常方便地获取提交信息。我们希望通过一种约定式的Commit Message,以提高代码提交规范,提高开发效率。
如果您所在的团队没有规范提交,建议您推动这项改善,这将极大的改善团队的开发协同效率。
Commit规范提交参考1
您是否在查阅别人代码时,经常在Commit Message中发现如下关键字,这正是一种规范提交的措施。
feat - 新功能 feature
fix - 修复 bug
docs - 文档注释
style - 代码格式(不影响代码运行的变动)
refactor - 重构、优化(既不增加新功能,也不是修复bug)
perf - 性能优化
test - 增加测试
chore - 构建过程或辅助工具的变动
revert - 回退
build - 打包
约定式提交 (conventionalcommits.org). https://www.conventionalcommits.org/zh-hans/v1.0.0/
概述
约定式提交规范是一种基于提交信息的轻量级约定。 它提供了一组简单规则来创建清晰的提交历史; 这更有利于编写自动化工具。 通过在提交信息中描述功能、修复和破坏性变更。
提交说明的结构如下所示:
原文:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
译文:
<类型>[可选 范围]: <描述>
[可选 正文]
[可选 脚注]
提交说明包含了下面的结构化元素,以向类库使用者表明其意图:
-
fix: 类型为
fix
的提交表示在代码库中修复了一个 bug。 -
feat: 类型为
feat
的提交表示在代码库中新增了一个功能。 -
除fix:和feat:之外,也可以使用其它提交类型,例如基于Angular 约定中推荐的build:、chore:、ci:、docs:、style:、refactor:、perf:、test:,等等。
- build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等;
- chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等;
- ci: 用于修改持续集成流程,例如修改 Travis、Jenkins 等工作流配置;
- docs: 用于修改文档,例如修改 README 文件、API 文档等;
- style: 用于修改代码的样式,例如调整缩进、空格、空行等;
- refactor: 用于重构代码,例如修改代码结构、变量名、函数名等但不修改功能逻辑;
- perf: 用于优化性能,例如提升代码的性能、减少内存占用等;
- test: 用于修改测试用例,例如添加、删除、修改代码的测试用例等。
示例
包含了描述并且脚注中有破坏性变更的提交说明
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
包含了范围和破坏性变更!`的提交說明
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
包含范围的提交说明
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
约定式提交规范
本文中的关键词 “必须(MUST)”、“禁止(MUST NOT)”、“必要(REQUIRED)”、“应当(SHALL)”、“不应当(SHALL NOT)”、“应该(SHOULD)”、“不应该(SHOULD NOT)”、“推荐(RECOMMENDED)”、“可以(MAY)” 和 “可选(OPTIONAL)” ,其相关解释参考 RFC 2119 。
- 每个提交都必须使用类型字段前缀,它由一个名词构成,诸如
feat
或fix
, 其后接可选的范围字段,可选的!
,以及必要的冒号(英文半角)和空格。 - 当一个提交为应用或类库实现了新功能时,必须使用
feat
类型。 - 当一个提交为应用修复了 bug 时,必须使用
fix
类型。 - 范围字段可以跟随在类型字段后面。范围必须是一个描述某部分代码的名词,并用圆括号包围,例如:
fix(parser):
- 描述字段必须直接跟在 <类型>(范围) 前缀的冒号和空格之后。 描述指的是对代码变更的简短总结,例如: fix: array parsing issue when multiple spaces were contained in string 。
- 在简短描述之后,可以编写较长的提交正文,为代码变更提供额外的上下文信息。正文必须起始于描述字段结束的一个空行后。
- 提交的正文内容自由编写,并可以使用空行分隔不同段落。
- 在正文结束的一个空行之后,可以编写一行或多行脚注。每行脚注都必须包含 一个令牌(token),后面紧跟
:<space>
或<space>#
作为分隔符,后面再紧跟令牌的值(受 git trailer convention 启发)。 - 脚注的令牌必须使用
-
作为连字符,比如Acked-by
(这样有助于 区分脚注和多行正文)。有一种例外情况就是BREAKING CHANGE
,它可以被认为是一个令牌。 - 脚注的值可以包含空格和换行,值的解析过程必须直到下一个脚注的令牌/分隔符出现为止。
- 破坏性变更必须在提交信息中标记出来,要么在 <类型>(范围) 前缀中标记,要么作为脚注的一项。
- 包含在脚注中时,破坏性变更必须包含大写的文本
BREAKING CHANGE
,后面紧跟着冒号、空格,然后是描述,例如: BREAKING CHANGE: environment variables now take precedence over config files 。 - 包含在 <类型>(范围) 前缀时,破坏性变更必须通过把
!
直接放在:
前面标记出来。 如果使用了!
,那么脚注中可以不写BREAKING CHANGE:
, 同时提交信息的描述中应该用来描述破坏性变更。 - 在提交说明中,可以使用
feat
和fix
之外的类型,比如:docs: updated ref docs. 。 - 工具的实现必须不区分大小写地解析构成约定式提交的信息单元,只有
BREAKING CHANGE
必须是大写的。 - BREAKING-CHANGE 作为脚注的令牌时必须是 BREAKING CHANGE 的同义词。
为什么使用约定式提交
- 自动化生成 CHANGELOG。
- 基于提交的类型,自动决定语义化的版本变更。
- 向同事、公众与其他利益关系者传达变化的性质。
- 触发构建和部署流程。
- 让人们探索一个更加结构化的提交历史,以便降低对你的项目做出贡献的难度。
Commit规范提交参考2
提交信息格式
Angular提交信息格式. https://github.com/angular/angular/blob/main/CONTRIBUTING.md
我们对于Git提交信息的格式有着非常精确的规则。
这种格式使得提交历史更易于阅读。
每一个提交信息包含一个header, 一个body, 和一个 footer.
<header>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
header要求必须遵守[Commit Message Header](#Commit Message Header)格式
除了docs类型的提交外,body对所有提交都是强制性的。
当正文出现时,它必须至少有20个字符长,并且必须符合[Commit Message Body](#Commit Message Body)格式。
footer 是可选的。[Commit Message Footer](#Commit Message Footer)格式描述了页脚的用途和它必须具有的结构。
Commit Message Header
<type>(<scope>): <short summary>
│ │ │
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
│ │
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
│ elements|forms|http|language-service|localize|platform-browser|
│ platform-browser-dynamic|platform-server|router|service-worker|
│ upgrade|zone.js|packaging|changelog|docs-infra|migrations|
│ devtools
│
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|test
<type>
和<summary>
是强制的, (<scope>)
是可选的
Type
Type必须是下面其中之一:
- build: 影响构建系统或外部依赖的更改(示例范围:gulp、broccoli、npm)
- ci: 更改我们的CI配置文件和脚本(示例:CircleCi, SauceLabs)
- docs: 仅文档的更新
- feat: 一个新增特性
- fix: 一个Bug的修复
- perf: 代码更改和性能改善
- refactor: 既不修复错误也不增加功能的代码更改
- test: 添加缺失的测试或更正现有的测试
Scope
作用域应该是受影响的npm包的名称(由读取提交消息生成的变更日志的人感知到)。
支持下面的scope:
animations
bazel
benchpress
common
compiler
compiler-cli
core
elements
forms
http
language-service
localize
platform-browser
platform-browser-dynamic
platform-server
router
service-worker
upgrade
zone.js
目前“使用包名”规则有几个例外:
-
packaging
: 用于改变我们所有包中的NPM包布局的更改,例如公共路径更改,package。对所有包的Json更改,d.s文件/格式更改,对bundle的更改等。 -
changelog
: 用于更新CHANGELOG.md中的发行说明 -
dev-infra
: 用于目录/脚本和/tools中与dev-infra相关的更改 -
docs-infra
: 用于在repo的/aio目录下对docs-app (angular.io)进行相关修改 -
migrations
: 用于更改’ ng update '迁移。 -
devtools
: 用于更改浏览器扩展 -
none/empty string: 对于跨所有包进行的“测试”和“重构”更改非常有用(例如:’ test:添加缺失的单元测试’)以及与特定包无关的文档更改(例如:’ docs:修复教程中的拼写错误’)。
小结
参考提交如下
使用summary字段提供对更改的简洁描述:
- 使用祈使句现在时:“change"而不是"changed"也不是"changes”
- 第一个字母不要大写
- 末尾没有点(.)
Commit Message Body
就像在总结中一样,使用祈使句的现在时:“fix"而不是"fixed"也不是"fixes”。
解释提交消息主体中更改的动机。这个提交消息应该解释为什么要进行更改。
您可以将以前的行为与新行为进行比较,以说明更改的影响。
Commit Message Footer
页脚可以包含有关突破性更改和弃用的信息,也是引用GitHub问题,Jira票据和其他pr的地方,此提交关闭或相关。
例如:
BREAKING CHANGE: <breaking change summary>
<BLANK LINE>
<breaking change description + migration instructions>
<BLANK LINE>
<BLANK LINE>
Fixes #<issue number>
或者
DEPRECATED: <what is deprecated>
<BLANK LINE>
<deprecation description + recommended update path>
<BLANK LINE>
<BLANK LINE>
Closes #<pr number>
中断更改部分应该以短语“BREAKING CHANGE:”开始,然后是中断更改的摘要、空白行和中断更改的详细描述,其中还包括迁移说明。
类似地,Deprecation部分应该以“DEPRECATED:”开头,然后是不推荐的内容的简短描述、空白行和不推荐的详细描述(还提到推荐的更新路径)。
撤销提交
如果提交撤销了之前的提交,它应该以revert:
开头,后跟被撤销提交的标题。
提交信息正文的内容应包含:
- 被撤销提交的SHA信息,格式如下:
This reverts commit <SHA>
, - 清晰地描述撤销提交信息的原因。
总结
每个公司都可以根据自己的实际情况约定一些提交规范。尤其是在一些大型项目中,约定Commit Message 是非常重要的,这将极大地改善团队协作的效率,减少一些不必要的沟通。
看似微不足道的改善,隐含着巨大的效益