Husky 常用 Git 钩子 — 详尽介绍与实战场景

下面是一篇面向前端/全栈开发者的实用文档,介绍 Husky(使用 Node.js + Git 管理本地钩子)的常用 Git 钩子、典型使用场景、配置示例与最佳实践。


一、什么是 Husky(快速简介)

Husky 是一个把原生 Git 钩子(native git hooks)以项目依赖方式管理的工具,能够把 shell 脚本放到 .husky/ 目录并在对应的 Git 事件(如 pre-commitcommit-msgpre-push 等)触发时执行,常用来在本地阻止不合格的提交或 push。官方文档说明了初始化/安装与基本用法。 (typicode.github.io)

注意:Husky 只是本地钩子管理器,重度或必须在所有提交上强制执行的策略仍应在 CI 或服务器端策略上校验(例如在 PR/CI 阶段运行完整测试套件)。


二、安装与初始化(快速上手)

推荐的最小安装流程(以 npm 为例):

# 安装 husky
npm install --save-dev husky

# 在项目内初始化(会创建 .husky/ 目录并把 prepare 脚本写入 package.json)
npx husky-init
# 或者手动安装 hook 支持
npm set-script prepare "husky install"
npx husky install
# 之后可以通过 npx husky add 添加单个 hook
npx husky add .husky/pre-commit "npm test"

Husky 的 hook 文件通常以 shell 脚本形式存在于 .husky/<hook-name>,文件顶部会包含一行类似 . "$(dirname -- "$0")/_/husky.sh" 的加载逻辑。官方 How-To 有详细示例。 (typicode.github.io, npm)


三、常用钩子(用途说明 + 场景 + 示例)

下面按频率与实用性列出常见钩子,并给出典型脚本与推荐实践。

1) pre-commit

目的:在 git commit 成功创建提交对象之前运行,常用于运行格式化、静态检查、或快速测试,阻止不合格代码进入版本历史。

典型场景

  • 用 Prettier 自动格式化 staged 文件

  • 运行 ESLint 修复并报错阻止提交

  • 运行对改动文件相关的快速单测(例如 jest --findRelatedTests

推荐实践

  • 不要在 pre-commit 里跑耗时很长的集成测试;那类检查放 pre-push 或 CI。

  • 使用 lint-staged 只针对 staged 文件运行工具,显著提高速度并避免无关文件被处理。 (GitHub)

示例

package.json(部分):

{
  "scripts": {
    "prepare": "husky install",
    "prettier:fix": "prettier --write",
    "lint": "eslint . --fix",
    "pre-commit": "lint-staged"
  },
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": ["npm run lint", "npm run prettier:fix", "git add"]
  }
}

添加 husky hook:

npx husky add .husky/pre-commit "npm run pre-commit"

.husky/pre-commit(示例自动生成):

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run pre-commit

2) commit-msg

目的:在提交信息输入后、提交保存之前检查 commit message 内容,常用于 enforce commit message 规范(如 Conventional Commits)。

典型场景

  • 使用 commitlint 校验提交信息是否符合团队规则(比如 feat:, fix:, chore: 等)

  • 阻止不规范的 message 推入历史,从而保障自动化发布/变更日志工具能正常工作

示例(使用 commitlint):

# 安装 commitlint 及配置
npm install --save-dev @commitlint/config-conventional @commitlint/cli

# 添加 commitlint 配置文件 commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional'] };

# 添加 husky commit-msg hook
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

详见 commitlint 的本地集成指南(可与 Husky 的 commit-msg 钩子配合)。 (commitlint.js.org)

小提示:在 Windows 或不同 shell 下,"$1" 的引用方式可能需调整,常见解决方案在社区问答中有说明。


3) pre-push

目的:在 git push 之前触发,适合运行可能比 pre-commit 更耗时但仍需要在推送前阻止错误进入远程仓库的检查(例如快速测试、类型检查、构建检查等)。

典型场景

  • 运行快速测试套件(或测试“快速模式”)

  • 运行 tsc --noEmit 做类型检查

  • 运行一次轻量端到端/集成检查(需谨慎控制时间)

示例

# 添加 pre-push hook 只跑快速测试
npx husky add .husky/pre-push "npm run test:quick"

实践建议

  • 把更慢的、必须稳定执行的检查交给 CI(如完整单元 + 集成测试),避免本地 push 时阻塞开发效率。

  • 对于 monorepo,pre-push 可以只对当前 package 运行轻量检查。


4) prepare-commit-msg

目的:在打开编辑器或生成默认 commit message 时触发,用于为 commit message 提供模板或自动注入信息(例如分支名、PR 引用、变更摘要)。

典型场景

  • 自动在合并提交模板中注入 PR 编号

  • 根据当前分支名预填充 commit message(例如 feat/issue-123 -> feat: 123 ...

示例

npx husky add .husky/prepare-commit-msg 'exec < /dev/tty && node scripts/prefill-commit-msg.js "$1"'

5) post-merge / post-checkout

目的:在合并或检出分支后触发,适合处理依赖变化或生成文件。

典型场景

  • package.json 或 lockfile 变化时自动运行 npm ci / pnpm install

  • 重新生成代码或重建本地缓存

示例

npx husky add .husky/post-merge "if [ -f package-lock.json ] || [ -f pnpm-lock.yaml ]; then npm ci; fi"

6) 其他钩子(简要)

  • pre-rebase:在 rebase 开始前触发,可用于提示或自动 stash 操作。

  • post-commit:提交后操作(例如自动推送到某个分支、触发本地脚本等)。

  • applypatch-msgpre-applypatchpost-applypatch 等:较少使用,通常用于特殊补丁流程。


四、最佳实践与注意事项(实践要点)

  1. 把重型检查放 CI、轻量放本地:避免在 pre-commit 上运行几分钟级别任务,影响本地开发效率。把长时间、熵大的检查放 CI/PR。

  2. 使用 lint-staged 限定为 staged 文件:显著提高速度,避免不相关文件被处理。 (GitHub)

  3. 写可读的失败提示与退出码:当 hook 拦截时,给出清晰修复建议(比如 eslint --fix / npm run format)。

  4. 允许跳过但谨慎使用git commit --no-verify 可跳过本地钩子(用于紧急提交),但应在团队中有明确定义何时允许跳过。

  5. 全局禁用开关:Husky 支持通过环境变量 HUSKY=0 全局禁用。可在特殊环境或容器中使用。 (typicode.github.io)

  6. 确保 .husky/* 脚本可执行:新建的 hook 文件需要有可执行权限(Unix 系统上使用 chmod +x .husky/*)。

  7. 把 hook 的具体实现放到 package.json scripts 或独立脚本,hook 文件仅做 orchestration,这样更好维护与测试。


五、典型错误与排查(Quick Troubleshooting)

  • 钩子没有触发:确认 .husky/ 目录存在并已执行 npm run prepare(或 npx husky install),检查 .git/hooks 是否被 husky 管理。查看 .husky/<hook> 文件是否有 shebang(#!/usr/bin/env sh)以及加载 husky.sh。 (typicode.github.io)

  • Windows 上参数/引用问题:某些脚本里的 $1/引号在 Windows shell 上解析不同,必要时使用 npx --no-install 或在脚本中做跨平台兼容处理。社区有大量实践可参考。

  • 速度慢:将长任务移到 pre-push 或 CI,使用 lint-staged 减少运行文件集合。


六、若干实战示例(整合小示例)

示例 A:Prettier + ESLint(只针对 staged 文件)

# 安装
npm install --save-dev husky lint-staged prettier eslint

# package.json scripts
{
  "scripts": {
    "prepare": "husky install",
    "pre-commit": "lint-staged",
    "format": "prettier --write",
    "lint": "eslint --fix"
  },
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": ["npm run lint", "npm run format", "git add"]
  }
}

# 添加 hook
npx husky add .husky/pre-commit "npm run pre-commit"

示例 B:commitlint 强制提交信息规范

npm install --save-dev @commitlint/cli @commitlint/config-conventional
# commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional'] };

# 添加 husky 钩子
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

示例 C:pre-push 运行快速测试

# 假定有 test:quick 脚本
npx husky add .husky/pre-push "npm run test:quick"

七、总结(落地建议)

  • 把 Husky 作为团队质量门槛的第一道防线:本地拦截常见问题(格式、静态检查、提交规范),但不要把完整验证都堆到本地。

  • 使用 lint-staged + pre-commit 的组合带来最佳体验(快速且有约束)。 (GitHub)

  • 使用 commit-msg + commitlint 规范提交信息可以大幅提升自动化发布/变更日志的可靠性。 (commitlint.js.org)

  • 初始化与使用命令、hook 文件格式等,请参考 Husky 官方文档与 How-To 指南(下列参考文档)。 (typicode.github.io)


参考(部分)

  • Husky 官方文档 — Get started / How To. (typicode.github.io)

  • Husky npm 包信息。 (npm)

  • lint-staged(用于 pre-commit 的最佳实践)。 (GitHub)

  • commitlint(与 commit-msg 钩子集成的常用工具)。 (commitlint.js.org)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值