以下示例将使用nodejs工具,但是您可以使用语言中的任何类似工具。另外,这篇文章假设您已经在项目中配置了刺激工具。
git挂钩是git功能之一,当发生某个操作时,它将触发自定义脚本。有多种git钩动作,但是今天我们将使用2个客户端钩子,这将帮助您或您的团队写出更好的信息和更改。
预警
将触发此钩子在将更改提交给git之前,我们将使用此钩子使用以下脚本来提交/优化我们的更改。 SVGO是一个了不起的NPM软件包,它将优化您的SVG文件,在https://jakearchibald.github.io/svgomg/上相同的实现
{
"scripts": {
// This will allow the lint to automatically fix our staged files
"format-eslint": "eslint --fix",
"format-prettier-eslint": "prettier-eslint --log-level 'silent' --write --eslint-config-path .eslintrc.js",
"format-stylelint": "stylelint --config .stylelintrc.json --fix",
"optimize-svgo": "svgo"
}
}
#!/bin/bash
PASS=true
# 'git diff --diff-filter=d --cached --name-only' will output the staged file names
# with 'grep -E' we can capture the output and filter out the files we wanted to lint using RegExp
STAGED_FILES=$(git diff --diff-filter=d --cached --name-only | grep -E '.*\.(js|vue|ts|svg)$')
# This will exit the script if there is no files matching the pattern
if [[ "$STAGED_FILES" = "" ]]; then
exit 0
fi
# '\033[0;33m' is yellow bash color
# '\e[0m' means we reset the color back to normal
echo -e "\033[0;33m☐ Running pre-commmit-hooks:\e[0m"
for FILE in $STAGED_FILES
do
# This will capture the initial has of the file, we use this to detect if there is changes applied after linting
PRE_LINT_HASH=$(git hash-object "$FILE")
# Only run eslint/prettier/stylelint on vue/js/ts files
if [[ $FILE == *vue || $FILE == *js || $FILE == *ts ]];
then
# Only run stylelint on vue files since other file types doesn't contain stylesheet
if [[ $FILE == *vue ]];
then
npm run --silent format-stylelint "$FILE" || PASS=false
npm run --silent format-prettier-eslint "$FILE" || PASS=false
npm run --silent format-eslint "$FILE" || PASS=false
else
npm run --silent format-prettier-eslint "$FILE" || PASS=false
npm run --silent format-eslint "$FILE" || PASS=false
fi
# SVGO optimize svg files
elif [[ $FILE == *svg ]]
then
npm run optimize-svgo "$FILE"
fi
POST_LINT_HASH=$(git hash-object "$FILE")
# If there is changes detected, we will set the PASS flag to false to stop the commit from continuing
if [[ "$PRE_LINT_HASH" != "$POST_LINT_HASH" ]]; then
PASS=false
fi
done
# Stop the commit if there is file changes during above process
if ! $PASS; then
# '\033[0;31m' is red bash color
echo -e "\033[0;31m☒ pre-commmit-hooks failed, please check all the errors or stage all changes\e[0m"
# 'exit 1' will stop the process by throwing error
exit 1
fi
exit $?
输出看起来像这样
-> % git commit -m "foo"
☐ Running pre-commmit-hooks:
~/project/foo.js
82:11 error Identifier 'foo_fighter' is not in camel case camelcase
✖ 1 problem (1 error, 0 warnings)
☒ pre-commmit-hooks failed, please check all the errors or stage all changes
准备委托-MSG
在输入提交消息CLI之前将触发此钩子。有时,我们会发出愚蠢或不描述性的提交信息,使用此钩子,我们会将分支名称附加到提交消息的开头中,以便我们可以在git责备期间看到分支名称。如果您使用的是JIRA或任何其他问题跟踪板,通常我们会创建一个带有其代码的分支名称,例如:git checkout -b PROD-34
。
#!/bin/bash
# This way you can customize which branches should be skipped when
# prepending commit message.
if [ -z "$BRANCHES_TO_SKIP" ]; then
BRANCHES_TO_SKIP=(master)
fi
# Get current commit branch name
BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_NAME="${BRANCH_NAME##*/}"
BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$")
BRANCH_IN_COMMIT=$(grep -c "\[$BRANCH_NAME\]" $1)
# '-n' is a test pattern, we check if the branch name matches with the one we wanted to skip
if [ -n "$BRANCH_NAME" ] && ! [[ $BRANCH_EXCLUDED -eq 1 ]] && ! [[ $BRANCH_IN_COMMIT -ge 1 ]]; then
# This will append the commit message with '[branch-name]:'
sed -i.bak -e "1s/^/[$BRANCH_NAME]: /" $1
fi
使用上述脚本,如果我们做
-> % git commit -m "foo"
[PROD-34 abc123456] [PROD-34]: foo
1 files changed, 2 insertions(+), 3 deletions(-)
create mode 100644 foo.js
,但我们不能在远程项目上安装git钩,只有本地
是的,这就是为什么我们要使用postinstall
脚本。这将在运行npm install
后将触发,我们将创建一个简单的nodejs
脚本,以在用户完成安装Project node_modules
之后,将我们准备的脚本文件复制到.git/hooks
文件夹中。在这里,我将钩子保存到git-hooks
文件夹中。
{
"scripts": {
"postinstall": "node build/post-install.js",
}
}
// post-install.js
const fs = require('fs')
// destination will be created or overwritten by default.
fs.copyFile('./git-hooks/prepare-commit-msg', './.git/hooks/prepare-commit-msg', err => {
if (err) throw err
console.log('File was copied to destination')
})
// destination will be created or overwritten by default.
fs.copyFile('./git-hooks/pre-commit', './.git/hooks/pre-commit', err => {
if (err) throw err
console.log('File was copied to destination')
})
这就是您可以使用git挂钩为团队代码质量创建一些自动化的方法。如果您想查看我在开发过程中使用的其他有用的脚本,则可以检查我的dotfiles。