Git Hook:让Git自动帮你干活
说实话,我刚接触Git Hook的时候,觉得这玩意儿挺玄乎的。什么钩子不钩子的,听着像钓鱼工具。直到有一次,我提交代码时忘了跑测试,结果把有bug的代码推到了线上...嗯,从那以后,我就老老实实研究Hook了。
说白了,Git Hook就是一些脚本。在特定事件发生时,Git会自动执行它们。比如你提交代码前,它帮你检查代码风格;推送代码后,它自动部署到服务器。是不是很香?
钩子到底是什么?
每个Git仓库下都有个.git/hooks目录。你进去看看,里面有一堆.sample结尾的文件。这些就是钩子的模板。
# 看看你的钩子目录
ls .git/hooks/
# 输出类似:
# applypatch-msg.sample pre-commit.sample
# commit-msg.sample pre-push.sample
# post-update.sample pre-rebase.sample
# ...
想启用某个钩子?把.sample去掉就行。我习惯把不需要的钩子直接删掉,只保留要用的,看着清爽。
核心要点:钩子本质上是可执行的脚本文件。可以用Shell、Python、Ruby等任何语言写。只要它能运行,Git就认。
客户端钩子:管好你自己
客户端钩子在你自己的机器上运行。别人推不推送代码,跟你没关系。你只管管好自己的提交。
pre-commit:提交前的守门员
这个钩子我最常用。每次git commit之前,它都会跑一遍。如果返回非零值,提交就失败。
#!/bin/sh
# .git/hooks/pre-commit
# 检查是否有调试代码
if grep -rn "console.log\|debugger\|TODO" --include="*.js" .; then
echo "❌ 发现调试代码或待办事项,请清理后再提交!"
exit 1
fi
echo "✅ 代码检查通过"
exit 0
我曾经在一个项目里,同事把console.log带到了生产环境。页面一打开,控制台全是调试信息...从那以后,我就给团队加了这个钩子。
commit-msg:规范你的提交信息
提交信息乱七八糟?这个钩子帮你治。
#!/bin/sh
# .git/hooks/commit-msg
# 检查提交信息格式:type(scope): description
commit_msg=$(cat "$1")
pattern="^(feat|fix|docs|style|refactor|test|chore)\(.*\): .{1,50}$"
if ! echo "$commit_msg" | grep -qE "$pattern"; then
echo "❌ 提交信息格式不对!"
echo "正确格式:type(scope): description"
echo "例如:feat(user): 添加登录功能"
exit 1
fi
我的建议:commit-msg钩子配合Conventional Commits规范,团队协作会顺畅很多。你想想看,看日志的时候一目了然,多舒服。
pre-push:推送前的最后防线
这个钩子在git push时触发。我一般用它来跑测试。
#!/bin/sh
# .git/hooks/pre-push
echo "🏃 运行测试..."
npm test
if [ $? -ne 0 ]; then
echo "❌ 测试失败,推送已阻止"
exit 1
fi
服务端钩子:团队协作的守门人
服务端钩子跑在远程仓库上。比如GitHub、GitLab或者你自己搭的Git服务器。它管的是整个团队的代码质量。
| 钩子名称 | 触发时机 | 典型用途 |
|---|---|---|
| pre-receive | 服务端收到推送时 | 检查推送权限、代码规范 |
| update | 每个分支更新时 | 分支保护、强制代码审查 |
| post-receive | 推送完成后 | 自动部署、通知团队 |
我见过一个团队用pre-receive钩子做代码审查。没通过Review的代码,直接拒绝推送。虽然严格了点,但代码质量确实上去了。
常用钩子示例:实战出真知
1. 代码格式化钩子
#!/bin/sh
# pre-commit: 自动格式化代码
echo "🎨 格式化代码..."
npx prettier --write "src/**/*.{js,jsx,ts,tsx}"
# 把格式化后的文件加入暂存区
git add -u
2. 分支命名检查
#!/bin/sh
# pre-push: 检查分支命名
branch=$(git rev-parse --abbrev-ref HEAD)
if [[ ! "$branch" =~ ^(feature|bugfix|hotfix)/[a-z0-9-]+$ ]]; then
echo "❌ 分支命名不规范"
echo "正确格式:feature/xxx 或 bugfix/xxx 或 hotfix/xxx"
exit 1
fi
注意:钩子脚本要设置可执行权限。我经常看到有人配好了钩子,但忘了chmod +x,结果钩子不生效。排查了半天...
自动化部署:从提交到上线
这才是钩子的高光时刻。用post-receive钩子,可以实现推送即部署。
#!/bin/sh
# 服务端 post-receive 钩子
# 实现自动部署
# 部署目录
DEPLOY_DIR="/var/www/myapp"
# 只处理主分支
while read oldrev newrev refname
do
if [ "$refname" = "refs/heads/main" ]; then
echo "🚀 开始部署到生产环境..."
# 切换到部署目录
cd $DEPLOY_DIR
# 拉取最新代码
git pull origin main
# 安装依赖
npm install --production
# 构建项目
npm run build
# 重启服务
pm2 restart app
echo "✅ 部署完成!"
fi
done
我有个小项目就是这么搞的。本地改完代码,git push一下,服务器自动更新。省去了手动上传的麻烦。不过要注意,生产环境慎用自动部署,最好加个手动确认步骤。
知识体系总览
下面这张图,把Git Hook的核心脉络理清楚了。你一看就明白。
避坑指南
玩钩子这些年,我踩过不少坑。分享几个给你:
- 钩子不生效?检查文件权限。我经常忘了
chmod +x,钩子文件没执行权限,Git理都不理你。 - 团队怎么共享钩子?
.git/hooks目录不会被推送。我习惯在项目根目录建个hooks文件夹,写个脚本自动复制到.git/hooks。 - 钩子执行太慢?别在钩子里跑全量测试。我一般只跑改动文件相关的测试,或者用
lint-staged只检查暂存区的文件。 - 想跳过钩子?用
--no-verify参数。但别滥用,我只有在紧急修复线上bug时才用。
小技巧:用husky这个工具管理钩子。它能把钩子配置写在package.json里,团队共享特别方便。我个人项目基本都用它。
Git Hook这东西,说白了就是让Git在关键时刻帮你做点事。用好了,能省不少心。你想想看,每次提交都自动检查代码、跑测试、格式化,多省事。别怕配置麻烦,一次配置,长期受益。