Husky 8+是当前最稳妥选择,旧版不兼容现代工作流;必须执行npx husky init初始化钩子文件并注入prepare脚本,否则钩子静默失效;pre-commit推荐用npx lint-staged而非全量npm run lint;commit-msg需正确传参$1;CI中应设HUSKY=0禁用钩子。

Husky 8+ 是目前最稳妥的选择,旧版 Husky(^4 或 ^7)配置方式已不兼容现代 npm/yarn 工作流,强行沿用会导致钩子静默失效。
安装后没生效?检查 husky init 是否真执行了
很多人手动运行 npm install husky --save-dev 就以为完事,但 Husky 8+ 不再自动创建钩子文件——必须显式初始化:
-
npx husky init才会生成.husky/pre-commit等模板文件,并在package.json中注入"prepare"脚本 - 若跳过这步,
git commit时钩子根本不会触发,控制台也无任何提示(不是报错,是彻底静默) - 确认是否生效:执行
ls -la .husky/,应看到至少一个带执行权限的 shell 文件(如-rwxr-xr-x 1 user staff 123 Apr 10 15:22 pre-commit)
pre-commit 钩子里跑 eslint 或 lint-staged 的关键区别
直接在 .husky/pre-commit 里写 npm run lint 看似简单,但容易踩两个坑:
- 它会对整个项目扫描,而非仅暂存文件,耗时长、易误报;推荐改用
npx lint-staged,它只处理git add过的文件 -
lint-staged需要额外配置lint-staged.config.js或package.json#lint-staged,否则默认不生效 - 若坚持用
eslint,务必加--cache参数(npx eslint . --ext .js,.ts --cache),否则每次提交都全量扫描
为什么 commit-msg 钩子校验失败却不阻断提交?
常见错误是把 commitlint 命令写成异步调用或漏传参数:
- 正确写法:
npx --no-install commitlint --edit $1——$1是 Git 传入的临时消息文件路径,缺了就无法读取内容 - 错误写法:
npx commitlint -E $1(-E是旧版参数,Husky 8+ 下已废弃)或npx commitlint(没传路径,校验空字符串) - 如果用了
simple-git-hooks或ghooks,它们的commit-msg传参方式不同,混用会导致校验逻辑失效
CI 环境下 Husky 钩子意外触发怎么办
Husky 默认在 CI 中也会启用钩子,但多数 CI(如 GitHub Actions、GitLab CI)不需要本地校验逻辑,反而拖慢流程甚至失败:
- 最简方案:在 CI 脚本开头加
export HUSKY=0,Husky 会主动跳过所有钩子 - 不要依赖
--no-verify,它只对单次命令有效,CI 脚本里难以全覆盖 - 若用 pnpm,还需注意
pnpm install默认不执行prepare,需显式加--recursive或在 CI 中补pnpm exec husky install
真正容易被忽略的是:Husky 的钩子脚本本质是 shell 脚本,它继承的是当前终端的环境变量,而不是 package.json 中定义的 scripts 所用的 Node.js 版本。如果你本地装了多个 Node 版本(比如用 nvm 切换),而 .husky/pre-commit 里调用的 npx 指向的是系统默认 Node,就可能因版本不一致导致 eslint 报错或 lint-staged 找不到插件。


















