Git Hooks 小记

了解 Git hooks 的用法。

Git hook

Git hooks 是 Git 提供的功能。Git hooks 分为客户端 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 目录中可以找到许多内置的钩子。

-w766

这是一个 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
#!/bin/bash
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

-w1363

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:

不过,公司的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.

-w1433

不过,这个功能只在 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> 调整钩子目录来将钩子纳入到版本管理中来

参考