如何使用
添加新 Hook
添加 hook 与创建文件一样简单。可以通过你喜欢的编辑器、脚本或 echo 命令来实现。例如,在 Linux/macOS 中:
echo "npm test" > .husky/pre-commit
启动文件
Husky 允许你在运行钩子之前执行本地命令。它从这些文件中读取命令:
$XDG_CONFIG_HOME/husky/init.sh
~/.config/husky/init.sh
~/.huskyrc
(已弃用)
Windows 系统:C:\Users\yourusername\.config\husky\init.sh
跳过 Git 钩子
对于单个命令
大多数 Git 命令都包含一个 -n/--no-verify
选项来用于跳过钩子:
git commit -m "..." -n # 跳过 Git 钩子
对于没有使用此标识的命令,使用 HUSKY=0 来临时禁用钩子:
HUSKY=0 git ... # 临时禁用所有 Git 钩子
git ... # 钩子会再次运行
对于多个命令
在一个较长的时间里禁用钩子(例如,在变基或者合并期间):
export HUSKY=0 # 禁用所有 Git 钩子
git ...
git ...
unset HUSKY # 重新启用钩子
对于 GUI 或全局
要在 GUI 客户端或全局禁用 Git 钩子,请修改 Husky 配置:
# ~/.config/husky/init.sh
export HUSKY=0 # Husky 不会安装,也不会再你的机器上运行钩子
CI 服务器和 Docker
要避免在 CI 服务器或 Docker 中安装 Git 钩子,请使用 HUSKY=0
。例如,在 GitHub Actions 中:
# https://docs.github.com/en/actions/learn-github-actions/variables
env:
HUSKY: 0
如果只安装 dependencies
(不是 devDependencies
),"prepare": "husky"
脚本可能会失败,因为 Husky 不会被安装。
你有多种解决方案。
修改 prepare
脚本使其永远不会失败:
// package.json
"prepare": "husky || true"
你仍然会在输出中看到一个 command not found
的错误消息,这可能会让你很感到困惑。为了让它消失,创建 .husky/install.mjs
:
// 在生产环境或 CI 环境中跳过 Husky 的安装
if (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {
process.exit(0)
}
const husky = (await import('husky')).default
console.log(husky())
然后,在 prepare
脚本中使用它:
"prepare": "node .husky/install.mjs"
测试钩子
要测试一个钩子,将 exit 1
添加到钩子脚本以中止 Git 命令:
# .husky/pre-commit
# 你的 WIP 脚本
# ...
exit 1
git commit -m "testing pre-commit code"
# 提交不会被创建
项目不在 Git 根目录
出于安全考虑,Husky 不会安装在父目录(../
)中。但是,你可以在 prepare
脚本中更改目录。
考虑一下这个项目结构:
.
├── .git/
├── backend/ # 没有 package.json
└── frontend/ # package.json 中带有 husky
像这样设置你的 prepare 脚本:
"prepare": "cd .. && husky frontend/.husky"
在你的 hook 脚本中,将目录切换回相关的子目录:
# frontend/.husky/pre-commit
cd frontend
npm test
非 shell 脚本钩子
为了运行需要使用脚本语言的脚本,对每个适用的钩子使用以下模式:
(使用钩子 pre-commit
和 NodeJS 的示例)
- 为钩子创建一个入口:shell
.husky/pre-commit
- 在文件中添加以下内容:shell
node .husky/pre-commit.js
- 在
.husky/pre-commit.js
文件中:javascript// 你的 NodeJS 代码 // ...
Bash
钩子脚本需要与 POSIX 兼容,以确保最佳兼容性,因为并非每个人都有 bash (例如 Windows 用户)。
也就是说,如果你的团队不使用 Windows,你可以这样使用 Bash:
# .husky/pre-commit
bash << EOF
# Put your bash script inside
# ...
EOF
Node 版本管理器和 GUI
如果您在 GUI 中使用 Git 钩子,并通过版本管理器(比如 nvm
、n
、fnm
、asdf
、volta
等等)安装 Node,由于 PATH
环境变量问题,你可能会遇到 command not found
报错。
了解 PATH
和版本管理器
PATH
是一个包含目录列表的环境变量,你的 shell 在这些目录中检索命令,如果没找到这个命令,你就会得到一个 command not found
报错。
在 shell 中运行 echo $PATH
来查看其内容。
版本管理器的工作方式如下:
- 将初始化代码添加到 shell 启动文件(
.zshrc
、.bashrc
等),它会在每次打开终端时运行。 - 将 Node 版本下载到主文件夹下的目录中。
例如,如果你有两个 Node 版本:
~/version-manager/Node-X/node
~/version-manager/Node-Y/node
打开终端将初始化版本管理器,它将选择一个版本(比如 Node-Y
)并预先设置其到 PATH
的路径:
echo $PATH
# 输出
~/version-manager/Node-Y/:...
现在,Node 指向 Node-Y
。切换到 Node-X
时会相应地改变 PATH
:
echo $PATH
# 输出
~/version-manager/Node-X/:...
出现这个问题是因为在终端之外启动的 GUI 没有初始化版本管理器,导致 PATH
没有 Node 安装路径。因此,来自 GUI 的 Git 钩子常常会失败。
解决方案
husky 在每个钩子之前都会执行 ~/.config/husky/init.sh
。将版本管理器初始化代码复制到这里,以确保在 GUI 中运行。
nvm
示例:
# ~/.config/husky/init.sh
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # 加载 nvm
或者,如果你的 shell 启动文件快速且轻量,也可以直接使用:
# ~/.config/husky/init.sh
. ~/.zshrc
手动设置
Git 需要配置,husky 需要在 .husky/
中设置文件。
在仓库中运行一次 husky
命令。理想情况下,将其设置在 package.json
的 prepare
脚本中,以便每次安装后自动执行推荐。
{
"scripts": {
"prepare": "husky"
}
}
{
"scripts": {
"prepare": "husky"
}
}
{
"scripts": {
// Yarn 不支持 prepare 脚本
"postinstall": "husky",
// 如果发布到 npmjs.com,需要加上这个
"prepack": "pinst --disable",
"postpack": "pinst --enable"
}
}
{
"scripts": {
"prepare": "husky"
}
}
运行一次 prepare
:
npm run prepare
pnpm run prepare
# Yarn 不支持 `prepare`
yarn run postinstall
bun run prepare
在 .husky/
目录中创建一个 pre-commit
文件:
# .husky/pre-commit
npm test
# .husky/pre-commit
pnpm test
# .husky/pre-commit
yarn test
# .husky/pre-commit
bun test