# Git 提交规范
# 约定式提交规范
提交规范格式如下:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
-------- 翻译 -------------
<类型>[可选 范围]: <描述>
[可选 正文]
[可选 脚注]
类型:feat、bug... 更改的代码形式
范围:用 lerna 做项目管理时,比如修改的时项目A,feat(proA): xx;又或者标注修改的哪个文件,feat(Home.vue):xxx
描述:修改的功能信息描述
# commitizen
上述只是一个提交规范的格式约束,需要人为自觉的手动执行,显然是很痛苦的。于是,就出现了 git 提交规范化工具 ——— commitizen就是其中之一。
commitizen
仓库名为 cz-cli (opens new window),它提供了 git cz
的指令用于代替 git commit
,也就是说:使用 commitizen 进行代码提交(git commit)时,commitizen 会校验提交时所有必须的提交字段。
TIP
全局安装:npm install -g commitizen
当前版本:4.2.4
commitizen 需要全局安装,个人理解它是一个 git 的插件,因为它相当于为 git commit
提供了一个替代方案:git cz
项目依赖安装:yarn add cz-customizable -D
当前版本:6.3.0
在 package.json
中配置 commitizen
,配置信息如下:
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
}
接着在项目的根目录下创建自定义提示文件:.cz-config.js
。
module.exports = {
// 可选类型
types: [
{ value: "feat", name: "feat: 新功能" },
{ value: "fix", name: "fix: 修复" },
{ value: "docs", name: "docs: 文档变更" },
{ value: "style", name: "style: 代码格式(不影响代码运行的变动)" },
{
value: "refactor",
name: "refactor: 重构(既不是增加feature,也不是修复bug)",
},
{ value: "perf", name: "perf: 性能优化" },
{ value: "test", name: "test: 增加测试" },
{ value: "chore", name: "chore: 构建过程或辅助工具的变动" },
{ value: "revert", name: "revert: 回退" },
{ value: "build", name: "build: 打包" },
],
// 消息步骤
messages: {
type: "请选择提交类型:",
customScope: "请输入修改范围(可选):",
subject: "请简要描述提交(必填):",
body: "请输入详细描述(可选):",
footer: "请输入要关闭的issue(可选):",
confirmCommit: "确认使用以上信息提交?(y/n/e/h)",
},
// 跳过问题
skipQuestions: ["body", "footer"],
// subject文字长度默认是72
subjectLimit: 72,
};
经过上述配置之后,通过执行 git cz
来代替执行 git commit
这一步时:
- 会先触发
commitizen
的提交规范 - 通过
commitizen
就找到了package.json
中的 config 配置,进而找到cz-customizable
这个可以自定义提交配置信息的第三方依赖中 cz-customizable
就会找到为其定义的配置文件.cz-config.js
,进而触发 commit 信息选择
就能看到如下的提示内容了:
当前项目的 package.json
信息:
{
"name": "vue3-solution",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"prepare": "husky install"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.15",
"@vue/cli-plugin-eslint": "~4.5.15",
"@vue/cli-plugin-router": "~4.5.15",
"@vue/cli-plugin-vuex": "~4.5.15",
"@vue/cli-service": "~4.5.15",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^7.0.0",
"lint-staged": "^9.5.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
},
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": ["vue-cli-service lint", "git add"]
}
}
commitizen 的处理方式有一个不稳妥的地方是,如果有人不知道或忘记执行 git cz
,照样执行 git commit
时是无法规范化提交信息了。所以,需要一种更为强制的方式,针对 git commit
进行规范化处理,就是 Git Hooks
。
# Git Hooks
git 在执行某个事件之前或者之后进行的一些其他额外的操作。
详情链接Git Hooks (opens new window),部分 git hooks
如下:
Git Hook | 调用时机 | 说明 |
---|---|---|
pre-applypatch | git am 执行前 | |
applypatch-msg | git am 执行前 | |
post-applypatch | git am 执行后 | 不影响 git am 的结果 |
pre-commit | git commit 执行前 | 可以用 git commit --no-verify 绕过 |
commit-msg | git commit 执行前 | 可以用 git commit --no-verify 绕过 |
post-commit | git commit 执行后 | 不影响 git commit 的结果 |
pre-merge-commit | git merge 执行前 | 可以用 git merge --no-verify 绕过 |
prepare-commit-msg | git commit 执行后,编辑器打开之前 | |
pre-rebase | git rebase 执行前 | |
post-checkout | git checkout 或git switch 执行后 | 如果不使用--no-checkout 参数,则在 git clone 后也会执行 |
post-merge | git commit 执行后 | 在执行git pull 时也会被调用 |
pre-push | git push 执行前 | |
pre-receive | git-receive-pack 执行前 | |
update |
TIP
本次要用的,就是 pre-commit
和 commit-msg
pre-commit
git commit
执行之前- 不接受任何参数,并且在获取提交日志消息并进行提交之前被调用
git commit
如果以非零 的状态退出会导致命令在创建提交之前中止
commit-msg
-git commit
执行前 - 可用于将消息规范化为某种项目标准格式 - 可用于检查消息文件后拒绝提交
# husky 与 commitlint
- commitlint 用于检查提交信息,详情 (opens new window)
- husky 即为
git hooks
的工具,它可以指定在众多钩子中的哪一个回调使用commitlint
来校验提交信息
TIP
注意,以下安装后如果执行有问题,请检查 npm 版本是否大于 7.0
# 安装 commitlint
# @commitlint/config-conventional 17.0.0
# @commitlint/cli 17.0.1
# Install commitlint cli and conventional config
npm install --save-dev @commitlint/{config-conventional,cli}
# For Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli
# commitlint.config.js 配置
commitlint.config.js
就是配置 commit
信息规范的文件,在 commitlint.config.js
中增加配置项,首先要继承 config-conventional
。
关于config-conventional
的默认配置可以查看这里 (opens new window)
注意,保存格式必须是 UTF-8 类型
module.exports = {
// 继承的规则
extends: ["@commitlint/config-conventional"],
// 定义规则类型
rules: {
// type 类型定义,表示 git 提交的 type 必须在以下类型范围内
"type-enum": [
// 当前验证的级别,2 表示错误级别
2,
// 在任何情况下,都进行验证
"always",
// type 的泛型类型
[
"feat", // 新功能 feature
"fix", // 修复 bug
"docs", // 文档注释
"style", // 代码格式(不影响代码运行的变动)
"refactor", // 重构(既不增加新功能,也不是修复bug)
"perf", // 性能优化
"test", // 增加测试
"chore", // 构建过程或辅助工具的变动
"revert", // 回退
"build", // 打包
],
],
// subject 大小写不做校验
"subject-case": [0],
},
};
# 安装 husky
# 当前版本 8.0.1
npm install husky --save-dev
# 配置
执行
npx husky install
指令启动hooks
会在根目录下生成.husky
文件夹,包含.gitignore
和husky.sh
文件commitlint
配合husky
的使用。
通过 husky
来监听 git hooks
,在 git hooks
中的 commit-msg
钩子里面执行 commitlint
对代码的提交信息进行校验。 执行命令:
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
# 或者 yarn
yarn husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
注意,这一步要执行指令,我手动创建文件并复制粘贴的命令,最终没有生效。
此时,.husky
文件夹下会多出一个 commit-msg
文件。至此,不符合标准的提交格式都无法提交了。
.husky
文件夹目录如下:
.
├── _
│ └── husky.sh
│ └── .gitignore
├── commit-msg
commit-msg
的内容如下:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit "$1"
然后执行 git commit -m "提交信息",如果不符合规范就会提醒报错
# package.json
该 package.json
中不包含上述的 commitizen
的配置模块。两者是不关联的
{
"name": "vue3-backstage",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@commitlint/cli": "^17.0.1",
"@commitlint/config-conventional": "^17.0.0",
"@vue/cli-plugin-babel": "~4.5.15",
"@vue/cli-plugin-eslint": "~4.5.15",
"@vue/cli-plugin-router": "~4.5.15",
"@vue/cli-plugin-vuex": "~4.5.15",
"@vue/cli-service": "~4.5.15",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"cz-customizable": "^6.3.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^7.0.0",
"husky": "^8.0.1",
"lint-staged": "^9.5.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
},
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": ["vue-cli-service lint", "git add"]
}
}
# husky 配合 Eslint
之前的 ESLint
和 Prettier
配合解决代码的问题,只能解决本地的代码。
之前的 Husky
配合 Commitlint
只能解决提交的信息的不合规范的问题。
如果有一个懒人,没有配置 ESLint
和 Prettier
,并且按合规的方式提交了格式不对的代码,就坑爹了。
所以,提交代码时,除了要对提交信息进行校验,还要对当前的代码格式进行一层校验,根据配置的规则可以自动将不符合规则的代码进行修复,至少是部分修复。
于是乎,我们通过 husky
来检测 pre-commit
钩子,在执行该钩子的时候,执行yarn husky --ext .js,.vue src
指令来进行代码检测。
执行
yarn husky add .husky/pre-commit "yarn eslint --ext .js,.vue src"
添加 commit 时的 hook。(yarn eslint --ext .js,.vue src
会在执行到该 hook 时运行)- 执行 eslint
- 针对
.js
,.vue
文件 - 在
src
文件夹下
.husky
文件夹下会生成pre-commit
文件。文件目录如下:
.
├── _
│ └── husky.sh
│ └── .gitignore
├── commit-msg
└── pre-commit
pre-commit
的内容如下:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn eslint --ext .js,.vue src
这种情况下,当关闭了 VSCode 或者别的编辑器的 Format On Save 功能时。
如果代码有了问题,执行 git commit 时就会报错。这行此时的校验时,commit-msg
校验还未执行。如下图:
# lint-staged 自动修复错误
经过上面 pre-commit
的校验拦截,如果代码中格式等问题触发 eslint 校验规则过多时,一一手动修复肯定很麻烦。所以,我们需要针对本次提交的内容有问题的地方,进行自动问题修复。
lint-stage
可以只检查本次修改更新的代码,并在出现错误的时候,自动的修复并且推送
在通过 vue-cli
创建项目时,lint-stage
已经被自动安装了, 当前版本是 9.5.0 并在 package.json
中进行了配置。
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
]
}
将该配置修改成下述形式:
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}
同时修改 pre-commit
的内容为执行 lint-staged
命令:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged
此时再次执行 git commit
提交带有错误格式的内容时,eslint 会尝试进行内容的修复,如果修复好代码则会进行提交。如果自动修复失败了,提示错误由人为修复,修复成功后才能提交代码。
# 最后的 package.json
{
"name": "vue3-backstage",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@commitlint/cli": "^17.0.1",
"@commitlint/config-conventional": "^17.0.0",
"@vue/cli-plugin-babel": "~4.5.15",
"@vue/cli-plugin-eslint": "~4.5.15",
"@vue/cli-plugin-router": "~4.5.15",
"@vue/cli-plugin-vuex": "~4.5.15",
"@vue/cli-service": "~4.5.15",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"cz-customizable": "^6.3.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^7.0.0",
"husky": "^8.0.1",
"lint-staged": "^9.5.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
},
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}
}
← 校验格式化工具