Git
章节 ▾ 第 2 版

8.3 定制 Git - Git 钩子

Git 钩子

像许多其他版本控制系统一样,Git 有一种方法可以在发生某些重要操作时触发自定义脚本。这些钩子分为两组:客户端钩子和服务器端钩子。客户端钩子由提交和合并等操作触发,而服务器端钩子则在接收推送提交等网络操作时运行。您可以出于各种原因使用这些钩子。

安装钩子

所有钩子都存储在 Git 目录的 hooks 子目录中。在大多数项目中,该目录为 .git/hooks。当您使用 git init 初始化新仓库时,Git 会在 hooks 目录中填充一些示例脚本,其中许多脚本本身就很有用;但它们也记录了每个脚本的输入值。所有示例都编写为 shell 脚本,其中还包含一些 Perl 代码,但任何名称正确的可执行脚本都可以正常工作——您可以使用 Ruby、Python 或您熟悉的任何语言编写它们。如果要使用捆绑的钩子脚本,则必须重命名它们;它们的文件名都以 .sample 结尾。

要启用钩子脚本,请在 .git 目录的 hooks 子目录中放置一个名称正确的(没有扩展名)且可执行的文件。从那时起,它应该会被调用。我们将在本文档中介绍大多数主要的钩子文件名。

客户端钩子

有很多客户端钩子。本节将它们分为提交工作流钩子、电子邮件工作流脚本和其他所有内容。

注意

需要注意的是,客户端钩子在克隆仓库时 **不会** 被复制。如果使用这些脚本的目的是执行策略,则可能需要在服务器端执行;请参阅 Git 强制策略示例 中的示例。

提交工作流钩子

前四个钩子与提交过程有关。

pre-commit 钩子在您甚至输入提交信息之前就被运行。它用于检查即将提交的快照,以查看您是否忘记了什么,确保测试运行,或者检查您需要在代码中检查的任何内容。从该钩子退出非零值将中止提交,尽管您可以使用 git commit --no-verify 跳过它。您可以执行诸如检查代码风格(运行 lint 或类似操作)、检查尾随空格(默认钩子正是这样做的)或检查新方法的适当文档等操作。

prepare-commit-msg 钩子在提交信息编辑器启动之前但创建默认信息之后运行。它允许您在提交作者看到它之前编辑默认信息。此钩子带有一些参数:包含迄今为止提交信息的文件的路径、提交类型以及如果这是一个修订提交则为提交 SHA-1。此钩子通常对普通提交没有用;相反,它适用于默认信息自动生成的提交,例如模板化提交信息、合并提交、压缩提交和修订提交。您可以将其与提交模板结合使用以编程方式插入信息。

commit-msg 钩子带有一个参数,该参数再次是包含开发人员编写的提交信息的临时文件的路径。如果此脚本退出非零值,Git 将中止提交过程,因此您可以使用它在允许提交通过之前验证您的项目状态或提交信息。在本章的最后一节中,我们将演示使用此钩子来检查您的提交信息是否符合所需模式。

在整个提交过程完成后,post-commit 钩子将运行。它不带任何参数,但您可以通过运行 git log -1 HEAD 轻松获取最后一次提交。通常,此脚本用于通知或类似操作。

电子邮件工作流钩子

您可以为基于电子邮件的工作流设置三个客户端钩子。它们都由 git am 命令调用,因此如果您在工作流中未使用该命令,则可以安全地跳到下一节。如果您通过 git format-patch 准备的电子邮件获取补丁,那么其中一些可能对您有所帮助。

第一个运行的钩子是 applypatch-msg。它带有一个参数:包含建议的提交信息临时文件的名称。如果此脚本退出非零值,Git 将中止补丁。您可以使用它来确保提交信息格式正确,或者通过让脚本就地编辑它来规范化信息。

通过 git am 应用补丁时运行的下一个钩子是 pre-applypatch。有点令人困惑的是,它是在应用补丁之后但在进行提交之前运行,因此您可以使用它在进行提交之前检查快照。您可以使用此脚本运行测试或以其他方式检查工作树。如果缺少某些内容或测试未通过,则退出非零值将中止 git am 脚本而不会提交补丁。

git am 操作期间运行的最后一个钩子是 post-applypatch,它在提交完成后运行。您可以使用它来通知您提取的补丁的组或作者您已这样做。您无法使用此脚本停止修补过程。

其他客户端钩子

pre-rebase 钩子在您重写任何内容之前运行,并且可以通过退出非零值来停止该过程。您可以使用此钩子禁止重写已推送的任何提交。Git 安装的示例 pre-rebase 钩子就是这样做的,尽管它做了一些可能与您的工作流不匹配的假设。

post-rewrite 钩子由替换提交的命令(例如 git commit --amendgit rebase(但 git filter-branch 除外))运行。它的唯一参数是触发重写的命令,它接收 stdin 上的重写列表。此钩子具有与 post-checkoutpost-merge 钩子许多相同的用途。

在您成功运行 git checkout 后,post-checkout 钩子将运行;您可以使用它为您的项目环境正确设置您的工作目录。这可能意味着移动您不想进行源代码管理的大型二进制文件、自动生成文档或类似操作。

post-merge 钩子在成功运行 merge 命令后运行。您可以使用它来恢复 Git 无法跟踪的工作树中的数据,例如权限数据。同样,此钩子可以验证您可能希望在工作树更改时复制的 Git 控制之外的文件的存在。

pre-push 钩子在 git push 期间运行,在远程引用更新后但在任何对象传输之前运行。它接收远程的名称和位置作为参数,以及通过 stdin 更新的引用列表。您可以使用它来验证一组引用更新,然后再进行推送(非零退出代码将中止推送)。

Git 偶尔会在其正常操作过程中进行垃圾回收,方法是调用 git gc --autopre-auto-gc 钩子在垃圾回收开始之前被调用,可用于通知您正在发生这种情况,或者如果现在不是好时机则中止回收。

服务器端钩子

除了客户端钩子之外,您还可以使用几个重要的服务器端钩子作为系统管理员来为您的项目执行几乎任何类型的策略。这些脚本在推送到服务器之前和之后运行。预钩子可以在任何时候退出非零值以拒绝推送以及将错误消息打印回客户端;您可以设置一个您想要的复杂程度的推送策略。

pre-receive

处理来自客户端的推送时运行的第一个脚本是 pre-receive。它从 stdin 获取正在推送的引用列表;如果它退出非零值,则不接受任何引用。您可以使用此钩子执行诸如确保所有更新的引用都不是非快进或对所有引用及其使用推送修改的文件执行访问控制等操作。

update

update 脚本与 pre-receive 脚本非常相似,只是它针对推送者尝试更新的每个分支运行一次。如果推送者尝试推送到多个分支,pre-receive 只运行一次,而 update 针对他们推送到的每个分支运行一次。此脚本不从 stdin 读取,而是获取三个参数:引用的名称(分支)、推送前引用指向的 SHA-1 以及用户尝试推送的 SHA-1。如果 update 脚本退出非零值,则仅拒绝该引用;其他引用仍然可以更新。

post-receive

post-receive 钩子在整个过程完成后运行,可用于更新其他服务或通知用户。它采用与 pre-receive 钩子相同的 stdin 数据。示例包括发送电子邮件列表、通知持续集成服务器或更新票证跟踪系统 - 您甚至可以解析提交信息以查看是否需要打开、修改或关闭任何票证。此脚本无法停止推送过程,但客户端在完成之前不会断开连接,因此如果您尝试执行可能需要很长时间的任何操作,请小心。

提示

如果您正在编写其他人需要阅读的脚本/钩子,请首选命令行标志的长版本;六个月后,您会感谢我们的。

scroll-to-top