pre-commit钩子通过pip-compile比对requirements.in与生成的requirements.txt是否一致来检查依赖更新,若不一致则拒绝提交;poetry项目则用poetry check校验pyproject.toml与poetry.lock一致性。

Git钩子本身不能直接检查Python依赖更新,因为依赖版本变化发生在requirements.txt或pyproject.toml里,而Git只感知文件内容变更——关键在于:你得让钩子主动比对“当前锁文件”和“重新生成的锁文件”是否一致。
pre-commit 钩子中用 pip-compile 检查 requirements.in 是否过期
这是最常见且可靠的模式:项目用requirements.in声明顶层依赖,靠pip-compile生成requirements.txt。钩子要做的就是运行一次pip-compile,再用git diff --quiet判断输出是否干净。
- 确保已安装
pip-tools:pip install pip-tools - 在
.pre-commit-config.yaml中添加:
repos:
- repo: https://github.com/jazzband/pip-tools
rev: 7.4.1
hooks:
- id: pip-compile
args: [--upgrade, --generate-hashes, --output-file=requirements.txt]
files: ^requirements\.in$注意:files正则只触发requirements.in变更时检查;--upgrade确保比对最新兼容版本;若requirements.txt未同步,pre-commit会报错并拒绝提交。
commit-msg 钩子中校验 pyproject.toml 的 dependencies 是否导致 poetry.lock 不一致
如果你用poetry管理依赖,pyproject.toml里的[tool.poetry.dependencies]改动后,必须运行poetry lock更新poetry.lock。钩子可直接调用poetry check(它隐式验证锁文件一致性)。
立即学习“Python免费学习笔记(深入)”;
- 在
.git/hooks/commit-msg中写入(需chmod +x):
#!/bin/sh if poetry check >/dev/null 2>&1; then exit 0 else echo "❌ poetry.lock is out of date. Run 'poetry lock' and commit the change." exit 1 fi
注意:poetry check不修改文件,只做校验;它依赖poetry已安装且在PATH中;若项目未初始化poetry环境(如无poetry.lock),该命令会失败——此时应改用poetry install兜底,但需谨慎避免自动安装。
为什么不用 git diff 直接比对 setup.py 或 pyproject.toml?
因为单纯看配置文件改动无法判断依赖是否真正“需要更新”——比如把requests>=2.25.0改成requests>=2.26.0只是放宽约束,并不强制升级;而pip-compile或poetry lock才是真正执行解析、求解、锁定的过程。直接diff会漏掉间接依赖的冲突或安全漏洞引入。
-
pip list --outdated不能用于钩子:它检查已安装包,而非源码声明,且受当前虚拟环境影响,不可重现 -
pip show或importlib.metadata.version()只能查运行时,对CI或新克隆仓库无效 - 所有钩子逻辑必须能在无网络、无额外缓存的CI环境中稳定执行——所以优先选
pip-compile --no-emit-trusted-host这类离线友好的命令
真正容易被忽略的是:钩子必须覆盖所有可能修改依赖声明的位置。比如有人绕过requirements.in直接改requirements.txt,或在pyproject.toml里误加[project.optional-dependencies]却没更新锁文件——这时光靠单点校验不够,得配合CI流水线二次扫描,或者把钩子设为pre-push而非pre-commit来提高覆盖面。


















