[Cli] Git提交规范之消息提交
标准化大厂编程规范解决方案之 ESLint + Git Hooks(3)
在前面我们通过 prettier + ESLint
解决了代码格式的问题,但是我们之前也说过 编程规范 指的可不仅仅只是 代码格式规范 。
除了 代码格式规范 之外,还有另外一个很重要的规范就是 git
提交规范!
在现在的项目开发中,通常情况下,我们都会通过 git
来管理项目。只要通过 git
来管理项目,那么就必然会遇到使用 git
提交代码的场景
当我们执行 git commit -m "描述信息"
的时候,我们知道此时必须添加一个描述信息。
而很多人的描述 “天马行空” ,这样就会导致别人在看你的提交记录时,看不懂你说的什么意思?不知道你当前的这次提交到底做了什么事情?会不会存在潜在的风险?
所以 git
提交规范 势在必行。
对于 git
提交规范 来说,不同的团队可能会有不同的标准,目前使用较多的 Angular 团队规范 延伸出的 Conventional Commits specification(约定式提交) 为例,详解 git
提交规范
约定式提交
约定式提交规范要求如下:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
-------- 翻译 -------------
<类型>[可选 范围]: <描述>
[可选 正文]
[可选 脚注]
其中 <type>
类型,必须是一个可选的值,比如:
- 新功能:
feat
- 修复:
fix
- 文档变更:
docs
- ....
也就是说,如果要按照 约定式提交规范 来去做的化,那么你的一次提交描述应该式这个样子的:
要是每次都这么写,写到猴年马月了!
所以需要使用 Commitizen 助你规范化提交代码
Commitizen
通过上面我们了解到如果严格按照约定式提交规范, 来手动进行代码提交的话,那么是一件非常痛苦的事情,但是 git 提交规范的处理 又势在必行,那么怎么办呢?
经过很多人的冥思苦想, 出现了一种叫做 git 提交规范化工具 的东西,而 commitizen
就是其中的佼佼者!
commitizen
仓库名为 cz-cli ,它提供了一个 git cz
的指令用于代替 git commit
,简单一句话介绍它:
当你使用
commitizen
进行代码提交(git commit)时,commitizen
会提交你在提交时填写所有必需的提交字段!
这句话怎么解释呢?不用着急,下面就来安装并且使用一下 commitizen
,使用完成之后自然就明白了这句话的意思!
全局安装
Commitizen
npm install -g commitizen@4.2.4
安装并配置
cz-customizable
插件使用
npm
下载cz-customizable
npm i cz-customizable@6.3.0 --save-dev
添加以下配置到
package.json
中...
"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
使用git cz
代替git commit
,即可看到提示内容
那么到这里就可以使用git cz
来代替了 git commit
实现了规范化的提交诉求了,但是当前依然存在着一个问题,那就是必须要通过 git cz
指令才可以完成规范化提交!
那么如果有马虎的同事,忘记了使用 git cz
指令,直接就提交了怎么办呢?
那么有没有方式来限制这种错误的出现呢?答案是有的!
所以需要 Git Hooks
Git Hooks
上面我们使用了 git cz
来代替了 git commit
实现了规范化的提交诉求,但是依然存在着有人会忘记使用的问题。
那么我们应该如何去进行解决。
先来明确一下我们最终要实现的效果:
我们希望:
当《提交描述信息》不符合 约定式提交规范 的时候,阻止当前的提交,并抛出对应的错误提示
而要实现这个目的,就需要先来了解一个概念,叫做 Git hooks(git 钩子 || git 回调方法)
也就是:git
在执行某个事件之前或之后进行一些其他额外的操作
而我们所期望的 阻止不合规的提交消息,那么就需要使用到 hooks
的钩子函数。
下面是我整理出来的所有的 hooks
,其中加粗的是常用到的 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 | ||
post-receive | git-receive-pack 执行后 | 不影响git-receive-pack 的结果 |
post-update | 当 git-receive-pack 对 git push 作出反应并更新仓库中的引用时 | |
push-to-checkout | 当`git-receive-pack 对git push 做出反应并更新仓库中的引用时,以及当推送试图更新当前被签出的分支且receive.denyCurrentBranch 配置被设置为updateInstead 时 | |
pre-auto-gc | git gc --auto 执行前 | |
post-rewrite | 执行git commit --amend 或git rebase 时 | |
sendemail-validate | git send-email 执行前 | |
fsmonitor-watchman | 配置core.fsmonitor 被设置为.git/hooks/fsmonitor-watchman 或.git/hooks/fsmonitor-watchmanv2 时 | |
p4-pre-submit | git-p4 submit 执行前 | 可以用git-p4 submit --no-verify 绕过 |
p4-prepare-changelist | git-p4 submit 执行后,编辑器启动前 | 可以用git-p4 submit --no-verify 绕过 |
p4-changelist | git-p4 submit 执行并编辑完changelist message 后 | 可以用git-p4 submit --no-verify 绕过 |
p4-post-changelist | git-p4 submit 执行后 | |
post-index-change | 索引被写入到read-cache.c do_write_locked_index 后 |
tip
详细的 HOOKS介绍
可点击这里查看
整体的 hooks
非常多,其中用的比较多的其实只有两个:
Git Hook | 调用时机 | 说明 |
---|---|---|
pre-commit | git commit 执行前它不接受任何参数,并且在获取提交日志消息并进行提交之前被调用。脚本 git commit 以非零状态退出会导致命令在创建提交之前中止。 | 可以用git commit --no-verify 绕过 |
commit-msg | git commit 执行前可用于将消息规范化为某种项目标准格式。 还可用于在检查消息文件后拒绝提交。 | 可以用git commit --no-verify 绕过 |
简单来说这两个钩子:
commit-msg
:可以用来规范化标准格式,并且可以按需指定是否要拒绝本次提交pre-commit
:会在提交前被调用,并且可以按需指定是否要拒绝本次提交
而接下来要做的关键,就在这两个钩子上面。
使用 husky + commitlint 检查提交描述是否符合规范要求
了解了 git hooks
的概念,那么接下来就使用 git hooks
来去校验提交信息。
要完成这么个目标,需要使用两个工具:
commitlint:用于检查提交信息
husky:是
git hooks
工具
两个包的说明
- commitlint 它可以检查提交信息, 但是只能起到检查的效果, 那么在何时进行检查就需要用到第二个库
- husky 来指定当前的 commit lint, 在 git hook 的 commit-msg 的 hooks 下执行, 来达到执行 git commit 的时候通过第一个库 commitlint 来进行提交信息校验的功能
注意:npm
需要在 7.x 以上版本!!!!!
那么下面分别安装一下这两个工具:
commitlint
- 安装依赖:
npm install --save-dev @commitlint/config-conventional@12.1.4 @commitlint/cli@12.1.4
- 创建
commitlint.config.js
文件
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
// 这句命令对外导出一个对象, 这个对象继承了这个包
- 打开
commitlint.config.js
, 增加配置项( config-conventional 默认配置点击可查看 ):
module.exports = {
// 继承的规则
extends: ["@commitlint/config-conventional"],
// 定义规则类型
rules: {
// type 类型定义,表示 git 提交的 type 必须在以下类型范围内
"type-enum": [
// 当前验证的错误级别, 2表示错误级别
2,
// 在什么情况下进行验证
"always",
// 泛型内容, 这里应该在之前定义的cz types里一样
[
"feat", // 新功能 feature
"fix", // 修复 bug
"docs", // 文档注释
"style", // 代码格式(不影响代码运行的变动)
"refactor", // 重构(既不增加新功能,也不是修复bug)
"perf", // 性能优化
"test", // 增加测试
"chore", // 构建过程或辅助工具的变动
"revert", // 回退
"build", // 打包
],
],
// subject 大小写不做校验
"subject-case": [0],
},
};
注意:确保保存为 UTF-8
的编码格式,否则可能会出现以下错误:
那么如何确定当前保存文件编码格式是UTF-8
?
在 VSCODE 右下角
此时, commitlint 已经安装并且配置完成了, 但是如果希望使用 commitlint 加入到 git hooks 里面, 还需要使用到另外一个库husky
husky
它是一个可以用来检测 git hooks 工具的东西
安装依赖:
npm install husky@7.0.1 --save-dev
启动
hooks
, 生成.husky
文件夹npx husky install
在
package.json
中生成prepare
指令( 需要 npm > 7.0 版本 )npm set-script prepare "husky install"
执行
prepare
指令npm run prepare
执行成功,提示
husky - Git hooks installed
执行以下指令, 指令的作用是添加
commitlint
的hook
到husky
中,也就是通过husky
来监听git hooks
的commit-msg
的回调里去执行 commit linint 来完成提交代码的检测. 并指令在commit-msg
的hooks
下执行npx --no-install commitlint --edit "$1"
指令npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
此时的
.husky
的文件结构 多出的 commit-msg 这个文件会在 commit-msg 的 git hook 里执行, 执行的时候会去执行这个文件里的npx --no-install commitlint --edit "$1"
这句指令commit-msg 的文件内容
至此, 不符合规范的 commit 将不再可提交:
PS F:\xxxxxxxxxxxxxxxxxxxxx\目录> git commit -m "测试"
⧗ input: 测试
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky - commit-msg hook exited with code 1 (error)
那么至此,就已经处理好了 强制规范化的提交要求,到现在 不符合规范的提交信息,将不可在被提交!
那么到这里 规范化目标 就完成了吗?
当然没有!
现在还缺少一个 规范化的处理 ,那就是 代码格式提交规范处理!
也就是说目前位置做的都是git 的消息提交规范, 但是我们的代码格式提交规范还没有做
所以需要下一步通过 pre-commit 处理提交时代码规范