Git Hooks
是什么?
Hooks是提前定义的脚本程序,它们可以在git命令执行的特定时刻被触发。它是git的内置功能,在本地运行。
常用的hook有:
- pre-commit
- prepare-commit-msg
- commit-msg
- post-commit
- post-merge
- pre-push
实际应用中,你可能需要这样的自动化配置来解放生产力,比如:
- 提交之前配合eslint进行代码规范检查、配合prettier进行代码格式化、进行单元测试。
- 为了维护清晰的提交记录,检查git提交是否符合Conventional Commits提交规范。
- 拉取远程仓库后,可能有人添加新的依赖,使用hook可以配置在拉取之后自动安装依赖。
怎么工作?
每个git仓库都有一个hooks的文件夹,默认为.git/hooks
,在特定git命令执行时被触发调用。hook脚本以非零状态码退出(exit 1
)时,会终止该git命令执行。
如何实现?
只需要在.git/hooks
中重写(或创建)脚本即可。然而,实际开发中通常不会这样做,而是使用工具,例如husky
。
husky
本文使用husky v6,使用v4版本以下有不同的使用方法。
安装:
yarn add -D husky
添加下面npm scripts:
"scripts": {
"test": "echo testing...",
"prepare": "husky install"
}
运行yarn prepare
,会在项目下创建一个文件夹,同时在.git/confg
文件中添加了这样一行代码hooksPath = .husky
,告诉git将hooks路径改为.husky
:
接着,你就可以执行husky add <file> [cmd]
创建钩子,例如:
# 如果没有相应钩子文件,会创建
yarn husky add .husky/pre-commit "echo 提交之前执行npm test命令"
# 已有钩子文件,会将[cmd]添加到钩子文件末尾
yarn husky add .husky/pre-commit "npm test"
生成.husky/pre-commit
如下:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo 提交之前执行npm test命令
yarn test
执行提交命令测试git commit -m "test"
,执行结果见下图:
如果你使用monorepo的项目管理模式,建议在根package.json中添加husky。
如果你只想测试一个hook,在脚本末尾加exit 1
来终止git命令。
# .husky/pre-commit
# ...
exit 1 # Commit will be aborted
Conventional Commits
Conventional Commits是一种提交信息规范,是一种约定,使git提交信息对人和机器都更具可读性。
该规范约定提交信息应该具有如下结构:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
如果想了解具体规范,请查阅官网。
commitizen
是遵循Conventional Commits规范的一个npm开发工具包,以命令行提示的方式让你更容易地按规范提交。它同时遵守Angular的约定提供了下面几种type:
- feat: A new feature
- fix: A bug fix
- docs: Documentation only changes
- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- refactor: A code change that neither fixes a bug nor adds a feature
- perf: A code change that improves performance
- test: Adding missing tests or correcting existing tests
- build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
- ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
- chore: Other changes that don't modify src or test files
- revert: Reverts a previous commit
安装:
yarn add -D commitizen
添加npm脚本:
"scripts": {
"cz": "cz"
}
仓库commitizen友好化:
yarn commitizen init cz-conventional-changelog --dev --exact
OK,现在想要提交执行yarn cz
按提示进行即可。
在pre-commit做测试或其他工作后失败导致终止提交,通过修改代码再次提交,可以通过--retry参数,运行
yarn cz -- --retry
重试上一次的提交。而不需要跟随commitizen提示,重新填写上次相同的commit内容。
然而,我们仍然可以通过git commit
的方式提交不规范的记录。这时可以利用GIt hooks在commit-msg钩子中添加规范检查,commitlint
就是这样一个检查工具包。
安装commitlint:
yarn add -D @commitlint/cli @commitlint/config-conventional
添加commitlint.config.js配置文件:
module.exports = {
extends: ['@commitlint/config-conventional']
}
添加commit-msg钩子:
yarn husky add .husky/commit-msg "npx commitlint --edit"
OK,此时通过git commit
提交不符合规范的记录,会失败并提示不符合规范的地方。