由于近半年来接触到的项目中Git Commit都没有做限制,不规范的Git Commit提交使得现有项目的Git Log杂乱无章。长此以往,当我们需要项目复盘、code review或者日常查询以往功能的时候分不清哪些是新功能、哪些是修复bug等等。
例如,我们在2021年开发了一个功能,后来由于项目不再需要此功能从代码中删除了。在2022年的时候其他需求中也用到了这个功能,这时候如果我们没有一个合理的git commit提交规范,以目前的git commit描述是很难找到这个功能的代码的。尤其是在多人协作的团队项目中,这种弊端更为明显。
因此规范团队的提交是非常有必要的,所以git commit规范约束就特别需要了。
以下为一个无commit message规范的git提交记录,可以看到commit message没有规范约束,可随意录入任何内容,无论它与提交内容是否一致。
所以我们今天要说的就是为commit message提供一个约束,使我们的提交信息更为规范,能够一目了然的知道我们这次提交是什么内容。
下面这张图是经过git commit规范约束后的commit message:
我们可以看到此条message的大致格式为:
,下面将会详细介绍git commit规范的格式和检测工具的具体配置方式。
Commit Message格式
要想规范git commit 提交,我们先要了解一下Commit Message格式,目前规范使用较多的是 Angular 团队的规范, 这是目前使用最广的写法,比较合理和系统化。继而衍生了 Conventional Commits specification. 很多工具也是基于此规范, 它的 message 格式如下:
():
Commit message 都包括三个部分:Header,Body 和 Footer,其中,Header 是必需的,Body 和 Footer 可以省略。不管是哪一个部分,任何一行都不得超过100个字符。这是为了避免自动换行影响美观。
由于Body和Footer不是必需的,我们日常用到的也比较少,这里不再多做阐述,我们重点介绍一下Header部分。
Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。注意冒号后面有空格
- type(必填)
type用于说明 commit 的类别。
* feat:新增功能
* fix:bug 修复
* docs:文档更新
* style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑)
* refactor:重构代码(既没有新增功能,也没有修复 bug)
* perf:性能, 体验优化
* test:新增测试用例或是更新现有测试
* build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
* ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
* chore:不属于以上类型的其他类型,比如构建流程, 依赖管理
* revert:回滚某个更早之前的提交
scope(可选)
scope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。subject(必填)
subject是 commit 目的的简短描述。
- 以动词开头,使用第一人称现在时,比如change,而不是changed或changes;
- 第一个字母小写;
- 结尾不加句号(.)
使用commitlint工具来检验commit格式是否符合规范
上面我们已经了解了Commit Message的格式是什么样的了,如果让我们自己手动敲出那些格式也不是不可能,但是我们都知道人工输入难免会有失误的时候,我们借助commitlint工具进行commit格式是否符合规范。
- 安装commitlint cli
npm install --save-dev @commitlint/config-conventional @commitlint/cli
- 配置commitlint使用传统的config配置文件
可以在项目根目录使用命令行生成(如下所示),也可以直接在根目录手动创建commitlint.config.js文件
echo module.exports = {extends: ['@commitlint/config-conventional']} > commitlint.config.js
自动生成的配置文件采用commitlint默认的配置,如下所示:
module.exports = { extends: ['@commitlint/config-conventional'] };
当然,你也可以配置rules,自定义规则:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'revert']
],
'subject-full-stop': [0, 'never'],
'subject-case': [0, 'never'],
'header-max-length': [0, 'always', 72]
}
};
rule配置说明:rule由name和配置数组组成,如:name:[0, 'always', 72]
。
- 数组中第一位为level,可选0、1、2。0为禁用,1为警告,2为错误;
- 第二位为应用与否,可选always|never;
- 第三位该rule的值。
Git Hooks
commitlint本身只是一个检测工具,想要让它真正发挥作用,需要与git hooks相结合。而husky 是一个 Git Hook 工具,一个为 git 客户端增加 hook 的工具,husky继承了Git下所有的钩子,在触发钩子的时候,husky可以阻止不合法的commit,push等等。这里我分需要分成三个部分来讲解:
Husky5.0版本以下,以4.3.8为例
- husky安装
npm install husky --save-dev
- 把commitline配置到githook钩子中,如果package.json文件中已经配置了husky,直接追加上去即可,如果没有配置,则添加以下代码
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
这段配置告诉了git hooks,当我们在当前项目中执行 git commit -m '测试提交'
时将触发commit-msg事件钩子并通知husky,从而执行commitlint -E HUSKY_GIT_PARAMS
命令,也就是我们刚开始安装的 ./node_modules/.bin/ commitlint,它将读取commitlint.config.js配置规则并对我们刚刚提交的“测试提交”这串文字进行校验,若校验不通过,则在终端输出错误,commit终止。
使用commit-msg给出了我们想要的东西:只要创建新的提交就会执行它。传递husky的 HUSKY_GIT_PARAMS 给 commitlint 通过 -E|--env 标记它引导到相关的编辑文件。-E默认为 .git/COMMIT_EDITMSG 。
从上面三张图片中可以看到,当手动提交git commit -m “aaa”
和git commit -m “abc: aaaaa”
时,由于不符合规则,就会报错,不通过了。只有把必填的都写上,符合规则才可以通过。
Husky5.0版本以上,以7.0.4为例
我们有时候会发现,按照以上步骤配置完成后 git commit的时候还是没有效果,没有去执行husky配置的钩子。因为Husky升级到5.0版本以上后,在配置上与4.x版本有所差别,按上面的配置只适用于4.x,这里简要概况一下。
- 依然需要先安装husky,由于现在husky版本已经7.x了,如果不指定版本,默认安装的是最新版本,这里我们使用官方推荐的自动安装的的方式,你也可以选择使用传统方式分步安装,具体步骤在这里:husky传统安装步骤
npx husky-init && npm install
安装后观察package.json文件,如果版本高于5.0,那么就用这个单元里的方案
"husky": "^7.0.4",
并且项目根目录下会多一个.husky文件夹,里面会有个pre-commit文件,这个文件就是在commit之前会执行的一个Hook(这里可以打开pre-commit文件看一下,如果默认里面是npm test,把他删除掉,不然后面会报错)
- 配置commit-msg钩子
执行以下命令,在生成的commit-msg文件中手动键入npx --no-install commitlint --edit "$1"
(这里已经试过,按照官方提供的方式直接执行npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
命令无法生成commit-msg文件)
npx husky add .husky/commit-msg
完成以上两个步骤以后,就可以去git commit测试一下是否已经配置完成。当然,我们也可以去pre-commit文件下配置一下代码过滤工具。
vue-cli创建的项目中的gitHooks
在使用 vue create xxx 创建项目的时候,Vue 会自动帮我们做好一些预配置,其中就有一个叫做yorkie的包,这个包是尤大 fork 自husky 的,它俩功能是一样的,都是生成一些 git hooks 文件,读取项目中 package.json 的相关配置项去执行一些命令,区别是尤大做了一些逻辑和配置上的改动。
yorkie的流程解析就不在这里细说,感兴趣的可以自行去网上查询资料,总之,在使用vue-cli创建的项目中可以不安装husky,直接配置gitHooks,当然你也可以使用husky的方式,这没有任何问题,一切根据个人习惯而定。
下面讲一下在vue项目中配置gitHooks的另一种方式:在vue-cli创建的环境中使用gitHooks是非常简单的,只需要commitlint cli安装安成后,在package.json文件中直接通过字段直接添加git钩子即可。
"gitHooks": {
"commit-msg": "commitlint -E GIT_PARAMS"
},
这里我们拓展一下知识点,我们知道commit-msg是一个git钩子,当然除了commit-msg,git还有很多的其他的钩子,现在我们就来听过pre-commit这个钩子来配置一下代码过滤工具,以防止不小心把错误的代码提交到git上。
- 安装lint-staged,这里用到的lint-staged版本为10.2.11,建议不要随意改动版本
npm install lint-staged --save-dev
- 在package.json中定义gitHooks
"gitHooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E GIT_PARAMS"
},
- 配置前端文件过滤工具lint-staged,这里用了vue-cli-service,当然你也可以选择用eslint等代码检测工具。
"lint-staged": {
"*.{js,vue}": [
"vue-cli-service lint",
"git add"
]
},