← 返回题目列表

Python 项目为什么要用 pre-commit?它和 CI 有什么区别?

高频 中等 第 13 / 27 题 更新于 2026/07/31
pre-commitCI代码质量Git Hooks

简化版

pre-commit 用 Git hooks 在提交前自动运行格式化、lint、类型检查、密钥扫描等任务,提前拦截低级问题。CI 是远端流水线,负责最终验证;pre-commit 更靠前、更快,CI 更权威、更完整,两者应配合使用。

详细版

常见 .pre-commit-config.yaml 会配置 ruff、black、mypy、detect-secrets 等工具。开发者提交前自动执行,失败就阻止提交。

pre-commit install
pre-commit run --all-files

它不能替代 CI,因为本地 hook 可能没安装、被跳过或环境不同。CI 仍要跑测试和质量检查。面试重点是:把质量检查前移,提高反馈速度,但最终门禁仍在 CI。

完整版教学

一、为什么需要提交前检查

如果格式错误、未排序 import、明显 lint 问题都等 CI 才发现,反馈会慢。pre-commit 把这些问题在提交前解决,减少无效 CI 和代码审查噪音。

编辑 -> git commit -> pre-commit 检查 -> CI -> review

越早发现问题,修复成本越低。

二、pre-commit 能跑什么

它可以跑格式化、lint、类型检查、YAML/JSON 校验、换行检查、大文件检查、密钥扫描等。

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    hooks:
      - id: ruff
      - id: ruff-format

每个 hook 有固定版本,团队结果更一致。

三、和 CI 的区别

pre-commit 在本地运行,快但不绝对可信;CI 在远端标准环境运行,慢一点但权威。

维度pre-commitCI
位置本地提交前远端合并前
速度较慢
可信度可被跳过更权威
范围快速检查完整测试/构建

pre-commit 是第一道筛子,CI 是最终门禁。

四、为什么要固定版本

如果每个人本地工具版本不同,格式化结果可能来回变。pre-commit 配置里固定 hook rev,可以让团队统一。

dev A ruff 0.x
dev B ruff 1.x
格式规则不同 -> diff 抖动

固定版本后,升级工具变成一次明确变更。

五、什么不适合放 pre-commit

太慢的全量集成测试、依赖外部服务的测试、需要大量数据的检查不适合每次 commit 都跑。否则开发者会频繁跳过 hook。

适合: 1-10 秒快速检查
不适合: 10 分钟端到端测试

慢任务放 CI,或者手动触发。

六、工程落地要注意什么

README 要写安装命令,CI 也要跑同样检查。否则有人没装 hook,问题仍会进仓库。可以在 CI 中执行 pre-commit run --all-files 保持一致。

pre-commit run --all-files

不要把 hook 配成“只有你本机能跑”,要保证跨平台和依赖可安装。

七、和 Python 工具链怎么配合

Python 项目里常见组合是 ruff 负责 lint 和格式,mypy/pyright 负责类型,pytest 负责测试,detect-secrets/gitleaks 负责密钥扫描。pre-commit 负责把这些命令串到提交流程里。

ruff -> formatting/lint
mypy -> type check
pytest -> tests
detect-secrets -> secret scan

不要为了“工具多”而堆工具,重点是每个 hook 的职责清楚、速度可接受。

八、升级和维护

pre-commit 配置不是写完就不管。工具版本要定期升级,可以用 pre-commit autoupdate,升级后在 CI 跑全量检查。大版本升级可能带来大量格式变化,最好单独提交,避免和业务代码混在一起。

pre-commit autoupdate
pre-commit run --all-files

这样 review 时能区分“工具升级导致的机械修改”和真实业务改动。

九、常见误区与追问

  • 误区:用了 pre-commit 就不用 CI。 本地 hook 可跳过,CI 仍是最终门禁。
  • 误区:所有测试都放 pre-commit。 太慢会影响开发体验,应该分层。
  • 误区:hook 不用固定版本。 不固定会导致团队结果不一致。
  • 追问:如何临时跳过? Git 支持 --no-verify,但不应常用。
  • 追问:pre-commit 能扫密钥吗? 可以配 detect-secrets、gitleaks 等。
  • 追问:格式化失败怎么办? 很多 hook 会自动修改文件,重新 add/commit。
  • 追问:CI 怎么复用?pre-commit run --all-files

十、加强记忆

pre-commit 记成“提交前的快速质量闸”。它把格式、lint、密钥扫描前移,减少低级问题进入 review;CI 负责标准环境下完整验证。快检查放本地,慢检查放 CI,两者配合才舒服。