多人协作开发时经常会遇到拉下来的代码编译报错了;拉下来都别人的调试代码影响开发体验;查找git代码提交记录时都是写的aaa等没有一点价值的commit-msg。本文基于Git Hooks来解决这些问题。
Git Hooks
git hooks,即git 钩子,定义为能在特定的重要动作发生时触发自定义脚本。
我们可以在git仓库中 .git/hooks文件夹中看到git hooks脚本文件。可以更改这些文件插入我们自己的脚本来实现我们的需求。但是直接使用git-hooks 编写成本高,无法共享(.git 文件夹是不会提交到代码仓库的)。husky可以让git hooks 的使用更简单。安装过程建议参考官方文档typicode/husky: Git hooks made easy 🐶 woof! (github.com)
下面是 husky 使用后示例图,可以直接在项目中看到 .husky/ 文件夹中都是对应的git hooks
安装
npm install husky -D
添加到package.json 中,这样别人下载代码时也会安装husky
npm set-script prepare "husky install"
npm run prepare
添加一个钩子
npx husky add .husky/pre-commit "npm test"
git add .husky/pre-commit
添加如下命令就可以在代码commit 之前执行代码检查。 lint检查并修复后,使用git add . 重新添加到暂存区。
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
git add .
Lint Staged
上面我们已经可以实现代码检查了,但是每次都会对项目中所有的文件执行一次代码检查,是没有必要的。并且git add . 也是有缺陷的,会把所有文件添加到暂存区。
对暂存的 git 文件运行 linters,不要让💩滑入您的代码库!
——来自lint-staged官方
在提交代码之前运行时,Linting 更有意义。通过这样做,您可以确保没有错误进入存储库并强制实施代码样式。但是,在整个项目上运行 lint 过程很慢,并且 lint 结果可能无关紧要。最终,您只想删除将要提交的文件。lint staged 可以让你的代码检查,只检查暂存区的代码,不会校验所有文件。而且修复后如果文件有改动,会自动重新执行git add当前文件提交到暂存区。
安装
npm install --save-dev lint-staged
在根目录创建 .lintstagedrc.json
# .lintstagedrc.json
{
"*.{js,ts,vue}": [
"npx eslint"
]
}
或者在package.json 中添加
// package.json
{
"lint-staged": {
"*.{js,ts,vue}": [
"npx eslint"
]
}
}
修改 pre-commit
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
确保npm script已经有 lint,本文不介绍eslint
规范commit-msg
在git-hooks 的comit-msg 钩子中我们可以去做msg的校验,同样直接编写会比较复杂。commitlint 可以让实现更简单,具体使用推荐参考官方文档 Local setup (commitlint.js.org)
安装
npm install --save-dev @commitlint/config-conventional @commitlint/cli
@commitlint/config-conventional 是一种共享的message配置,还有很多commitlint/@commitlint at master · conventional-changelog/commitlint (github.com),选择适合自己的,也可以自定义配置
添加配置文件
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
or 手动配置
# commitlint.config.js
module.exports = {
extends: ["@commitlint/config-conventional"],
};
这样在 git commit 提交时就必须按照msg提交格式来提交了。
推荐的msg格式
type(scope?): subject
body?
footer?
type不知道使用哪个?commitlint/index.js at master ·conventional-changelog/commitlint (github.com)
如果记不住,可以使用msg提示工具,Use prompt (commitlint.js.org)或者commitizen/cz-cli: The commitizen command line utility. #BlackLivesMatter (github.com)
自动删除调试日志
webpack 可以配置在build时删除console.log 和 debugger 等调试代码。但是只能在build的时候处理。多人协作开发时,拉下来别人忘删除的调试代码也是很常见的。所有我们也可以在lint-staged 中解决这个问题,在提交之前删除调试日志。
修改lint-staged
{
"*.{js,ts,vue}": [
"node ./misc/checkLog.js",
"npx eslint"
]
}
删除log一定要在lint 之前。这样删除后,lint --fix 时可以修复代码格式问题
lint-staged 的调用,会把文件名当作参数传递到脚本文件,可以通过 process.argv 接收参数,代码如下
// misc/checkLog.js
/* eslint-env node */
const fs = require("fs");
const files = process.argv.slice(2); // 从第二次参数开始都是文件名
files.forEach((filePath) => {
if (filePath.includes("/misc/")) return;
const oldText = fs.readFileSync(filePath, "utf-8");
const newText = oldText
.replace(/console.log\(.*\)\n/g, "\n")
.replace(/debugger\n/g, "\n");
fs.writeFileSync(filePath, newText, "utf-8");
});
总结:使用husky来简化git hooks。使用lint-staged只处理暂存区的文件,并自动重新git add。使用 @commitlint/cli 来规范提交到commit-msg。使用自定义的脚本文件在代码提交前删除调试debugger 和 console.log。