在了解husky之前,先了解一下Git hooks。
GitHooks
官方文档:https://git-scm.com/docs/githooks
是什么
git hooks 是git提供的hooks,类似Vue的生命周期钩子函数一样,Git也会在它运行周期里面的某些时间点,提供一些让用户添加和执行自定义的函数。
默认情况下,hooks 目录是 $GIT_DIR/hooks
,但可以通过 core.hooksPath
配置变量进行更改。打开之后能看到很多Hooks
的sample
。
Simple
文件的内容如下:
可以发现,Githooks文件其实是一个shell
脚本,可以通过修改shell
脚本来实现自定义功能。
常用的hooks
pre-commit 预提交
该钩子由 git-commit
调用,可以使用 --no-verify
选项绕过。它不带任何参数,在提交之前调用。从此脚本中以非零状态退出会导致 git commit
命令在创建提交前中止。
prepare-commit-msg 准备-提交-消息
在准备好默认日志消息之后、启动编辑器之前,git-commit[1] 会立即调用此挂钩。
它需要一到三个参数。
- 第一个是包含提交日志消息的文件的名称。
- 第二个是提交消息的来源,可以是:
message
(如果给出了-m
或-F
选项);template
(如果给出了-t
选项或设置了配置选项commit.template
);merge
(如果提交是合并或存在.git/MERGE_MSG
文件);squash
(如果.git/SQUASH_MSG
文件存在);或commit
,后跟提交对象名称(如果给出了-c
、-C
或--amend
选项)。
如果退出状态非零, git commit
将中止。
Githooks能解决什么
回到项目中的实际问题
- 问题:远程仓库的代码中存在语法错误
- 原因:有成员没有仔细检查,误把有语法错误的代码上传了
- 解决方法:在
commit之前
检查在暂存区的代码,看是否存在语法错误 显然,如果只靠当前成员去检查自己添加到暂存区的代码有没有错误,是很不可靠且低效的行为,那么这里我们可以用到pre-commit
这一个hook了,它可以在git commit之前执行我们自定义的语句,当执行错误
或者返回非0状态
的时候阻止commit行为。
除了这个Hook以外,还有哪些就不一一介绍了,一般的Git操作,例如commit、push等会提供操作前或操作后的Hook,有兴趣的可以查看Githooks去了解。
Husky
git hooks和husky有什么关系呢?用一句话概括,那就是husky能够简化上述创建或者修改Githooks的操作流程。
husky工作原理
- 初始化:先检查该项目是否通过Git来托管代码的
1 | if (spawnSync('git', ['rev-parse']).status !== 0) { |
- 创建
.husky
文件夹:创建.husky
文件夹用来存放Githooks
和husky
的配置
1 | // 创建 .husky/_ |
- 修改
git hooks
路径:通过core.hooksPath
使项目Githooks
的路径,指向新创建的.husky
文件夹
1 | const { error } = spawnSync('git', ['config', 'core.hooksPath', dir]); |
- 初始化之后,可以通过
add
命令来进行创建或者往文件后面增加语句
1 | if (existsSync(file)) { |
如何使用Husky
为了更好的演示这个功能,我们来做一个小Demo。
需求如下:
在代码commit之前,检查暂存区的代码的语法错误。
解决方案:
pre-commit hook
+husky
。它可以在git commit之前执行我们自定义的语句,当执行错误
或者返回非0状态
的时候阻止commit
行为。
npm
初始化:安装eslint
、lint-staged
和husky
1 | npm install --save-dev eslint lint-staged husky |
eslint
初始化
1 | npm init @eslint/config |
husky
初始化
1 | npx husky install |
这时候我们就看到了.husky的文件夹
- 添加
lintstagedrc.js
:用来配置暂存区文件相对应的lint
1 | module.exports = { |
- 使用husky add添加一条检查命令:
创建一个pre-commit hook
,用来对暂存区的文件进行检查
1 | npx husky add .husky/pre-commit "npx lint-staged -c .husky/lintstagedrc.js" |
- 在项目中新增一个js,故意写上语法错误
1 | const testA = { |
- 尝试提交代码,得到以下报错
- 把语法错误修复之后再
commit
,这时候就可以顺利通过检测且commit了,这样我们的目的就达成了