AI 参与说明(Agent:Codex):本文由 Codex 根据 Husky、Git 与 lint-staged 的官方文档及公开源码辅助调研、撰写和校验,并使用
humanizer-zh编辑中文正文。资料核验于 2026-10-12;安装机制以 Husky9.1.7为例。运行记录:模型gpt-6.1-sol,reasoning effortultra,执行入口 Codex Desktop,提供方openai,CLI 版本0.162.0-alpha.17.2(不代表桌面 App 版本)。
| 英文术语 | 中文名称 | 简要解释 |
|---|---|---|
| Git hooks | Git 钩子 | Git 在提交、推送等事件发生时调用的脚本。 |
| Husky | Husky(产品名) | 帮助项目安装和维护 Git hooks 的工具。 |
| lint-staged | lint-staged(产品名) | 按匹配规则,对已暂存的文件运行检查或格式化命令。 |
| CI | 持续集成 | 在远端自动运行构建、检查和测试的流程。 |
.husky 通常是项目使用 Husky 保存 Git hooks 的目录。你可以把它理解成“执行 Git 操作时,自动运行哪些命令”的约定:提交前检查代码,检查提交说明,或者推送前运行测试。目录名开头的点表示它按 Unix 习惯属于隐藏目录,在 GitHub 的文件列表中仍然能看到。Husky 官方介绍
Git invokes hooks at defined events; Husky connects those hooks to scripts maintained in the project. Husky 本身不制定代码规范,也不负责判断测试是否通过;这些工作由脚本调用的检查工具完成。Git hooks 手册
目录里的文件分别做什么
下面是常见结构示意,不是每个项目都会有全部文件:
.husky/
├── pre-commit
├── commit-msg
├── pre-push
└── _/
| 文件或目录 | 调用时机与用途 |
|---|---|
pre-commit | 创建 commit 前运行;项目可以在这里检查格式、静态规则或测试。 |
commit-msg | 检查已准备好的提交说明;例如调用 commitlint 检查项目约定的格式。 |
pre-push | 推送到远端前运行;项目可以在这里安排测试等检查。 |
_ | Husky 安装时生成的内部脚本目录,通常不需要人工编辑或提交。 |
前三个名称对应 Git 定义的事件。对于这些 hooks,脚本返回非零退出码时,Git 会中止对应的提交或推送操作;并非所有 Git hooks 都能阻止操作,例如 post-commit 在 commit 已经创建后才运行。Git hooks 手册
在 Husky 9.1.7 的默认安装中,core.hooksPath 被设置为 .husky/_。Git 先调用该目录中的入口,再由 Husky 调用项目维护的 .husky/pre-commit 等脚本。Husky 会在 _ 中生成 .gitignore,忽略该目录的生成文件。因此,仓库通常提交 .husky/pre-commit 等项目脚本,而不提交 .husky/_。Husky 9.1.7 安装源码
为什么很多开源仓库都有它
Git 默认使用的 .git/hooks 属于本地仓库元数据,其中的脚本不会随普通 clone 自动复制给其他贡献者。把项目脚本保存为受版本控制的 .husky/pre-commit 等文件,贡献者就能拿到同一套规则;再通过安装步骤在各自的本地仓库启用它们。Pro Git:Git Hooks
这对多人协作很实用:贡献者提交之前就能发现格式错误或测试失败,维护者也能少处理一些只涉及格式的修改。规则作为普通文件进入代码审查,修改时可以看 diff、讨论原因,并保留历史。这些是采用这种工作方式的理由,是否需要安装仍取决于项目。
Husky 能直接调用 JavaScript 项目已有的 npm 命令,因而容易融入这类项目的开发流程。它也支持多种操作系统和 Git GUI,并非某个前端框架专属的目录。Husky 官方介绍
“最近经常看到”不足以证明它最近才出现或使用量近期大幅增长。更准确的解释是:查看采用这类提交检查流程的开源仓库时,会反复遇到这个目录;模板或脚手架若预置了这些配置,也会让更多新项目带有它。
读一个脚本就能看懂项目的要求
例如,一个已配置 lint-staged 的项目可以有这样的脚本:
# .husky/pre-commit
npx lint-staged
这里的分工是:Git 决定调用时机,Husky 负责接入项目脚本,lint-staged 选出已暂存且符合配置的文件,最后由配置中的检查或格式化工具处理它们。实际检查内容还要继续查看 package.json 或该项目的 lint-staged 配置文件。上面的片段是结构示意,不能在未安装和配置 lint-staged 的项目里直接照用。lint-staged 官方 README
也可以直接在 hook 中写 npm test。这通常运行项目定义的整个测试命令,不会因为放在 pre-commit 里,就自动缩小到本次暂存的文件范围。检查范围取决于被调用的命令及其配置。
最小示例:验证提交前确实会执行脚本
以下示例适用于已安装 Node.js、npm 和 Git 的 macOS / Linux shell;Windows 可在 Git Bash 中尝试。请在独立演示目录运行,避免覆盖现有项目的 test 或 prepare 配置。示例固定使用 Husky 9.1.7,目的是观察 Git hooks 的调用行为,打印语句不代表真实的业务测试。
mkdir husky-demo
cd husky-demo
git init
npm init -y
npm install --save-dev husky@9.1.7
npm pkg set 'scripts.test=node -e "console.log(\"hook ran\")"'
npx husky init
git config --get core.hooksPath
git add package.json package-lock.json .husky/pre-commit
git commit -m "chore: initialize hook demo"
前提是 Git 已配置提交身份。husky init 会创建 .husky/pre-commit,默认内容调用 npm test,并把 package.json 的 prepare 设置为 husky。core.hooksPath 的预期输出是 .husky/_;执行 commit 时应看到 hook ran,随后创建 commit。Husky Get Started
再把演示命令改为失败:
npm pkg set 'scripts.test=node -e "process.exit(1)"'
git add package.json
git commit -m "chore: demonstrate a failing hook"
这次提交应失败,且不会创建新的 commit。实际项目应把演示命令换成已有、能够单独运行的检查或测试命令。
本文在 Node.js 26.0.0、npm 11.12.1、Git 2.34.1 和 Husky 9.1.7 的隔离仓库中验证了上述调用机制:通过的命令在提交时运行,失败的命令使 commit 返回状态码 1,HEAD 保持不变,暂存内容仍然保留。
拿到一个仓库后,先看哪些地方
先读 .husky/pre-commit、.husky/commit-msg 或 .husky/pre-push,再追踪它们调用的 npm scripts 和工具配置,就能知道维护者要求做什么。随后查看项目的贡献指南和 package.json 中的安装配置。
有 .husky 目录并不等于本地已经启用 Git hooks。对于使用 npm 且配置为 "prepare": "husky" 的项目,正常安装依赖时可以通过 prepare 安装 hooks;如果跳过安装脚本、缺少 Husky 开发依赖,或者设置了 HUSKY=0,则需要检查实际启用状态。可运行 git config --get core.hooksPath 辅助确认,但自定义目录的项目不能只照默认路径判断。Husky How To
Local hooks provide early feedback, but they can be skipped. CI should repeat the checks that the project requires before merging. 例如,git commit --no-verify 可以跳过 pre-commit 和 commit-msg,但不会跳过 prepare-commit-msg;Husky 还支持通过 HUSKY=0 禁用其 hooks。因此,本地检查适合缩短反馈时间,项目要求的合并检查仍应在远端执行。Git hooks 手册、Husky How To
阅读旧仓库时还要留意 Husky 版本。较旧的脚本可能包含加载 _/husky.sh 的头部,不能把旧教程中的安装步骤直接套进新版。先对照项目声明的版本与对应文档,再修改脚本。Husky 9.1.7 安装源码