vscode本身不执行pre-commit钩子,真正起作用的是.git/hooks/pre-commit脚本是否正确安装且能在git执行时找到python和pre-commit命令;常见失效原因包括未在项目根目录运行pre-commit install、shell环境未激活pyenv/venv导致命令找不到、缺少可执行权限、误装commit-msg钩子而非pre-commit钩子。

VSCode 本身不执行 pre-commit 钩子,它只是触发 git commit;真正起作用的是 .git/hooks/pre-commit 脚本是否被正确安装、能否在 Git 执行时找到 Python 和 pre-commit 命令。
pre-commit install 为什么没反应
运行 pre-commit install 后,.git/hooks/pre-commit 文件为空、不可执行,或内容是 shell stub(比如只有一行 #!/bin/sh),说明钩子没真正写入。常见原因包括:
- 没在项目根目录下运行命令(必须 cd 进项目根,且该目录含
.pre-commit-config.yaml) - 当前 shell 环境没激活 pyenv / venv,导致
pre-commit命令找不到,安装过程静默失败 - 权限问题:
.git/hooks/pre-commit缺少可执行位,需手动chmod +x .git/hooks/pre-commit - 用了
pre-commit install --hook-type commit-msg,这装的是提交信息检查钩子,不是 pre-commit 阶段的
VSCode 提交时 pre-commit 不触发的典型现象
你在终端里 git commit -m "test" 能看到 black / eslint 输出,但点击 VSCode 左侧「✔️」提交按钮却直接跳过检查、甚至报 Aborting commit due to empty commit message —— 这不是 VSCode 设置错了,而是:
- VSCode 的 GUI 提交流程调用系统 Git,但不会加载你的
~/.zshrc或~/.bash_profile,PATH 里没有pre-commit可执行文件路径 -
"git.enableSmartCommit": true开启时,VSCode 会把未暂存文件一并提交,绕过 pre-commit 对 staged 文件的检查逻辑(pre-commit 默认只处理git add过的文件) -
.git/hooks/pre-commit是用系统 Python 跑的,但你项目依赖的black、flake8安装在 venv 里,系统 Python 找不到它们
让 pre-commit 在 VSCode 提交中稳定生效的关键动作
不是改 VSCode 的“钩子开关”,而是确保 Git 层面的执行环境可靠:
- 先激活环境再安装钩子:如果用 pyenv,先
pyenv local 3.11;如果用 venv,先source venv/bin/activate,再运行pre-commit install - 验证钩子是否就位:
ls -l .git/hooks/pre-commit应显示指向 Python 脚本(如python3.11 .../pre_commit/main.py),不是空文件或#!/bin/sh - 在 VSCode 设置里加一条:
"terminal.integrated.inheritEnv": true,让内置终端能读到 shell 的 PATH 和 PYTHONPATH - 关掉智能提交:
"git.enableSmartCommit": false,强制自己先git add,再点提交,保证 pre-commit 有东西可检查
pre-commit 和 lint-staged / husky 混用时的冲突点
如果你同时装了 husky 和 pre-commit,又在 .husky/pre-commit 里写了 npx lint-staged,而 .git/hooks/pre-commit 又是 pre-commit 框架生成的,Git 会只执行后者(因为 .git/hooks/pre-commit 优先级更高),前者被完全忽略。
更麻烦的是:pre-commit 默认只对 staged 文件运行,而 lint-staged 也一样 —— 两者逻辑重叠,但配置分散、报错路径不同,排错成本翻倍。建议二选一:
- Python 项目优先用
pre-commit(原生支持 flake8 / mypy / black,配置集中) - JS/TS 项目优先用
husky + lint-staged(生态成熟,npm 包管理更顺) - 混用时,删掉
.git/hooks/pre-commit,只保留.husky/pre-commit,并在里面明确调用pre-commit run --all-files或按需指定钩子
最容易被忽略的一点:pre-commit 钩子是否生效,和 VSCode 设置几乎无关;它本质是个 Git 层机制,成败取决于 .git/hooks/pre-commit 文件内容、执行权限、以及它启动时能否访问到正确的 Python 环境和依赖包。别在 settings.json 里找“启用 pre-commit”开关——它根本不存在。











