Git Hooks 小记
了解 Git hook 的用法。
Git hook
Git hook 是 Git 提供的功能。Git hook 分为客户端 hook 和服务器端 hook。
客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作
钩子都被存储在 Git 目录下的 hooks 子目录中。 也即绝大部分项目中的 .git/hooks 。 当你用 git init 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。 这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,不过,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python,或任何你熟悉的语言编写它们。 这些示例的名字都是以 .sample 结尾,如果你想启用它们,得先移除这个后缀。
常用钩子如下:
pre-commit
- 在键入提交信息前运行。 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 如果该钩子以非零值退出,Git 将放弃此次提交,不过你可以用 git commit –no-verify 来绕过这个环节。pre-receive
- 处理来自客户端的推送操作时,最先被调用的脚本是 pre-receive。 它从标准输入获取一系列被推送的引用。如果它以非零值退出,所有的推送内容都不会被接受。 你可以用这个钩子阻止对引用进行非快进(non-fast-forward)的更新,或者对该推送所修改的所有引用和文件进行访问控制
客户端钩子的使用非常简单。在工程的 .git/hooks
目录中可以找到许多内置的钩子。
这是一个 commit-msg
钩子。内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
MSG=`awk '{printf("%s",$0)}' $1`
if [[ $MSG =~ ^Merge|(feat|fix|perf|refactor|version|test|docs|style|build|ci|lint|demo|chore):[[:space:]].*$ ]]
then
echo -e "\033[32m commit success! \033[0m"
else
echo -e "\033[31m 错误: 不规范的提交信息! \033[m"
echo -e "\033[31m 提示: 可选的提交类型 [feat|fix|perf|lint|refactor|version|test|docs|style|build|ci|chore|demo] \033[m"
echo -e "\n"
echo -e "\033[31m feat: 新功能 \033[m"
echo -e "\033[31m fix: 问题修复 \033[m"
echo -e "\033[31m build: 依赖项更新,比如升级第三方库版本 \033[m"
echo -e "\033[31m ci: CI 配置或脚本更新 \033[m"
echo -e "\033[31m lint: 代码警告清理(基本不影响功能) \033[m"
echo -e "\033[31m perf: 性能优化(不影响功能) \033[m"
echo -e "\033[31m refactor: 代码重构(不影响功能) \033[m"
echo -e "\033[31m version: SDK版本号更新(不影响功能) \033[m"
echo -e "\033[31m test: 测试代码更新(不影响功能) \033[m"
echo -e "\033[31m demo: demo代码更新(不影响功能) \033[m"
echo -e "\033[31m docs: 文档更新(不影响功能) \033[m"
echo -e "\033[31m style: 代码格式化(不影响功能) \033[m"
echo -e "\033[31m chore: 代码或文档以外的更新,比如更新CHANGELOG(不影响功能) \033[m"
echo -e "\n"
echo -e "\033[31m 示例: feat: 订单模块增加倒计时功能 \033[m"
exit 1
fi
默认的客户端 hook 是放在 .git/hooks/ 目录下,所以不受版本控制。
我们可以将客户端 hook 纳入到版本控制中。在根目录中新建 .githooks
目录,目录中放 hook 脚本,然后执行如下命令:1
git config core.hooksPath .githooks
服务器端的钩子也是类似方法来配置。Gitlab 支持 Server hooks
GitLab administrators configure server hooks on the file system of the GitLab server. If you don’t have file system access, alternatives to server hooks include:
- Webhooks
- GitLab CI/CD
- Push rules, for a user-configurable Git hook interface.
不过,公司的git服务器由专人管理,我们通常无权限随意修改服务端的钩子。Gitlab 提供的其他可替代方案包括:Webhooks、GitLab CI/CD、Push rules
Push rules 机制,允许用户为自己的项目设备 pre-receive
钩子。
Push rules are pre-receive Git hooks you can enable in a user-friendly interface. Push rules give you more control over what can and can’t be pushed to your repository.
不过,这个功能只在 Gitlab Premium 版本中提供,Gitlab CE 版本中不支持。很不幸,我们公司使用的是 Gitlab CE 版本。
总结
- 钩子(hook)是 Git 提供的功能,它跟 Github、Gitlab 或 Gogs 无关
- 钩子分客户端钩子和服务器端钩子
- Gitlab 支持 Server hooks。不过 Serve hooks 一般只有系统管理员才有权限操作
- Gitlab Premium 版本支持 Push Rules (即
pre-receive
) - Gitlab CE 版本不支持 Push Rules
- Gitlab CE 版本中 Push Rules 的最佳替代方案是 GitLab CI/CD
- 可以通过
git config core.hooksPath <path>
调整钩子目录来将钩子纳入到版本管理中来