问题背景
之前在做代码合并的时候,部分同事的私仓代码合并到公仓分支时,被gitlab
的pre-merge-hooks
拦住了,提示提交的commit信息不符合规范,同事的提交信息是这个样子:
commit fc442934c39fe700aa24d3f2f426d266e07a459e
Author: xxxxx
Date: Fri Nov 5 10:08:50 2021 +0800
修改文案
公司的提交commit提交规范是这样一个标准:
- 第一行是需求编号
S
开头,然后跟某个数值 - 第二行是
Message:
开头,然后跟内容
commit fc442934c39fe700aa24d3f2f426d266e07a459e
Author: xxxxx
Date: Fri Nov 5 10:08:50 2021 +0800
S200
Message: 修改文案
同事是知道这个规范的,提交的时候就忘了。 怎么避免这种情况,现在来说下一个常用的方案
解决方案
我们可以把这个拦截操作提前,在本地提交代码的时候,不符合commit信息规范的禁止提交。而不是在合并公仓的时候才发现。
现在流行的方案是husky + lint-staged
。
husky
可以在执行git-hooks
处理一些额外配置任务,比如在commit-msg
钩子检查提交信息是否规范lint-staged
只会对暂存区的文件运行已经配置linter或其他任务,比如prettier
格式化代码
husky
yarn add husky
安装完后可以在当前工程的.git/hooks/
文件夹下检查是否安装成功
[~/Work_Space/demo/.git/hooks] []
-> % tree
.
|____pre-rebase
|____pre-applypatch
|____husky.sh //新增了husky脚本,说明安装成功
|____husky.local.sh
|____commit-msg
|____pre-commit
|____pre-merge-commit
lint-staged:
yarn add lint-staged
安装后配置下package.json
:
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "echo 'from husky'" // 输出一句话
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"echo 'from lint-stage'"
]
}
}
上面的配置意思是,在pre-commit
钩子执行的时候,对暂存区中src目录下任意后缀为.js.vue
输出一句话,commit-msg
同理。
来测试下:
从结果来看配置是ok的。
项目配置
项目中的具体配置:
- pre-commit的时候对暂存区文件执行lint操作
- commit-msg的时候校验提交commit信息
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "node scripts/verify-commit.js"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint",
"git add" // eslint结束后重新把文件加入暂存区
]
}
}
verify-commit.js:
const chalk = require('chalk');
const path = require('path');
const msg = require('fs')
.readFileSync(path.resolve('.git/COMMIT_EDITMSG'), 'utf-8')
.trim();
const commitRE = /^(S|R\d+\r?\n(?:M|m)essage: .{1,50})/;
if (!commitRE.test(msg)) {
console.log()
console.error(
` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(
`Invalid commit message format.`
)}\n\n` +
chalk.red(
` Proper commit message format as below. Example:\n\n`
) +
` ${chalk.green(`S2222`)}\n` +
` ${chalk.green(
`Message: feat(router): 修改文案字体大小`
)}\n\n`
);
process.exit(1);
}
现在我们来测试下,不符合格式的提交信息是否能拦住:
我修改了下src/main.js
,提交的时候pre-commit
通过了,因为代码没有eslint
错误, 然后也正确的拦截住了错误的提交信息。
其他问题
在vscode中不管是使用命令行还是插件gitLen
是没问题的,但是不少同事习惯用source-tree
提交代码,经过测试,mac
电脑使用source-tree
提交代码的时候,就算lint-staged
有eslint
错误或者提交信息格式不正确,source-tree
吞掉了这些错误,硬是把代码提交上去了。查看了git日志后描述:
Can't find npx in PATH: /Applications/Sourcetree.app/Contents/Resources/git_local/libexec/git-core:/Applications/Sourcetree.app/Contents/Resources/bin:/Applications/Sourcetree.app/Contents/Resources/git_local/bin:/Applications/Sourcetree.app/Contents/Resources/git_local/gitflow:/Applications/Sourcetree.app/Contents/Resources/git_local/git-lfs:/usr/bin:/bin:/usr/sbin:/sbin
Skipping pre-commit hook!!!
原因是soucre-tree
找不到npx
命令,这种类型的客户端gui,访问的环境变量是需要提前配置的。这里需要给配置正确的node
路径,使用node
执行npx
命令,需要在.git/hooks/pre-commit
和.git/hooks/commit-message
加入:
#!/bin/sh
# husky
PATH=/Users/root/n/bin:$PATH # 加入这行
# Created by Husky v4.3.8 (https://github.com/typicode/husky#readme)
# At: 2021/11/5 下午2:33:07
# (https://github.com/typicode/husky#readme)
. "$(dirname "$0")/husky.sh"
PATH=/Users/root/n/bin:$PATH
中/Users/root/n/bin
就是node
所处的目录, 根据自己的电脑来配置node路径
which node
/Users/root/n/bin
设置完环境变量后,重新测试:
成功拦截!如果husky还配置其他钩子任务,使用source-tree
提交也要加上上诉环境变量配置。
总结
github有标准的commit-msg的规范
, 很多第开源项目都采用这个标准,比如vue-next
的提交规范,可以作为一个标准的参考。