
pre-commit 在首次安装后会自动缓存并复用已配置的 hook 依赖(如 PyPI 包),即使原始本地代码库被删除,只要 .pre-commit-config.yaml 中仍声明 additional_dependencies,它就会从 PyPI 下载并执行对应工具——这正是其“配置即事实”的设计哲学。
pre-commit 在首次安装后会自动缓存并复用已配置的 hook 依赖(如 pypi 包),即使原始本地代码库被删除,只要 `.pre-commit-config.yaml` 中仍声明 `additional_dependencies`,它就会从 pypi 下载并执行对应工具——这正是其“配置即事实”的设计哲学。
当你在 .pre-commit-config.yaml 中配置如下本地 hook:
- repo: local
hooks:
- id: trailing-whitespace
name: Trim trailing-whitespace
language: python
entry: python3 -m pre_commit_hooks.trailing_whitespace_fixer
additional_dependencies: [pre_commit_hooks]
关键点在于: additional_dependencies: [pre_commit_hooks] 并非指向你本地开发的 ./pre_commit_hooks/ 目录,而是明确要求 pre-commit 从 PyPI 安装官方包 pre-commit-hooks(注意连字符)。该包已预置 trailing_whitespace_fixer 模块,因此即使你删掉自己的 hooks 仓库、清空 ~/.cache/pre-commit、甚至重装 pre-commit,只要配置未变,pre-commit 就会在每次 pre-commit run 或 git commit 前自动拉取并复用该 PyPI 包的已缓存环境——这就是你观察到“钩子照常运行”的根本原因。
✅ 验证方式(推荐):
运行以下命令查看实际加载的 Python 环境路径:
pre-commit run --verbose trailing-whitespace --all-files 2>&1 | grep "python.*site-packages"
输出中将显示类似 /Users/xxx/.cache/pre-commit/repoxxx/py_env-python3.11/lib/python3.11/site-packages/pre_commit_hooks/ 的路径,证实其来源是 PyPI 缓存包,而非你的本地目录。
? 彻底禁用该 hook 的正确做法:
-
删除或注释掉
.pre-commit-config.yaml中对应 hook 配置段(最直接有效); - 若需保留配置但临时跳过,提交时加
--no-verify(不推荐长期使用); - 若误装了其他冲突依赖,可强制清理所有缓存环境:
pre-commit clean rm -rf ~/.cache/pre-commit # 然后重新 install(此时因配置缺失,不再安装任何 hook) pre-commit install
⚠️ 重要提醒:
-
pre-commit clean仅清除 hook 运行时环境缓存,不会修改配置文件或卸载 PyPI 依赖本身; -
pre-commit install仅生成.git/hooks/pre-commit脚本,真正决定“执行什么”的是.pre-commit-config.yaml—— 只要它存在且含additional_dependencies,pre-commit 就会按需安装并运行; - 本地开发自定义 hook 应使用
language: system+ 绝对路径,或通过repo: ./path/to/local/hooks(需为 Git 仓库)显式引用,避免与 PyPI 同名包混淆。
? 总结:pre-commit 的行为由配置驱动,而非文件系统状态。要让它“找不到 hook”,唯一可靠的方式是移除或修正配置中的依赖声明——这是其确定性、可复现、适合 CI/CD 的核心设计,而非 bug。










