|
| 1 | +**原文链接:** [Git Commit Message 应该怎么写?](https://mp.weixin.qq.com/s/EvN_lUyiQnlHR9kJ5SiosA) |
| 2 | + |
| 3 | +最近被同事吐槽了,说我代码提交说明写的太差。其实都不用他吐槽,我自己心里也非常清楚。毕竟很多时候犯懒,都是直接一个 `-m "fix"` 就提交上去了。 |
| 4 | + |
| 5 | +这样做是非常不好的,我也是自食恶果,深受其害。特别是查看历史提交记录时,想通过提交说明来了解当时的功能变更,基本不可能,都得点进去看代码才行。 |
| 6 | + |
| 7 | +所以这两天看了一些**如何写好提交说明**的资料,系统地学习了一下。虽然团队没有这方面的要求,但是想要进步,得对自己提更高的要求才行。 |
| 8 | + |
| 9 | +一般使用 git 提交代码的话,可以使用 `-m` 参数来指定提交说明,比如: |
| 10 | + |
| 11 | +```shell |
| 12 | +$ git commit -m "hello world" |
| 13 | +``` |
| 14 | + |
| 15 | +如果一行不够,可以只执行 `git commit`,这样就会跳出文本编辑器来写多行: |
| 16 | + |
| 17 | +```shell |
| 18 | +$ git commit |
| 19 | +``` |
| 20 | + |
| 21 | +## Commit Message 格式 |
| 22 | + |
| 23 | +Commit Message 包括三个部分:Header,Body 和 Footer。 |
| 24 | + |
| 25 | +```shell |
| 26 | +<Header> |
| 27 | + |
| 28 | +<Body> |
| 29 | + |
| 30 | +<Footer> |
| 31 | +``` |
| 32 | + |
| 33 | +其中,Header 是必需的,Body 和 Footer 可以省略。 |
| 34 | + |
| 35 | +### Header |
| 36 | + |
| 37 | +Header 部分只有一行,包括三个字段:type(必需)、scope(可选)、subject(必需)。 |
| 38 | + |
| 39 | +```shell |
| 40 | +<type>(<scope>): <subject> |
| 41 | +``` |
| 42 | + |
| 43 | +#### type |
| 44 | + |
| 45 | +type 用于说明 commit 的类别,具体的标识如下: |
| 46 | + |
| 47 | +- `feat`:一个新的功能(feature); |
| 48 | +- `fix`:修复 bug; |
| 49 | +- `docs`:修改文档,比如 README.md、CHANGELOG.md 等; |
| 50 | +- `style`:修改代码的格式,不影响代码运行的变动,比如空格、格式化代码、补齐句末分号等等; |
| 51 | +- `refactor`:代码重构,没有新功能的添加以及 bug 修复的代码改动; |
| 52 | +- `perf`:优化代码以提高性能; |
| 53 | +- `test`:增加测试或优化改善现有的测试; |
| 54 | +- `build`:修改影响项目构建文件或外部依赖项,比如 npm、gulp、webpack、broccoli 等; |
| 55 | +- `ci`:修改 CI 配置文件和脚本; |
| 56 | +- `chore`:其他非 src 路径文件和测试文件的修改,比如 .gitignore、.editorconfig 等; |
| 57 | +- `revert`:代码回退; |
| 58 | + |
| 59 | +#### scope |
| 60 | + |
| 61 | +scope 用于说明 commit 的影响范围,比如数据层、控制层、视图层等等,视项目不同而不同。 |
| 62 | + |
| 63 | +如果你的修改影响了不止一个 scope,就可以使用 `*` 代替。 |
| 64 | + |
| 65 | +#### subject |
| 66 | + |
| 67 | +subject 是 commit 目的的简单描述,不超过 50 个字符,结尾不需要句号。 |
| 68 | + |
| 69 | +### Body |
| 70 | + |
| 71 | +Body 部分是对本次 commit 的详细描述,可以分多行。 |
| 72 | + |
| 73 | +Body 部分应该说明代码变动的动机,以及与以前行为的对比。 |
| 74 | + |
| 75 | +```shell |
| 76 | +More detailed explanatory text, if necessary. Wrap it to |
| 77 | +about 72 characters or so. |
| 78 | + |
| 79 | +Further paragraphs come after blank lines. |
| 80 | + |
| 81 | +- Bullet points are okay, too |
| 82 | +- Use a hanging indent |
| 83 | +``` |
| 84 | +
|
| 85 | +### Footer |
| 86 | +
|
| 87 | +Footer 部分主要用于两种情况:不兼容变动和处理 Issue。 |
| 88 | +
|
| 89 | +#### 不兼容变动 |
| 90 | +
|
| 91 | +如果当前代码与上一个版本不兼容,则 Footer 部分以 `BREAKING CHANGE:` 开头,后面就是对变动的描述、以及变动理由和迁移方法。 |
| 92 | +
|
| 93 | +```shell |
| 94 | +BREAKING CHANGE: Previously, $compileProvider.preAssignBindingsEnabled was set to true by default. This means bindings were pre-assigned in component constructors. In Angular 1.5+ the place to put the initialization logic relying on bindings being present is the controller $onInit method. |
| 95 | + |
| 96 | +To migrate follow the example below: |
| 97 | + |
| 98 | +Before: |
| 99 | + |
| 100 | +```js |
| 101 | +angular.module('myApp', []) |
| 102 | + .component('myComponent', { |
| 103 | + bindings: {value: '<'}, |
| 104 | + controller: function() { |
| 105 | + this.doubleValue = this.value * 2; |
| 106 | + } |
| 107 | +}); |
| 108 | +``` |
| 109 | + |
| 110 | +After: |
| 111 | +```js |
| 112 | +angular.module('myApp', []) |
| 113 | + .component('myComponent', { |
| 114 | + bindings: {value: '<'}, |
| 115 | + controller: function() { |
| 116 | + this.$onInit = function() { |
| 117 | + this.doubleValue = this.value * 2; |
| 118 | + }; |
| 119 | + }; |
| 120 | + this.doubleValue = this.value * 2; |
| 121 | + } |
| 122 | +}); |
| 123 | +``` |
| 124 | + |
| 125 | +Don't do this if you're writing a library, though, as you shouldn't change global configuration then. |
| 126 | +``` |
| 127 | +
|
| 128 | +#### 处理 Issue |
| 129 | +
|
| 130 | +处理 Issue 分为两种情况,分别是关联 Issue 和关闭 Issue。 |
| 131 | +
|
| 132 | +比如本次提交如果和某个 issue 有关系: |
| 133 | +
|
| 134 | +```shell |
| 135 | +Issue #1, #2, #3 |
| 136 | +``` |
| 137 | +
|
| 138 | +如果当前提交信息解决了某个 issue: |
| 139 | +
|
| 140 | +```shell |
| 141 | +Close #1, #2, #3 |
| 142 | +``` |
| 143 | +
|
| 144 | +### Revert |
| 145 | +
|
| 146 | +还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以 `revert:` 开头,后面跟着被撤销 commit 的 Header。 |
| 147 | +
|
| 148 | +```shell |
| 149 | +revert: feat(pencil): add 'graphiteWidth' option |
| 150 | +
|
| 151 | +This reverts commit 667ecc1654a317a13331b17617d973392f415f02. |
| 152 | +``` |
| 153 | +
|
| 154 | +Body 部分的格式是固定的,必须写成 `This reverts commit <hash>.`,其中 hash 是被撤销 commit 的 SHA 标识符。 |
| 155 | +
|
| 156 | +如果当前 commit 与被撤销的 commit,在同一个发布(release)里面,那么它们都不会出现在 Change log 里面。如果两者在不同的发布,那么当前 commit,会出现在 Change log 的 Reverts 小标题下面。 |
| 157 | +
|
| 158 | +最后来看一个例子,算是一个总结,至于具体内容还是要根据实际情况来填写。 |
| 159 | +
|
| 160 | +```shell |
| 161 | +feat: 添加了分享功能 |
| 162 | +
|
| 163 | +给每篇博文添加了分享功能 |
| 164 | +
|
| 165 | +- 添加分享到微博功能 |
| 166 | +- 添加分享到微信功能 |
| 167 | +- 添加分享到朋友圈功能 |
| 168 | +
|
| 169 | +Issue #1, #2 |
| 170 | +Close #1 |
| 171 | +``` |
| 172 | +
|
| 173 | +## 插件推荐 |
| 174 | +
|
| 175 | +有了这些规范,也知道怎么写了,但是不是会担心记不住呢?不要怕,有插件可以用,如果使用 VsCode 的话,可以安装一个叫 **Commit Message Editor** 的插件。 |
| 176 | +
|
| 177 | +可以根据提示信息直接写: |
| 178 | +
|
| 179 | + |
| 180 | +
|
| 181 | +也可以使用表单的方式,有选项可以选择: |
| 182 | +
|
| 183 | + |
| 184 | +
|
| 185 | +这样不仅可以很方便地写提交说明了,还可以使提交说明更加的规范。 |
| 186 | +
|
| 187 | +以上就是本文的全部内容,如果觉得还不错的话欢迎**点赞**,**转发**和**关注**,感谢支持。 |
| 188 | +
|
| 189 | +--- |
| 190 | +
|
| 191 | +**参考文章:** |
| 192 | +
|
| 193 | +- https://juejin.cn/post/6960541430473293837 |
| 194 | +- https://mrseawave.github.io/blogs/articles/2021/03/31/git-commit-message/ |
| 195 | +
|
| 196 | +**推荐阅读:** |
| 197 | +
|
| 198 | +- [Git 分支管理策略](https://mp.weixin.qq.com/s/hRd1UNMRutmA6MGmswweBw) |
0 commit comments