本文目录导读:

常用 Git 钩子与检查时机
| 钩子类型 | 触发时机 | 适用场景 |
|---|---|---|
pre-commit |
执行 git commit 之前 |
检查代码格式、禁止提交调试代码、运行静态分析 |
commit-msg |
用户输入提交信息后 | 检查提交信息格式(如是否包含 issue 编号) |
pre-push |
执行 git push 之前 |
运行单元测试、集成测试、安全扫描、覆盖率检查 |
pre-receive / update |
服务端接收推送时 | 强制分支保护规则、合规性检查 |
常见的可靠性门禁检查项
1 代码风格与静态分析
#!/bin/sh
# pre-commit 示例:运行 linter 和格式化检查
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Linting failed. Please fix issues before commit."
exit 1
fi
# 检查是否有调试代码(如 console.log 在非开发环境)
if git diff --cached | grep -E "console\.log|debugger" > /dev/null; then
echo "❌ Found debugger/console.log in staged changes. Remove them first."
exit 1
fi
2 单元测试与覆盖率
#!/bin/sh
# pre-push 示例:运行单元测试并检查覆盖率
npm test -- --coverage
# 提取覆盖率数据(假设 Jest 输出到 coverage/lcov-report/index.html)
COVERAGE=$(node -e "const cov = require('./coverage/coverage-summary.json'); console.log(cov.total.lines.pct);")
# 设置最低覆盖率门限(80%)
THRESHOLD=80
if (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then
echo "❌ Code coverage is ${COVERAGE}%, which is below the ${THRESHOLD}% threshold."
exit 1
fi
3 安全漏洞扫描
#!/bin/sh
# pre-push 示例:运行 npm audit 或安全插件
npm audit --audit-level=high
if [ $? -ne 0 ]; then
echo "❌ Security audit failed. Fix vulnerabilities before pushing."
exit 1
fi
4 构建验证
#!/bin/sh
# pre-push 示例:确保代码可以编译或构建成功
npm run build
if [ $? -ne 0 ]; then
echo "❌ Build failed. Fix compilation errors before pushing."
exit 1
fi
管理多个钩子与工具链(推荐)
使用 Husky + lint-staged 是目前最流行的方式:
安装
npm install husky lint-staged --save-dev npx husky init
配置 package.json
{
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.md": ["prettier --write"]
}
}
配置钩子 .husky/pre-commit
#!/bin/sh npx lint-staged npx tsc --noEmit # TypeScript 类型检查
配置钩子 .husky/pre-push
#!/bin/sh npm run test:coverage npm run audit npm run build
服务端强制门禁(服务端钩子)
如果团队需要不可绕过的门禁,可以在远程 Git 仓库(如 GitLab/GitHub Self-hosted)配置:
服务端 pre-receive 钩子(Git 原生)
#!/bin/bash
# 强制:每次 push 都必须包含测试通过记录(如 CI pipeline 传递的 token)
while read oldrev newrev refname; do
# 检查是否在分支保护范围内
if [ "$refname" = "refs/heads/main" ]; then
# 实际生产环境:调用外部 CI 系统 API 确认构建状态
echo "❌ Direct push to main is blocked. Use merge request + CI pipeline."
exit 1
fi
done
更推荐的做法:结合 CI/CD 系统
- GitLab CI / GitHub Actions:在 Pipeline 中定义可靠性门禁,仅当通过后才允许合并 PR。
- Branch Protection Rules:设置“需要状态检查通过”才能合并。
绕过风险与最佳实践
| 风险 | 解决方案 |
|---|---|
用户可以 git commit --no-verify 跳过钩子 |
服务端钩子(pre-receive)不可绕过 |
| 钩子运行耗时过长影响开发体验 | 使用 lint-staged 仅检查暂存区文件 |
| 依赖安装失败导致钩子无效 | CI 中再次执行相同检查作为双重保障 |
| 不同开发环境差异导致误判 | 使用 Docker 容器化环境运行检查 |
完整示例脚本(pre-push)
#!/bin/bash
# .husky/pre-push - 综合可靠性门禁
echo "🔍 Running reliability gate checks..."
# 1. 运行单元测试并生成覆盖率报告
npm test -- --coverage --silent
TEST_EXIT=$?
if [ $TEST_EXIT -ne 0 ]; then
echo "❌ Unit tests failed. Fix before pushing."
exit 1
fi
# 2. 检查代码覆盖率(从 coverage-summary.json 解析)
COVERAGE=$(node -e "
try {
const c = require('./coverage/coverage-summary.json');
const lines = c.total.lines.pct;
const branches = c.total.branches.pct;
const minLines = process.argv[1] || 85;
console.log(JSON.stringify({ lines, branches }));
} catch(e) {
console.log('{}');
}
" 2>/dev/null)
LINES=$(echo "$COVERAGE" | node -e "const d = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(d.lines || 0);" 2>/dev/null)
THRESHOLD=85
if (( $(echo "$LINES < $THRESHOLD" | bc -l 2>/dev/null) )); then
echo "❌ Line coverage ${LINES}% < ${THRESHOLD}% threshold."
exit 1
fi
# 3. 安全扫描(仅检查 high 以上级别)
npm audit --audit-level=high 2>&1 | tail -1 | grep -q "found 0 vulnerabilities"
if [ $? -ne 0 ]; then
echo "❌ High/critical vulnerabilities found. Fix before push."
exit 1
fi
# 4. 生产构建验证
npm run build 2>/dev/null
if [ $? -ne 0 ]; then
echo "❌ Build failed."
exit 1
fi
echo "✅ All reliability checks passed. Push allowed."
exit 0
可靠性门禁检查核心思路
命令行:git commit --no-verify? → 本地钩子很容易绕过
CI/CD:merge request pipeline → 最可靠的门禁位置
服务端钩子:pre-receive → 不可绕过,但管理成本高
最佳组合:本地钩子 + CI 门禁 → 既快又安全
关键点:本地钩子防止低质量代码流出,CI 门禁作为最终防线,服务端保护规则封死绕过路径。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播