如何使用
添加新 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 1git 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
# ...
EOFNode 版本管理器和 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 preparepnpm run prepare# Yarn 不支持 `prepare`
yarn run postinstallbun 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