每次都在用Git作Commit提交,但如何编写Commit Message这个细节点,却很容易被忽视。
通常,我们的Commit Message应该简洁明了,说明清楚本次提交的目的即可,除此外,团队中最好可以遵循一定的提交Commit规范,整体项目的标准和维护性更高。
1. Commit日志格式规范作用
- 在浏览历史记录时提供更好的信息,方便快速浏览项目变更记录:
git log <last tag> HEAD --pretty=format:%s
- 可以快速pick出特性、Fix或功能内容:
$ git log <last release> HEAD --grep feature
- 允许通过脚本生成
CHANGELOG.md
- 允许忽略git bisect的提交(不重要的提交,例如格式化)
2. 格式规范
1
2
3
4
5
6
7
8
9
10
11
12
13
| Header: <type>(<scope>): <subject>
- type: 代表 commit 的类别:feat, fix, docs, style, refactor, test, chore,必要栏位。
- scope 代表 commit 影响的范围,例如资料库、控制层、模板层等等,视专案不同而不同,为可选栏位。
- subject 代表此 commit 的简短描述,不要超过 50 个字元,结尾不要加句号,为必要栏位。
Body: 72-character wrapped. This should answer:
* Body 部份是对本次 Commit 的详细描述,可以分成多行,每一行不要超过 72 个字元。
* 说明程式码变动的项目与原因,还有与先前行为的对比。
Footer:
- 填写任务编号(如果有的话).
- BREAKING CHANGE(可忽略),记录不兼容的变动,
以 BREAKING CHANGE: 开头,后面是对变动的描述、以及变动原因和迁移方法。
|
2.1. type,用于说明commit类型
- feat: 新增/修改功能 (feature)。
- fix: 修改bug (bug fix)。
- docs: 文件 (documentation)。
- style: 代码格式调整(不影响程序运行 white-space, formatting, missing semi colons, etc)。
- refactor: 重构代码 。
- perf: 改善性能 (A code change that improves performance)。
- test: 增加测试 (when adding missing tests)。
- chore: 辅助工具、构建工具的变动 (maintain)。
- revert: 撤回先前的commit,例如:revert: type(scope): subject (回覆版本:xxxx)。
Tips: Type定义类型是让Code Review
的人,以何种心态面对Commit的内容,可以提升CR效率,比如:
type=fix
,则应该以Commit是如何解决问题视角CRtype=refactor
,重构代码,CR人员应该注意代码是如何重构的feat
、fix
的commit会在Change Log
中出现,其余的类型,可以选择是否放入Change Log
中
2.2. scope,用于说明commit影响范围
可以从架构层面,比如数据层、控制层、视图层,依据项目不同而异,应该提前统一规划好;
比如feat($browser)
、feat($compiler)
,不同的团队、项目会有一定的规范,提前约定好!
2.3. subject,提交内容的简要描述,不超过50个字符
- 以动词开头,使用第一人称现在时,比如change、非changed或changes
- 小写字母开头
- 结尾不加.
- 不超过50个字符
2.4. body,对本次Commit的详述,可以分成多行
- 使用第一人称现在时,比如使用change,而非changed或changes
- 说明代码改动的动机,以及与之前的差异
1
2
3
4
5
6
7
| 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
|
- 不兼容改动,使用
BREAKING CHANGE
开头,描述变动信息 - ISSUE关闭,比如
close #234
,close #1,#3
3. 校验工具
3.1. Commitizen - 撰写合格Commit Message的工具
通过npm安装
1
2
3
4
5
6
7
| // 安装
npm install -g commitizen
// 项目下运行下面命令,使其支持Angular的Commit Message格式
commitizen init cz-conventional-changelog --save --save-exact
// 通过git cz替换git commit,编写合格Commit Message
|
3.2. Validate-commit-msg
通过设置git的Hook,可以做到在提交时候,检测Commit Message是否合格
4. Change Log生成
4.1. conventional-changelog-cli 生成Change Log的工具
1
2
| // 安装
npm install -g conventional-changelog-cli
|
5. AngularJS团队的样例
5.1. Case1 - feat示例
1
2
3
4
5
6
7
8
| feat($browser): onUrlChange event (popstate/hashchange/polling)
Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available
Breaks $browser.onHashChange, which was removed (use onUrlChange instead)
|
5.2. Case2 - fix示例
1
2
3
4
5
6
7
8
| fix($compile): couple of unit tests for IE9
Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.
Closes #392
Breaks foo.bar api, foo.baz should be used instead
|
5.3. Case3 - feat示例
1
2
3
4
5
6
| feat(directive): ng:disabled, ng:checked, ng:multiple, ng:readonly, ng:selected
New directives for proper binding these attributes in older browsers (IE).
Added coresponding description, live examples and e2e tests.
Closes #351
|
5.4. Case4 - docs示例
1
2
3
4
5
6
7
| docs(guide): updated fixed docs from Google Docs
Couple of typos fixed:
- indentation
- batchLogbatchLog -> batchLog
- start periodic checking
- missing brace
|
5.5. Case5 - feat示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| feat($compile): simplify isolate scope bindings
Changed the isolate scope binding options to:
- @attr - attribute binding (including interpolation)
- =model - by-directional model binding
- &expr - expression execution binding
This change simplifies the terminology as well as
number of choices available to the developer. It
also supports local name aliasing from the parent.
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.
To migrate the code follow the example below:
Before:
scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}
After:
scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor
}
The removed `inject` wasn't generaly useful for directives so there should be no code using it.
|
6. 参考
- https://wadehuanglearning.blogspot.com/2019/05/commit-commit-commit-why-what-commit.html
- https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.4a9jrkze4u4a