lint-staged是核心工具,husky仅执行命令;pre-commit应写npx lint-staged,因其自动提取暂存文件、按后缀分发任务、自动git add,避免误操作与格式不一致。

Husky 本身不格式化、不校验、不写入 Git 暂存区——它只负责在 git commit 触发时,忠实地执行你写的那行命令。真正干活的是 lint-staged、prettier 或 eslint,而 VSCode 只管保存时的即时反馈。
pre-commit 钩子该写什么命令?别直接调用 prettier --write .
写 npx lint-staged 是最稳的选择,不是因为“高级”,而是它天然解决三个硬伤:
-
lint-staged自动从git diff --cached提取暂存文件,不会误扫node_modules或未git add的草稿 - 支持按后缀分发不同命令(比如 JS 跑
eslint --fix+prettier --write,CSS 只跑prettier --write) - 格式化后自动
git add回暂存区——这点必须有,否则改了文件但没加进提交,husky 会报错退出
如果你跳过 lint-staged 直接写 npx prettier --write .,大概率会卡在权限错误、路径不存在,或把生成文件/配置文件一并重写。
为什么 pre-commit 看似运行了,但代码没被格式化?
常见断点不在 husky,而在下游工具链是否“连得通”:
-
.husky/pre-commit文件缺少可执行权限(Linux/macOS 下必须chmod +x .husky/pre-commit) -
package.json里lint-staged字段的 glob 模式和你git add的文件不匹配(例如写了*.js却提交了index.tsx) -
prettier找不到.prettierrc,退回到默认规则——这时 VSCode 看到的和 husky 执行的格式结果可能不一致 -
npx在 VSCode 内置终端里找不到本地node_modules/.bin/prettier(PATH 不一致),建议在.husky/pre-commit开头加echo $PATH对比验证
VSCode 保存格式化和 husky 提交前格式化能共存吗?
能,而且应该共存,但前提是规则完全对齐:
- VSCode 保存时用
editor.formatOnSave: true快速响应,靠esbenp.prettier-vscode插件读取项目根目录的.prettierrc - husky +
lint-staged是兜底:处理你忘了保存的文件、修复 VSCode 插件没覆盖的规则(比如 ESLint 的no-console)、阻断不合规提交 - 关键:所有配置文件(
.prettierrc、.eslintrc.js、.stylelintrc.json)必须放在项目根目录,并且git add进仓库——VSCode 和 husky 都依赖这个路径读取,不存在“本地插件读一个、npx 读另一个”的情况
VSCode 提交面板不显示模板,但 commit-msg 钩子却生效?
这是典型混淆:VSCode 是否显示提交模板,和 husky 完全无关。
- 模板由 Git 原生命令控制:
git config --get commit.template返回的路径是否有效、是否 UTF-8 无 BOM、末尾是否有空行 -
commit-msg钩子是 husky 注册的另一套逻辑,只在校验提交信息格式(比如是否以feat:开头),它不参与模板渲染 - 如果 VSCode 没加载模板,先检查
.gitmessage.txt是否存在且编码正确,而不是去翻.husky/commit-msg
最容易被忽略的其实是环境一致性:VSCode 终端、系统终端、CI 环境下的 Node 版本、npx 查找路径、Prettier 配置加载顺序,稍有偏差就导致“本地 OK,提交失败”。与其反复调试,不如在 .husky/pre-commit 开头固定写上 set -euxo pipefail,让每一步失败都暴露出来。











