众所周知,代码格式是非常重要的,统一的代码格式将大大提高代码的可读性.每个有追求的团队都应该重视代码格式的统一,但是如果没有自动强制检测机制的话只能通过 code review 来检查了,而这么做的效率很低且容易遗漏.所以我们必须能够自动检查代码格式,在不符合时阻止代码入库.
目前最流行的代码管理工具非 git 莫属了,我们可以利用 git 提供的钩子机制来达到自动强制检查的目的.
git 的钩子机制就是在特定动作发生时可以自动运行一些自定义脚本,git 提供了两种钩子一种运行在客户端,一种运行在服务端. 顾名思义服务端钩子需要在服务器上进行安装,由于git服务器上的配置需要各种权限,开发者不一定有这个权限,所以我们用客户端钩子来做这件事.
需要注意的是,克隆某个版本库时,它的客户端钩子并不随同复制。
也就是说,客户端钩子不会同步到其他开发者的机器上,只能在本机生效,这就达不到强制执行的目的了.很多人看到这条限制就直接放弃客户端钩子了,其实我们可以想一些方案来同步钩子.
代码开发肯定是需要本地调试和测试的,不管是调试还是测试都需要运行一些命令让代码跑起来,我们可以在这些命令运行时顺便把 git 钩子安装上.,把要安装的钩子放在项目根目录的 githooks 目录下,然后再运行调试命令时把 githooks 目录复制到 .git/hooks 目录下就可以了.
拿 javascript 项目来说,一般都是通过 npm run xxx
来运行代码的,可以这样写package.json
{
....
"scripts": {
"start": "cp -rf githooks/ .git/hooks/ ; webpack"
},
.....
}
或者
{
....
"scripts": {
"prestart": "cp -rf githooks/ .git/hooks/",
"postinstall": "cp -rf githooks/ .git/hooks/",
"start": "webpack"
},
.....
}
对于代码格式检查来说合适的钩子是 pre-commit, 我们可以在 pre-commit 里进行代码格式检查,如果代码有问题就返回1来阻止继续提交.
下面是我用的 pre-commit 的脚本内容
#!/bin/sh
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep ".jsx\{0,1\}$")
ESLINT="$(git rev-parse --show-toplevel)/node_modules/.bin/eslint"
if [[ "$STAGED_FILES" = "" ]]; then
exit 0
fi
PASS=true
# Check for eslint
if [[ ! -x "$ESLINT" ]]; then
echo "\t\033[41mPlease install ESlint\033[0m (npm i --save-dev eslint)"
exit 1
fi
for FILE in $STAGED_FILES
do
"$ESLINT" "$FILE"
if [[ "$?" != 0 ]]; then
echo "\t\033[41mESLint Failed: $FILE\033[0m"
PASS=false
fi
done
if ! $PASS; then
echo "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass ESLint but do not. Please fix the ESLint errors and try again.\n"
exit 1
fi
exit $?
脚本很简单,就是先拿到本次提交的 js 或者 jsx 文件路径,然后依次对这些文件进行eslint,如果有错误就输出错误信息,返回1来阻止继续提交.