Git Commit 质量门禁流程

Pre-commit Hook 完整流水线 · .husky/pre-commit · 更新于 2026-02-08

流水线总览

每次 git commit 时,Husky pre-commit hook 会依次执行以下 6 个检查步骤。任一步骤失败(exit 1)将阻断 commit。

1
JavaScript 语法检查 ~2s 阻断
扫描所有 staged 的 JS 文件,检查语法错误(SyntaxError)。不涉及代码风格,只检查能否被 Node.js 解析。
scripts/tools/check-syntax.js
2
错误码定义验证 ~1s 条件触发
仅在 shared/errors/ 有变更时触发。验证错误码唯一性、HTTP 状态码映射正确性,并自动更新错误码文档。
scripts/validate-error-codes.js → scripts/generate-error-docs.js
触发条件: git diff --cached --name-only | grep "shared/errors/"
3
国际化硬编码检查 ~3s 条件触发
仅在前端 .ts/.tsx/.js 文件变更时触发。扫描硬编码的中文字符串,要求使用 next-intluseTranslations()。支持白名单豁免。
scripts/check-i18n.js --staged --strict --whitelist
触发条件: git diff --cached --name-only | grep "^frontend/.*\.(ts|tsx|js)$"
白名单: scripts/i18n-whitelist.json
4
统一错误码使用审计 ~3s 条件触发
仅在后端 .js 文件变更时触发。扫描 throw new Error()、硬编码 res.status(4xx/5xx) 等应迁移到统一错误码系统的模式。CI 模式忽略注释中的代码。
scripts/audit-error-usage.js --ci
触发条件: git diff --cached --name-only | grep "^backend/.*\.js$"
扫描目录: backend/api/, backend/services/, backend/auth/, backend/jobs/
5
代码格式与规范检查 (lint-staged) ~5s 阻断
对所有 staged 文件运行 ESLint + Prettier。仅处理 staged 部分(增量),不全量扫描。内存限制 4GB。
npx lint-staged (NODE_OPTIONS=--max-old-space-size=4096)
6
测试覆盖率门禁 ~2-5min 阻断
运行后端 + 前端完整 Jest 测试套件并检查覆盖率。低于阈值自动阻断 commit。
cd backend && npx jest --coverage
cd frontend/web_app && npx jest --coverage

覆盖率阈值配置

阈值由各子项目的 jest.config.jscoverageThreshold 字段控制。Jest 内置机制:低于阈值时进程以非零码退出。

项目配置文件BranchesFunctionsLinesStatements
后端 (Backend) backend/jest.config.js 60%60%60%60%
前端 (Frontend) frontend/web_app/jest.config.js 70%70%70%70%

覆盖率收集范围

项目包含排除
后端 api/**/*.js, auth/**/*.js, services/**/*.js, database/**/*.js database/migrations/**, node_modules, logs, uploads
前端 src/**/*.{js,jsx,ts,tsx} *.d.ts, types/**, layout.tsx, loading.tsx, error.tsx, not-found.tsx

跳过方式

方法 1: 仅跳过覆盖率(推荐)

SKIP_COVERAGE=1 git commit -m "wip: work in progress"

只跳过第 6 步覆盖率检查,前 5 步(语法、错误码、i18n、审计、lint)仍然执行。适合开发中的 WIP commit。

方法 2: 跳过所有 hook

git commit --no-verify -m "hotfix: emergency"

跳过整个 pre-commit hook。仅限紧急情况使用。

不建议频繁跳过

覆盖率门禁的目的是确保每次提交不会引入未测试的代码。频繁使用 SKIP_COVERAGE=1 会导致技术债积累。如果发现经常需要跳过,应该反思是否需要补充测试。

相关文件一览

用途文件路径
Pre-commit Hook 主文件.husky/pre-commit
Husky 配置.husky/_/husky.sh
语法检查脚本scripts/tools/check-syntax.js
错误码验证scripts/validate-error-codes.js
错误码文档生成scripts/generate-error-docs.js
i18n 检查脚本scripts/check-i18n.js
i18n 白名单scripts/i18n-whitelist.json
错误使用审计scripts/audit-error-usage.js
lint-staged 配置package.json (lint-staged 字段)
后端 Jest 配置backend/jest.config.js
前端 Jest 配置frontend/web_app/jest.config.js

常见问题

Q: Commit 被阻断但不知道哪一步失败了?

每一步都有对应的 emoji 前缀输出。查看终端输出中最后一个 emoji 标记即可定位:

Q: 覆盖率检查太慢怎么办?

完整覆盖率检查需要 2-5 分钟。如果觉得开发节奏受影响:

Q: 覆盖率阈值想调整?

修改对应的 jest.config.jscoverageThreshold.global 字段即可。Hook 本身不做数值判断,完全依赖 Jest 内置机制。

设计原则