pre-commit 钩子必须放在 .git/hooks/pre-commit 路径且无后缀、有执行权限;需用 git diff --cached 精准过滤待提交的 JS/TS 文件,配合 npx eslint 检查并确保失败时退出码为 1;推荐用 npm prepare 软链复用脚本。

pre-commit 钩子文件放哪才生效
Git 只认 .git/hooks/pre-commit 这个路径的可执行文件,其他位置(比如项目根目录下的 pre-commit 或 scripts/pre-commit)默认不会触发。
常见错误是把脚本放在别处、加了 .sh 后缀、或没给执行权限——Git 会静默跳过,不报错也不运行。
- 进项目根目录,执行
chmod +x .git/hooks/pre-commit - 确保文件没有后缀(必须叫
pre-commit,不是pre-commit.sh) - 如果用
#!/usr/bin/env bash开头,确认系统有bash且路径正确(macOS 默认/bin/bash,新版可能受限) - Windows 用户注意:WSL 下用 Linux 路径规则;Git for Windows 自带 Bash,但要用
#!/bin/sh更稳妥
用 shell 脚本调用 ESLint / Prettier 最简写法
不用装额外工具链,纯 shell 就能跑检查。关键是捕获「本次提交要提交的 JS 文件」,而不是扫全量目录。
Git 提供 git diff --cached --name-only --diff-filter=ACM 来列出即将提交的新增/修改/重命名文件,过滤出 .js 和 .ts 即可。
- 在
.git/hooks/pre-commit里写:
#!/bin/sh
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$\|\.ts$')
if [ -n "$FILES" ]; then
npx eslint --quiet $FILES
if [ $? -ne 0 ]; then
echo "ESLint 失败,请修复后再提交"
exit 1
fi
fi
-
--quiet避免输出大量警告干扰判断;真正阻断提交的是非零退出码 - 别用
eslint .—— 会检查 node_modules 和历史文件,慢且误报多 - 如果项目没装
eslint到本地node_modules,npx会 fallback 到全局,但行为不稳定,建议统一用npm exec eslint(npm v7+)
pre-commit 退出码为 1 却没拦住提交?
最常踩的坑:脚本里某条命令失败,但没被检测到,整体仍返回 0。
比如写了 eslint file.js; echo "done",即使 ESLint 报错,echo 成功导致整个脚本退出码是 0,Git 就当通过了。
- 每条关键检查后加
|| exit 1,或开头加set -e(但注意它对管道和条件语句有陷阱) - 避免无意义的
echo、printf放在检查逻辑后面,它们会覆盖前一条命令的退出码 - 调试时在脚本末尾加
echo "exit code: $?",提交前手动运行.git/hooks/pre-commit看输出 - Git 不捕获 stdout/stderr,所以日志得靠
echo打到终端,否则你根本不知道它跑没跑
想让团队共用 pre-commit,又不想手动复制文件
直接硬拷贝 pre-commit 到每个人 .git/hooks/ 下,协作成本高、易不同步、还可能被 IDE 自动删掉(比如 VS Code 的 Git 插件)。
更稳的方式是用 npm prepare 脚本自动软链,或借助 husky 这类工具——但它底层仍是生成并 chmod 那个文件,只是帮你省了手动手续。
- 推荐轻量方案:在
package.json里加
"scripts": {
"prepare": "ln -sf ../../scripts/pre-commit .git/hooks/pre-commit || cp scripts/pre-commit .git/hooks/"
}
- 运行
npm install后自动部署钩子;Windows 用户用cp分支兜底 - 把真实脚本放在
scripts/pre-commit,方便 git commit、code review、CI 复用逻辑 - 别把
.git/hooks/加进版本库——Git 不跟踪这个目录,而且不同用户钩子可能需微调(比如本地路径)
钩子本质是本地脚本,再怎么封装也绕不开「每个开发者机器上得有对应依赖」这一层。Node 版本、全局工具、甚至 shell 类型(zsh/bash),都可能让同一份脚本表现不一。


















