Appearance
如何
¥How To
添加新钩子
¥Adding a New Hook
添加钩子就像创建文件一样简单。这可以使用你最喜欢的编辑器、脚本或基本的 echo 命令来完成。例如,在 Linux/macOS 上:
¥Adding a hook is as simple as creating a file. This can be accomplished using your favorite editor, a script or a basic echo command. For example, on Linux/macOS:
shell
echo "npm test" > .husky/pre-commit
启动文件
¥Startup files
Husky 允许你在运行钩子之前执行本地命令。它从这些文件中读取命令:
¥Husky allows you to execute local commands before running hooks. It reads commands from these files:
$XDG_CONFIG_HOME/husky/init.sh
~/.config/husky/init.sh
~/.huskyrc
(已弃用)¥
~/.huskyrc
(deprecated)
在 Windows 上:C:\Users\yourusername\.config\husky\init.sh
¥On Windows: C:\Users\yourusername\.config\husky\init.sh
跳过 Git 钩子
¥Skipping Git Hooks
用于单个命令
¥For a Single Command
大多数 Git 命令都包含一个 -n/--no-verify
选项来跳过钩子:
¥Most Git commands include a -n/--no-verify
option to skip hooks:
sh
git commit -m "..." -n # Skips Git hooks
对于没有此标志的命令,请使用 HUSKY=0 暂时禁用钩子:
¥For commands without this flag, disable hooks temporarily with HUSKY=0:
shell
HUSKY=0 git ... # Temporarily disables all Git hooks
git ... # Hooks will run again
用于多个命令
¥For multiple commands
要在较长时间内禁用钩子(例如,在 rebase/merge 期间):
¥To disable hooks for an extended period (e.g., during rebase/merge):
shell
export HUSKY=0 # Disables all Git hooks
git ...
git ...
unset HUSKY # Re-enables hooks
用于 GUI 或全局
¥For a GUI or Globally
要在 GUI 客户端或全局禁用 Git 钩子,请修改 husky 配置:
¥To disable Git hooks in a GUI client or globally, modify the husky config:
sh
# ~/.config/husky/init.sh
export HUSKY=0 # Husky won't install and won't run hooks on your machine
CI 服务器和 Docker
¥CI server and Docker
要避免在 CI 服务器或 Docker 中安装 Git Hooks,请使用 HUSKY=0
。例如,在 GitHub Actions 中:
¥To avoid installing Git Hooks on CI servers or in Docker, use HUSKY=0
. For instance, in GitHub Actions:
yml
# https://docs.github.com/en/actions/learn-github-actions/variables
env:
HUSKY: 0
如果仅安装 dependencies
(而不是 devDependencies
),"prepare": "husky"
脚本可能会失败,因为不会安装 Husky。
¥If installing only dependencies
(not devDependencies
), the "prepare": "husky"
script may fail because Husky won't be installed.
你有多种解决方案。
¥You have multiple solutions.
修改 prepare
脚本以永不失败:
¥Modify the prepare
script to never fail:
json
// package.json
"prepare": "husky || true"
你仍会在输出中收到 command not found
错误消息,这可能会造成混淆。要使其保持静默,请创建 .husky/install.mjs
:
¥You'll still get a command not found
error message in your output which may be confusing. To make it silent, create .husky/install.mjs
:
js
// Skip Husky install in production and CI
if (process.env.NODE_ENV === 'production' || process.env.CI === 'true') {
process.exit(0)
}
const husky = (await import('husky')).default
console.log(husky())
然后,在 prepare
中使用它:
¥Then, use it in prepare
:
json
"prepare": "node .husky/install.mjs"
无需提交即可测试钩子
¥Testing Hooks Without Committing
要测试钩子,请将 exit 1
添加到钩子脚本以中止 Git 命令:
¥To test a hook, add exit 1
to the hook script to abort the Git command:
shell
# .husky/pre-commit
# Your WIP script
# ...
exit 1
shell
git commit -m "testing pre-commit code"
# A commit will not be created
项目不在 Git 根目录中目录
¥Project Not in Git Root Directory
出于安全原因,Husky 不会安装在父目录 (../
) 中。但是,你可以在 prepare
脚本中更改目录。
¥Husky doesn't install in parent directories (../
) for security reasons. However, you can change the directory in the prepare
script.
考虑这个项目结构:
¥Consider this project structure:
.
├── .git/
├── backend/ # No package.json
└── frontend/ # Package.json with husky
像这样设置你的准备脚本:
¥Set your prepare script like this:
json
"prepare": "cd .. && husky frontend/.husky"
在你的钩子脚本中,将目录更改回相关子目录:
¥In your hook script, change the directory back to the relevant subdirectory:
shell
# frontend/.husky/pre-commit
cd frontend
npm test
非 shell 钩子
¥Non-shell hooks
为了运行需要使用脚本语言的脚本,请对每个适用的钩子使用以下模式:
¥In order to run scripts that require the use of a scripting language, use the following pattern for each applicable hook:
(使用钩子 pre-commit
和 NodeJS 的示例)
¥(Example using hook pre-commit
and NodeJS)
为钩子创建一个入口点:
¥Create an entrypoint for the hook:
shell.husky/pre-commit
在文件中添加以下内容
¥In the file add the following
shellnode .husky/pre-commit.js
在
.husky/pre-commit.js
中¥in
.husky/pre-commit.js
javascript// Your NodeJS code // ...
Bash
钩子脚本需要符合 POSIX 标准以确保最佳兼容性,因为并非每个人都拥有 bash
(例如 Windows 用户)。
¥Hook scripts need to be POSIX compliant to ensure best compatibility as not everyone has bash
(e.g. Windows users).
话虽如此,如果你的团队不使用 Windows,你可以通过这种方式使用 Bash:
¥That being said, if your team doesn't use Windows, you can use Bash this way:
shell
# .husky/pre-commit
bash << EOF
# Put your bash script inside
# ...
EOF
Node 版本管理器和 GUI
¥Node Version Managers and GUIs
如果你在通过版本管理器安装 Node 的 GUI 中使用 Git 钩子(如 nvm
、n
、fnm
、asdf
、volta
等),你可能会因为 PATH
环境变量问题而遇到 command not found
错误。
¥If you're using Git hooks in GUIs with Node installed via a version manager (like nvm
, n
, fnm
, asdf
, volta
, etc...), you might face a command not found
error due to PATH
environment variable issues.
了解 PATH
和版本管理器
¥Understanding PATH
and Version Managers
PATH
是一个包含目录列表的环境变量。你的 shell 会在这些目录中搜索命令。如果找不到命令,你会收到一条 command not found
消息。
¥PATH
is an environment variable containing a list of directories. Your shell searches these directories for commands. If it doesn't find a command, you get a command not found
message.
在 shell 中运行 echo $PATH
以查看其内容。
¥Run echo $PATH
in a shell to view its contents.
版本管理器的工作方式:
¥Version managers work by:
将初始化代码添加到你的 shell 启动文件(
.zshrc
、.bashrc
等)中,该文件在你每次打开终端时运行。¥Adding initialization code to your shell startup file (
.zshrc
,.bashrc
, etc.), which runs each time you open a terminal.将 Node 版本下载到主文件夹中的目录中。
¥Downloading Node versions to a directory in your home folder.
例如,如果你有两个 Node 版本:
¥For example, if you have two Node versions:
shell
~/version-manager/Node-X/node
~/version-manager/Node-Y/node
打开终端初始化
¥Opening a terminal initializes the version manager, which picks a version (say Node-Y
) and prepends its path to PATH
:
shell
echo $PATH
# Output
~/version-manager/Node-Y/:...
现在,node 指的是 Node-Y
。切换到 Node-X
会相应地更改 PATH
:
¥Now, node refers to Node-Y
. Switching to Node-X
changes PATH
accordingly:
shell
echo $PATH
# Output
~/version-manager/Node-X/:...
出现此问题的原因是,在终端外启动的 GUI 不会初始化版本管理器,导致 PATH
没有 Node 安装路径。因此,来自 GUI 的 Git 钩子经常会失败。
¥The issue arises because GUIs, launched outside a terminal, don't initialize the version manager, leaving PATH
without the Node install path. Thus, Git hooks from GUIs often fail.
解决方案
¥Solution
Husky 在每个 Git 钩子之前获取 ~/.config/husky/init.sh
源。在此处复制你的版本管理器初始化代码以确保它在 GUI 中运行。
¥Husky sources ~/.config/husky/init.sh
before each Git hook. Copy your version manager initialization code here to ensure it runs in GUIs.
nvm
示例:
¥Example with nvm
:
shell
# ~/.config/husky/init.sh
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
或者,如果你的 shell 启动文件快速且轻量,请直接获取它:
¥Alternatively, if your shell startup file is fast and lightweight, source it directly:
shell
# ~/.config/husky/init.sh
. ~/.zshrc
手动设置
¥Manual setup
Git 需要配置,husky 需要在 .husky/
中设置文件。
¥Git needs to be configured and husky needs to setup files in .husky/
.
在你的 repo 中运行一次 husky
命令。理想情况下,将其包含在 package.json
中的 prepare
脚本中,以便在每次安装后自动执行(推荐)。
¥Run the husky
command once in your repo. Ideally, include it in the prepare
script in package.json
for automatic execution after each install (recommended).
json
{
"scripts": {
"prepare": "husky"
}
}
json
{
"scripts": {
"prepare": "husky"
}
}
json
{
"scripts": {
// Yarn doesn't support prepare script
"postinstall": "husky",
// Include this if publishing to npmjs.com
"prepack": "pinst --disable",
"postpack": "pinst --enable"
}
}
json
{
"scripts": {
"prepare": "husky"
}
}
运行 prepare
一次:
¥Run prepare
once:
sh
npm run prepare
sh
pnpm run prepare
sh
# Yarn doesn't support `prepare`
yarn run postinstall
sh
bun run prepare
在 .husky/
目录中创建一个 pre-commit
文件:
¥Create a pre-commit
file in the .husky/
directory:
shell
# .husky/pre-commit
npm test
shell
# .husky/pre-commit
pnpm test
shell
# .husky/pre-commit
yarn test
sh
# .husky/pre-commit
bun test