理解 Git Hooks 的工作原理,掌握常用钩子的使用场景,学会用 Husky 实现团队代码规范化。
Hooks — 在 Git 操作的前后自动执行脚本
每次 git commit 之前自动检查代码风格、跑单元测试、验证提交信息格式……这些自动化流程都可以通过 Git Hooks 实现。
一、
什么是 Git Hooks?
Git Hooks 是在 Git 事件(如 commit、push、merge)前后自动执行的脚本。它们存放在 .git/hooks/ 目录中。
工作原理:
- Git 执行某个操作(如
git commit) - 检查
.git/hooks/ 目录下是否有对应的钩子脚本 - 如果有,自动执行该脚本
- 如果脚本返回非零退出码,操作会被中止
二、
常用钩子一览
客户端钩子(本地操作触发)
| 钩子 | 触发时机 | 典型用途 |
|---|
pre-commit | commit 之前 | 代码检查、格式化、跑测试 |
prepare-commit-msg | 打开提交信息编辑器之前 | 自动填充提交模板 |
commit-msg | 提交信息写好之后 | 验证提交信息格式 |
post-commit | commit 之后 | 发送通知、记录日志 |
pre-push | push 之前 | 跑完整测试套件 |
pre-rebase | rebase 之前 | 禁止对公共分支 rebase |
服务端钩子(远程仓库触发)
| 钩子 | 触发时机 | 典型用途 |
|---|
pre-receive | 接收 push 之前 | 拒绝不符合规范的推送 |
update | 接收 push 时(每个分支) | 分支级别的控制 |
post-receive | 接收 push 之后 | 自动部署、发送通知 |
三、
手动创建钩子
创建一个 pre-commit 钩子
1 2
| vim .git/hooks/pre-commit
|
写入脚本内容:
1 2 3 4 5 6 7 8 9 10 11 12
| #!/bin/bash
if git diff --cached | grep -q "TODO"; then echo "⚠️ 检测到 TODO 注释,请先处理后再提交" exit 1 fi
if git diff --cached | grep -q "console.log"; then echo "⚠️ 检测到 console.log,请移除后再提交" exit 1 fi
|
1 2
| chmod +x .git/hooks/pre-commit
|
创建一个 commit-msg 钩子
1 2 3 4 5 6 7 8 9
| #!/bin/bash
commit_msg=$(cat "$1") if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore):"; then echo "❌ 提交信息格式错误" echo " 必须以 feat: fix: docs: style: refactor: test: chore: 开头" echo " 你的提交信息:$commit_msg" exit 1 fi
|
手动创建钩子的两个问题:
.git/hooks/ 不会被 Git 跟踪,团队成员 clone 后没有你的钩子- 每次
git init 或 git clone 后需要重新配置
解决方案:用 Husky(见下文)。
四、
Husky — 团队共享的 Git Hooks
Husky 是目前最流行的 Git Hooks 管理工具,它把钩子配置放在项目代码中,团队成员 clone 后自动生效。
安装与初始化
1 2 3 4 5
| npm install -D husky
npx husky init
|
生成的结构:
1 2 3 4 5
| my-project/ ├── .husky/ │ └── pre-commit ← 钩子脚本(会被 Git 跟踪) ├── package.json ← 包含 prepare 脚本 └── ...
|
配置 pre-commit 钩子
编辑 .husky/pre-commit:
1 2 3 4 5
| npx eslint src/ --fix
npm test
|
配置 commit-msg 钩子
1 2
| npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
|
五、
lint-staged — 只检查暂存的文件
Husky 配合 lint-staged 使用效果更好:只检查本次提交暂存的文件,而不是全量检查。
安装
1
| npm install -D lint-staged
|
配置
在 package.json 中添加:
1 2 3 4 5 6 7 8 9 10
| { "lint-staged": { "*.{js,ts,vue}": [ "eslint --fix" ], "*.{css,scss,less}": [ "stylelint --fix" ] } }
|
配合 Husky
编辑 .husky/pre-commit:
完整效果:
- 开发者执行
git commit - Husky 触发
pre-commit 钩子 - lint-staged 只检查暂存区的
.js、.css 文件 - 自动修复能修复的问题(
--fix) - 如果有无法自动修复的错误 → 提交被阻止
- 全部通过 → 提交成功
六、
commitlint — 规范提交信息
commitlint 用于强制提交信息遵循 Conventional Commits 规范。
安装
1
| npm install -D @commitlint/cli @commitlint/config-conventional
|
配置
创建 commitlint.config.js:
1 2 3
| module.exports = { extends: ['@commitlint/config-conventional'] };
|
允许的格式:
1 2 3 4 5
| feat: 添加用户登录功能 ✅ fix: 修复密码验证错误 ✅ docs: 更新 API 文档 ✅ update ❌ 缺少类型前缀 修复了一个bug ❌ 格式不对
|
配合 Husky
1 2 3
| echo "npx --no -- commitlint --edit \${1}" > .husky/commit-msg chmod +x .husky/commit-msg
|
七、
跳过钩子
某些紧急情况下需要跳过钩子:
1 2
| git commit --no-verify -m "hotfix: 紧急修复线上问题"
|
慎用 --no-verify:这等于绕过了所有质量检查。只在紧急修复时使用,事后要记得补上规范化的提交。
八、
实战:完整的团队规范配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| npm install -D husky lint-staged @commitlint/cli @commitlint/config-conventional
npx husky init
echo "npx lint-staged" > .husky/pre-commit
echo 'npx --no -- commitlint --edit ${1}' > .husky/commit-msg
echo "module.exports = { extends: ['@commitlint/config-conventional'] }" > commitlint.config.js
git add . git commit -m "chore: 配置 husky + lint-staged + commitlint"
|
总结:Git Hooks 速查卡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ┌──────────────────────────────────────────────────────────┐ │ Git Hooks 速查 │ ├────────────────┬─────────────────────────────────────────┤ │ pre-commit │ commit 前:代码检查、格式化、跑测试 │ │ commit-msg │ 提交信息写好后:验证格式 │ │ pre-push │ push 前:跑完整测试套件 │ │ pre-rebase │ rebase 前:禁止对公共分支操作 │ ├────────────────┼─────────────────────────────────────────┤ │ 手动创建钩子 │ .git/hooks/pre-commit + chmod +x │ │ 团队共享钩子 │ Husky:.husky/ 目录被 Git 跟踪 │ │ 只检查暂存文件 │ lint-staged │ │ 规范提交信息 │ commitlint │ ├────────────────┼─────────────────────────────────────────┤ │ 跳过钩子 │ git commit --no-verify │ └────────────────┴─────────────────────────────────────────┘
|