1. 先搞清楚报错的来龙去脉
1.1 husky 是什么,pre-commit 又是什么
先说结论:这条报错不是 git 本身坏了,而是 git 在提交时触发了一个“钩子”,钩子里的检查脚本没跑通,返回了非 0 的退出码,git 出于安全考虑,直接终止了这次 commit。
git 的钩子机制(hooks)是原生就有的,它会在特定时机执行一些脚本,比如 commit 之前、push 之前、merge 之后等等。钩子文件默认放在 .git/hooks 目录下,里面是一堆带 .sample 后缀的示例脚本,正常情况下它们不会被触发。问题是手写钩子太麻烦,不同成员的开发环境复制起来也容易丢,于是 husky 就出现了。
husky 做的事情很简单:把钩子的管理从 .git 目录里解放出来,放在项目根目录的 .husky 文件夹下,并且可以随着仓库一起提交,团队成员拉下来代码之后通过 npm install 自动完成 hook 的注册和更新。.husky/pre-commit 文件就是我们今天要排查的主角,它一般长这样:
bash复制#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
npx lint-staged
这个脚本的意思是:在你执行 git commit 之后、真正生成提交之前,先跑一遍代码检查。如果检查不过,脚本以非 0 状态退出,git 就会抛出开头那条 husky - pre-commit hook exited with code 1。
这条报错适合谁看?被它拦在提交门外、急着交付又不知道从哪下手的开发同学都适合。我按自己的排障习惯把问题拆成了五类高频原因,照着查基本就能定位。
1.2 报错里其实藏着好几条线索
很多同学一看到 exited with code 1 就慌,其实这个提示只说了一半的信息。真实的排查线索往往藏在它上面的几行输出里。
举个典型的完整报错:
bash复制git commit -m "feat: add login page"
✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications...
✖ Some of your tasks use `git commit` args (e.g. `--no-verify`)
which will be ignored. Run without args to fix this.
husky - pre-commit hook exited with code 1 (error)
注意看,报错的前半段是 lint-staged 的输出,后半段才是 husky 的退出信息。如果只看最后一行,你会觉得毫无头绪;但把完整输出拉出来,问题往往已经写在里面了。
还有一种更隐蔽的情况:husky 的报错信息里只有一行 error: cannot run .husky/pre-commit: No such file or directory,这通常是文件权限或者 hooksPath 配置错了。所以我的习惯是,遇到这类问题先别急着搜报错原文,先把完整日志存一份,再往下走排查流程。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 高频原因拆解:为什么你的 commit 会被拦下来
2.1 第一大类:代码检查真的没过
最常见的场景就是 ESLint 或 Prettier 检查不通过。很多团队会在 pre-commit 阶段跑 eslint --fix,但 --fix 只能处理那些能自动修复的规则,遇到不能自动修的(比如变量命名规范、禁止使用 any、复杂度超限),就只能人工改。
你可能会问:我本地明明跑得好好的,怎么提交的时候就不行了?这里有一个非常常见的认知盲区:本地编辑器可能带了各种插件,帮你自动修复了大部分问题,所以你在编辑器里觉得“没事了”,但 commit 时执行的是命令行环境里的全新检查,它不带任何编辑器状态,严格按规则来。
再有一种情况:项目大了之后,lint-staged 默认可能只检查暂
