新版 husky 配置与Git Hooks剖析
前端工程化 —— husky
分享近期配置 husky 的一些心得
husky
husky 是前端工程化不可缺少的工具,它支持添加项目的 git hooks(可以理解当我们使用 git 命令操作时会触发的钩子事件),如此一来我们就能在提交代码时:
配合 commitlint | lint-staged & ESlint & Stylelint,对提交信息进行检查 | 运行测试 | 检查代码格式与是否报错。
我还记得在我实习的时候,我老大就经常会进行前端工程化的工作,将我们几个实习生的代码规范和开发流程严格把控,时间长了对这几个前端工程化工具慢慢就会熟悉。这恰恰是一个开发团队需要的开发规范。这几天我也需要搭建一个新的项目但是发现 husky 的配置和原来有很大的不一样。
(4.*) 旧版玩法
1. 下载依赖
npm install -D husky@^4.3.0
yarn add -D husky@^4.3.0
2. 配置
在 package.json 中配置
husky
属性
{
"husky": {
"hooks": {
"pre-push": "npm run test",
"commit-msg": "commitlint --config -E HUSKY_GIT_PARAMS"
}
}
}
- 这样在你执行
git commit
的时候就会自动执行commitlint
命令。即把你的commit信息赋值给HUSKY_GIT_PARAMS
作为参数传入commitlint
命令进行校验。 - 这里可以看出旧版主要是利用
package.json
进行git钩子信息获取。
(7.*) 新版玩法
1. 下载依赖
npm install -D husky
yarn add -D husky
2. 配置
在 package.json 中配置
scripts
添加属性
{
"scripts": {
"prepare": "husky install"
}
}
新版 husky 提供命令来添加 git 钩子事件 ——
husky add <file> [cmd]
,即执行下面的命令
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
npx husky add .husky/pre-push "npm run test"
prepare
是NPM
操作的生命周期的一环,即当我们执行npm install
时会按照生命周期以此触发生命周期钩子,在NPM7:preinstall -> install -> postinstall -> prepublish -> preprepare -> prepare -> postprepare
- 这里可以发现
commit-msg
和pre-push
和旧版配置中有点眼熟,这两个恰恰都是我们就是执行git命令钩子事件名 Git Hooks
新版剖析
git hooks一共有两种方式创建:
- 第一种就是旧版的在
.git/hooks
文件夹中创建对应事件名的脚本文件 - 第二种就是定义
hooksPath
配置指向 hooks 文件夹
为什么抛弃传统js的写法
作者写的文章:链接
- 创建了所有的
git hooks
:旧版正是 git hooks 创建方式的第一种- 好处:用户不需要关心 git hooks类型,只需要在
package.json
配置命令即可 - 坏处:每次执行 git 操作时所有的
git hooks
都会挨个执行
- 好处:用户不需要关心 git hooks类型,只需要在
- 没办法按需引入
git hooks
:当用户对package.json
进行添加操作后,没办法同步添加.git/hooks
对应的钩子文件。 - 太局限,用户自定义困难:比如我有需求在命令行当中利用钩子进行构建,生成文件,读取文件信息等需要大量
shell
命令时,对于一个天天接触 shell 的我而言只能写单一脚本的传统的package.json
写法 太局限了,会很难受。
e.g: 输出一些信息:
上图示例代码
#!/bin/sh
# 在新版中可以很舒服的写 shell 脚本
. "$(dirname "$0")/_/husky.sh"
printf "\n\033[1;32m%s \033[1;33m%s \033[1;32m%s\033[0m\n" \
"»»»" \
"commitlint checking..." \
"«««"
yarn commitlint --edit "$1"
新版是什么原理
- git config 的
core.hooksPath
。在2016年git 2.9
版本引入新feature,hooksPath
属性可以支持设置 Git Hooks 文件夹指向。我们可以打开.git/.config
文件看看: - 新版顺利安装后我们会得到一个文件夹正是
.husky
:
$ x ls -T .husky/ -a
.husky
├── _
│ ├── .gitignore
│ └── husky.sh
├── commit-msg
└── pre-commit
- 从这里开始他的设计已经明了:定义了Git Hooks 指向文件夹后,每当我们使用 git 命令的执行时会去对应文件夹下寻找与钩子事件名同名的文件进行source,这个设计和我们 x-cmd 的workspace script设计很像。
- 至于新版的commit-msg命令中的
$1
进行输出确认是.git/COMMIT_EDITMSG
文件: 即最近一次的commit edit message。
总结
- 其实新版这个设计对于小白添加了一定难度,但是对于项目上的设计放开的局限性。husky的目的也达到了:作为项目管理上的 git hooks 的入口。
- 立个flag,我相信我们X-Cmd团队会在不远的将来有一套方案和他竞争 😎
旧版迁移新版
- 删除项目当中的
.git/hooks
文件夹、 - 删除package.json的
husky
属性 - 执行上面新版的操作
Git Hooks
除了
commit-msg
和pre-commit
还有什么git hooks ? 文档
Git Hook | 调用时机 | 说明 |
---|---|---|
pre-applypatch | git am 执行前 | |
applypatch-msg | git am 执行前 | |
post-applypatch | git am 执行后 | 不影响git am 的结果 |
pre-commit | git commit 执行前 | 可以用git commit --no-verify 绕过 |
commit-msg | git commit 执行前 | 可以用git commit --no-verify 绕过 |
post-commit | git commit 执行后 | 不影响git commit 的结果 |
pre-merge-commit | git merge 执行前 | 可以用git merge --no-verify 绕过。 |
prepare-commit-msg | git commit 执行后,编辑器打开之前 | |
pre-rebase | git rebase 执行前 | |
post-checkout | git checkout 或git switch 执行后 | 如果不使用--no-checkout 参数,则在git clone 之后也会执行。 |
post-merge | git commit 执行后 | 在执行git pull 时也会被调用 |
pre-push | git push 执行前 | |
pre-receive | git-receive-pack 执行前 | |
update | ||
post-receive | git-receive-pack 执行后 | 不影响git-receive-pack 的结果 |
post-update | 当 git-receive-pack 对 git push 作出反应并更新仓库中的引用时 | |
... |
I just try my best to make thing well, Could you give a star ⭐ to encourage me ?
- (4.*) 旧版玩法
- 1. 下载依赖
- 2. 配置
- (7.*) 新版玩法
- 1. 下载依赖
- 2. 配置
- 新版剖析
- 为什么抛弃传统js的写法
- 新版是什么原理
- 总结
- 旧版迁移新版
- Git Hooks