pre-commit用于本地快速拦截,post-receive用于服务端部署;前者禁用耗时操作和.git目录外依赖,后者须通过--work-tree配合裸仓库执行checkout,并统一用husky或setup-hooks.sh管理同步。
能,但必须分清客户端和服务端职责,否则上线即崩。 pre-commit 负责本地拦截,post-receive 才能触发部署,两者混用或错放位置是绝大多数失败案例的根源。
它只运行在开发者本地,执行时间必须短(理想
prettier --check 或 eslint --quiet 扫描暂存区文件(git diff --cached --name-only 获取)git diff --cached -U0 | grep -q "password|API_KEY" && echo "⚠️ 检测到疑似密钥" && exit 1
commit-msg 单独处理,别塞进 pre-commit
pre-push 或 CI它在 git push 发出前触发,适合执行稍重但仍有意义的拦截,比如:
npm test -- --changedSince=origin/main
! npm ls &> /dev/null && echo "❌ node_modules 缺失" && exit 1
git status --porcelain | grep ".env$" && echo "❌ .env 文件未提交或被忽略" && exit 1
#!/usr/bin/env bash 开头,避免 /bin/bash 路径失效它运行在裸仓库(bare repo)里,没有工作目录,git checkout 会失败。正确做法是:
git --work-tree=/path/to/site --git-dir=/path/to/bare.git checkout -f
chmod +x 权限,且脚本第一行必须是 #!/usr/bin/env bash
2>&1 >> /var/log/deploy.log 加到命令末尾,否则失败时完全看不到原因真正难的不是写脚本,而是让所有成员的 .git/hooks/ 同步更新——没人会手动复制,也没人记得 chmod +x。用 husky 或自建 setup-hooks.sh 注册到 package.json postinstall 才是可持续方案。