pre-commit hook 默认不自动启用,需确保文件存在、有执行权限、正确解释器声明、无Windows换行符、用绝对路径调用命令,且避免git add引发递归;若要只警告不阻断,须保证脚本最终返回0。

pre-commit hook 为什么没触发?
Git 的 pre-commit hook 默认不自动启用,它只是个可执行文件,放在 .git/hooks/pre-commit 但没权限或没写对逻辑,就完全静默失效。
- 确保文件存在且有执行权限:
chmod +x .git/hooks/pre-commit - 脚本第一行必须是正确的解释器声明,比如
#!/bin/sh或#!/usr/bin/env bash,Windows 换行符(CRLF)会导致解析失败 - Git 不会帮你加载 shell 配置(如
~/.bashrc),PATH 可能不含你期望的命令(比如prettier),建议用绝对路径调用二进制,或显式设置 PATH - hook 中执行
git add会引发递归调用(再次触发pre-commit),导致死循环或报错fatal: Unable to create '/path/.git/index.lock'
怎么让 pre-commit 检查代码格式但不阻断提交?
默认行为是:检查失败就退出非零码,Git 直接中止提交。想“只警告不拦截”,就得自己控制退出码——只要最后返回 0,Git 就认为通过。
- 用
prettier --check src/**.ts判断是否格式错误,但别直接让它决定退出码 - 捕获输出再处理:
if ! prettier --check "src/**.ts" 2>/dev/null; then echo "⚠️ 格式有问题,已自动修复"; prettier --write "src/**.ts"; fi - 注意:修复后文件已修改,但 Git 并不知道,
git status里仍是“未暂存”,得手动git add才能提交——这恰恰是防止误提交脏代码的关键设计
husky 和直接写 .git/hooks/pre-commit 有啥区别?
本质都是跑 pre-commit 脚本,但 husky 解决了三个实际痛点:跨团队共享、hook 版本化、Node.js 环境隔离。
- 纯
.git/hooks/文件不会被 git commit 提交,新成员 clone 后 hook 丢失;husky 把配置写进package.json的husky字段,配合preparescript 自动安装 - husky 启动时会重置环境变量,确保
node和npx可用,而原生 hook 依赖系统 PATH,CI 环境容易找不到eslint - 如果你项目不用 npm/yarn/pnpm,或者 CI 流程禁止安装依赖,那直接写
.git/hooks/pre-commit更轻量、更可控
pre-commit 里调用 eslint 或 prettier 很慢怎么办?
慢通常是因为扫描了 node_modules、.git、dist 这类不该检查的目录,或每次启动完整 Node.js 环境。
- 加
--ext限定扩展名:eslint --ext .js,.ts src/,避免遍历整个工作区 - 用
prettier --list-different替代--check,前者只输出不合规文件名,开销更低 - 在 CI 中禁用 hook(
git commit --no-verify),把格式检查交给单独的 job,避免干扰本地开发流速 - 注意:不要在 hook 里启动 watch 模式或后台进程,Git 会等它结束,卡住终端
git add 再测试 hook 行为,才接近真实场景。


















