简体中文 ▾ 主题 ▾ 最新版本 ▾ githooks 最后更新于 2.46.1

名称

githooks - Git 使用的钩子

概要

$GIT_DIR/hooks/* (或 `git config core.hooksPath`/*)

描述

钩子是在 Git 执行的特定点触发操作的程序,您可以将它们放置在钩子目录中。未设置可执行位的钩子将被忽略。

默认情况下,钩子目录是 $GIT_DIR/hooks,但可以通过 core.hooksPath 配置变量进行更改(请参阅 git-config[1])。

在 Git 调用钩子之前,它会将工作目录更改为裸仓库中的 $GIT_DIR 或非裸仓库中的工作树根目录。一个例外是推送期间触发的钩子(pre-receiveupdatepost-receivepost-updatepush-to-checkout),这些钩子始终在 $GIT_DIR 中执行。

环境变量,如 GIT_DIRGIT_WORK_TREE 等,会被导出,以便钩子运行的 Git 命令能够正确找到仓库。如果您的钩子需要在一个外部仓库或同一仓库的不同工作树中调用 Git 命令,那么它应该清除这些环境变量,以免它们干扰外部位置的 Git 操作。例如

local_desc=$(git describe)
foreign_desc=$(unset $(git rev-parse --local-env-vars); git -C ../foreign-repo describe)

钩子可以通过环境变量、命令行参数和标准输入获取其参数。有关详细信息,请参阅下面每个钩子的文档。

git init 可能会根据其配置将钩子复制到新仓库。有关详细信息,请参阅 git-init[1] 中的“TEMPLATE DIRECTORY”部分。当本文档的其余部分提及“默认钩子”时,指的是 Git 附带的默认模板。

下面将描述当前支持的钩子。

钩子

applypatch-msg

此钩子由 git-am[1] 调用。它接受一个参数,即保存建议的提交日志消息的文件名。以非零状态退出将导致 git am 在应用补丁之前中止。

钩子允许就地编辑消息文件,并可用于将消息规范化为某些项目标准格式。它还可以用于在检查消息文件后拒绝提交。

默认的 applypatch-msg 钩子在启用时会运行 commit-msg 钩子(如果后者已启用)。

pre-applypatch

此钩子由 git-am[1] 调用。它不接受参数,并在应用补丁但提交之前被调用。

如果它以非零状态退出,那么在应用补丁后工作树将不会被提交。

它可以用于检查当前工作树,并在不满足某些测试时拒绝提交。

默认的 pre-applypatch 钩子在启用时会运行 pre-commit 钩子(如果后者已启用)。

post-applypatch

此钩子由 git-am[1] 调用。它不接受参数,并在应用补丁并提交之后被调用。

此钩子主要用于通知,不能影响 git am 的结果。

pre-commit

此钩子由 git-commit[1] 调用,并可通过 --no-verify 选项绕过。它不接受参数,并在获取建议的提交日志消息和进行提交之前被调用。脚本以非零状态退出将导致 git commit 命令在创建提交之前中止。

默认的 pre-commit 钩子在启用时会捕获引入的带有尾随空格的行,并在找到这样的行时中止提交。

如果命令不会启动编辑器来修改提交消息,则所有 git commit 钩子都会以环境变量 GIT_EDITOR=: 调用。

默认的 pre-commit 钩子在启用时(并且 hooks.allownonascii 配置选项未设置或设置为 false)会阻止使用非 ASCII 文件名。

pre-merge-commit

此钩子由 git-merge[1] 调用,并可通过 --no-verify 选项绕过。它不接受参数,并在合并成功执行后、在获取建议的提交日志消息以进行提交之前被调用。脚本以非零状态退出将导致 git merge 命令在创建提交之前中止。

默认的 pre-merge-commit 钩子在启用时会运行 pre-commit 钩子(如果后者已启用)。

如果命令不会启动编辑器来修改提交消息,则此钩子将以环境变量 GIT_EDITOR=: 调用。

如果合并无法自动进行,则需要单独解决冲突并提交结果(请参阅 git-merge[1])。此时,此钩子不会执行,但 pre-commit 钩子(如果已启用)将会执行。

prepare-commit-msg

此钩子由 git-commit[1] 在准备好默认日志消息后、在编辑器启动之前调用。

它接受一个到三个参数。第一个是包含提交日志消息的文件名。第二个是提交消息的来源,可以是:message(如果给出了 -m-F 选项);template(如果给出了 -t 选项或设置了 commit.template 配置选项);merge(如果提交是合并或存在 .git/MERGE_MSG 文件);squash(如果存在 .git/SQUASH_MSG 文件);或 commit,后跟一个提交对象名称(如果给出了 -c-C--amend 选项)。

如果退出状态为非零,git commit 将中止。

此钩子的目的是就地编辑消息文件,并且不会被 --no-verify 选项抑制。非零退出表示钩子失败并中止提交。它不应被用作 pre-commit 钩子的替代品。

Git 附带的示例 prepare-commit-msg 钩子会删除提交模板注释部分中的帮助消息。

commit-msg

此钩子由 git-commit[1]git-merge[1] 调用,并可通过 --no-verify 选项绕过。它接受一个参数,即保存建议的提交日志消息的文件名。以非零状态退出将导致命令中止。

钩子允许就地编辑消息文件,并可用于将消息规范化为某些项目标准格式。它还可以用于在检查消息文件后拒绝提交。

默认的 commit-msg 钩子在启用时会检测重复的 Signed-off-by 尾部,并在找到重复项时中止提交。

post-commit

此钩子由 git-commit[1] 调用。它不接受参数,并在提交完成后被调用。

此钩子主要用于通知,不能影响 git commit 的结果。

pre-rebase

此钩子由 git-rebase[1] 调用,可用于阻止分支被 rebase。该钩子可能带有一个或两个参数。第一个参数是系列从中分叉的上游。第二个参数是要 rebase 的分支,在 rebase 当前分支时未设置。

post-checkout

git-checkout[1]git-switch[1] 在更新工作树后运行时,会调用此钩子。该钩子接受三个参数:上一个 HEAD 的 ref、新的 HEAD 的 ref(可能已更改,也可能未更改),以及一个指示签出是分支签出(更改分支,flag=1)还是文件签出(从索引检索文件,flag=0)的标志。此钩子不能影响 git switchgit checkout 的结果,除了钩子的退出状态将成为这两个命令的退出状态。

git-clone[1] 之后也会运行此钩子,除非使用了 --no-checkout-n)选项。传递给钩子的第一个参数是 null-ref,第二个是新 HEAD 的 ref,标志始终为 1。对于 git worktree add 也是如此,除非使用了 --no-checkout

此钩子可用于执行仓库有效性检查、在不同时自动显示与前一个 HEAD 的差异,或设置工作目录元数据属性。

post-merge

此钩子由 git-merge[1] 调用,当在本地仓库上执行 git pull 时会发生。该钩子接受一个参数,一个状态标志,指定正在进行的合并是否为 squash 合并。此钩子不能影响 git merge 的结果,并且在合并因冲突而失败时不会执行。

此钩子可与相应的 pre-commit 钩子结合使用,以保存和恢复与工作树关联的任何形式的元数据(例如:权限/所有权、ACL 等)。请参阅 contrib/hooks/setgitperms.perl 以获取如何执行此操作的示例。

pre-push

此钩子由 git-push[1] 调用,可用于阻止推送发生。该钩子带有两个参数,提供目标远程的名称和位置,如果未使用命名远程,则两个值将相同。

有关要推送的内容的信息通过以下格式的行提供给钩子的标准输入

<local-ref> SP <local-object-name> SP <remote-ref> SP <remote-object-name> LF

例如,如果运行了命令 git push origin master:foreign,则钩子将收到类似以下的行

refs/heads/master 67890 refs/heads/foreign 12345

尽管会提供完整的对象名称。如果 foreign ref 尚不存在,则 <remote-object-name> 将是全零对象名称。如果要删除 ref,则 <local-ref> 将提供为 (delete),并且 <local-object-name> 将是全零对象名称。如果本地提交是通过除可展开名称(如 HEAD~ 或对象名称)之外的内容指定的,则将按原始方式提供。

如果此钩子以非零状态退出,git push 将中止,不执行任何推送。有关拒绝推送的原因的信息可以通过写入标准错误来发送给用户。

pre-receive

git-receive-pack[1] 响应 git push 并更新其仓库中的引用时,会调用此钩子。在开始更新远程仓库中的 ref 之前,会调用 pre-receive 钩子。其退出状态决定更新的成功或失败。

此钩子对每个接收操作执行一次。它不接受参数,但对于要更新的每个 ref,它会在标准输入上接收一行格式如下:

<old-oid> SP <new-oid> SP <ref-name> LF

其中 <old-oid> 是存储在 ref 中的旧对象名称,<new-oid> 是要存储在新 ref 中的新对象名称,<ref-name> 是 ref 的完整名称。在创建新 ref 时,<old-oid> 是全零对象名称。

如果钩子以非零状态退出,则不会更新任何 ref。如果钩子以零状态退出,更新仍然可以被 update 钩子阻止。

标准输出和标准错误输出都会转发到另一端的 git send-pack,因此您可以简单地 echo 消息给用户。

可以通过环境变量 GIT_PUSH_OPTION_COUNT 读取 git push --push-option=... 命令行的推选项数量,选项本身位于 GIT_PUSH_OPTION_0GIT_PUSH_OPTION_1、…​。如果协商不使用推选项阶段,则不会设置环境变量。如果客户端选择使用推选项但未传输任何选项,则计数变量将设置为零,GIT_PUSH_OPTION_COUNT=0

有关注意事项,请参阅 git-receive-pack[1] 中的“Quarantine Environment”部分。

update

git-receive-pack[1] 响应 git push 并更新其仓库中的引用时,会调用此钩子。在更新远程仓库中的 ref 之前,会调用 update 钩子。其退出状态决定 ref 更新的成功或失败。

该钩子对每个要更新的 ref 执行一次,并接受三个参数:

  • 正在更新的 ref 的名称,

  • 存储在 ref 中的旧对象名称,

  • 以及要存储在新 ref 中的新对象名称。

update 钩子以零退出允许更新 ref。以非零状态退出将阻止 git receive-pack 更新该 ref。

此钩子可用于通过确保对象名称是现有对象名称所指向提交对象的后代提交对象来防止对某些 ref 进行*强制*更新。也就是说,强制执行“仅限快进”策略。

它还可以用于记录旧..新状态。但是,它不知道所有分支的集合,因此在天真使用时,最终会为每个 ref 发送一封电子邮件。 post-receive 钩子更适合此目的。

在限制用户仅通过网络访问 git 命令的环境中,此钩子可用于实现访问控制,而无需依赖文件系统所有权和组 membership。请参阅 git-shell[1] 了解如何使用登录 shell 将用户的访问权限限制为仅 git 命令。

标准输出和标准错误输出都会转发到另一端的 git send-pack,因此您可以简单地 echo 消息给用户。

默认的 update 钩子在启用时(并且 hooks.allowunannotated 配置选项未设置或设置为 false)会阻止推送未注解的标签。

proc-receive

此钩子由 git-receive-pack[1] 调用。如果服务器设置了多值配置变量 receive.procReceiveRefs,并且发送到 receive-pack 的命令具有匹配的引用名称,则这些命令将由此钩子执行,而不是由内部 execute_commands() 函数执行。此钩子负责更新相关引用并将结果报告回 receive-pack

此钩子对每个接收操作执行一次。它不接受参数,但使用 pkt-line 格式协议与 receive-pack 通信,以读取命令、推选项并发送结果。在下面的协议示例中,字母 S 代表 receive-pack,字母 H 代表此钩子。

# Version and features negotiation.
S: PKT-LINE(version=1\0push-options atomic...)
S: flush-pkt
H: PKT-LINE(version=1\0push-options...)
H: flush-pkt
# Send commands from server to the hook.
S: PKT-LINE(<old-oid> <new-oid> <ref>)
S: ... ...
S: flush-pkt
# Send push-options only if the 'push-options' feature is enabled.
S: PKT-LINE(push-option)
S: ... ...
S: flush-pkt
# Receive results from the hook.
# OK, run this command successfully.
H: PKT-LINE(ok <ref>)
# NO, I reject it.
H: PKT-LINE(ng <ref> <reason>)
# Fall through, let 'receive-pack' execute it.
H: PKT-LINE(ok <ref>)
H: PKT-LINE(option fall-through)
# OK, but has an alternate reference.  The alternate reference name
# and other status can be given in option directives.
H: PKT-LINE(ok <ref>)
H: PKT-LINE(option refname <refname>)
H: PKT-LINE(option old-oid <old-oid>)
H: PKT-LINE(option new-oid <new-oid>)
H: PKT-LINE(option forced-update)
H: ... ...
H: flush-pkt

proc-receive 钩子的每个命令可能指向一个伪引用,并且始终将零旧值作为其 old-oid,而 proc-receive 钩子可以更新一个备用引用,并且该备用引用可能已存在一个非零 old-oid。对于这种情况,此钩子将使用“option”指令来报告由前导“ok”指令给出的引用的扩展属性。

此钩子命令的报告应与输入顺序相同。proc-receive 钩子的退出状态仅决定发送给它的命令组的成功或失败,除非使用原子推

post-receive

git-receive-pack[1] 响应 git push 并更新其仓库中的引用时,会调用此钩子。在处理完所有建议的 ref 更新后,如果至少有一个 ref 已更新,则此钩子将在远程仓库上执行一次。

该钩子不接受参数。对于每个成功更新的 ref,它会在标准输入上接收一行,格式与 pre-receive 钩子相同。

此钩子不会影响 git receive-pack 的结果,因为它在实际工作完成后被调用。

它取代了 post-update 钩子,因为它除了 ref 名称外,还可以获取所有 ref 的旧值和新值。

标准输出和标准错误输出都会转发到另一端的 git send-pack,因此您可以简单地 echo 消息给用户。

默认的 post-receive 钩子是空的,但在 Git 发行版的 contrib/hooks 目录中提供了一个示例脚本 post-receive-email,该脚本实现了发送提交电子邮件的功能。

可以通过环境变量 GIT_PUSH_OPTION_COUNT 读取 git push --push-option=... 命令行的推选项数量,选项本身位于 GIT_PUSH_OPTION_0GIT_PUSH_OPTION_1、…​。如果协商不使用推选项阶段,则不会设置环境变量。如果客户端选择使用推选项但未传输任何选项,则计数变量将设置为零,GIT_PUSH_OPTION_COUNT=0

有关其他详细信息,请参阅 git-receive-pack[1] 中的“post-receive”部分。

post-update

git-receive-pack[1] 响应 git push 并更新其仓库中的引用时,会调用此钩子。它在所有 ref 更新完成后在远程仓库上执行一次。

它接受可变数量的参数,每个参数是要更新的 ref 的名称。

此钩子主要用于通知,不能影响 git receive-pack 的结果。

post-update 钩子可以知道哪些 head 被推送了,但它不知道它们的原始值和更新值,所以它不适合用于记录旧..新。如果您需要它们,可以考虑使用 post-receive 钩子。

启用后,默认的 post-update 钩子会运行 git update-server-info 以保持用于哑传输(例如 HTTP)的信息是最新的。如果您发布了一个可以通过 HTTP 访问的 Git 仓库,您应该启用此钩子。

标准输出和标准错误输出都会转发到另一端的 git send-pack,因此您可以简单地 echo 消息给用户。

reference-transaction

此钩子由执行引用更新的任何 Git 命令调用。它在引用事务准备、提交或中止时执行,因此可能会被调用多次。该钩子还支持符号引用更新。

该钩子接受一个参数,即给定引用事务所处的当前状态:

  • "prepared": 所有引用更新都已排队到事务中,并且引用已在磁盘上锁定。

  • "committed": 引用事务已提交,并且所有引用现在都具有各自的新值。

  • "aborted": 引用事务已中止,未执行任何更改,并且已释放锁定。

对于添加到事务中的每个引用更新,钩子将在标准输入上接收一行格式如下:

<old-value> SP <new-value> SP <ref-name> LF

其中 <old-value> 是传递到引用事务中的旧对象名称,<new-value> 是要存储在 ref 中的新对象名称,<ref-name> 是 ref 的完整名称。在强制更新引用而不考虑其当前值时,或当引用需要重新创建时,<old-value> 是全零对象名称。为了区分这些情况,您可以通过 git rev-parse 检查 <ref-name> 的当前值。

对于符号引用更新,<old_value><new-value> 字段可以表示引用而不是对象。引用将以 ref: 前缀表示,例如 ref:<ref-target>

除了“prepared”状态外,钩子的退出状态在任何状态下都被忽略。在“prepared”状态下,非零退出状态将导致事务被中止。在这种情况下,钩子不会以“aborted”状态被调用。

push-to-checkout

git-receive-pack[1] 响应 git push 并更新其仓库中的引用时,并且当推尝试更新当前已签出的分支且 receive.denyCurrentBranch 配置变量设置为 updateInstead 时,会调用此钩子。默认情况下,如果远程仓库的工作树和索引与当前已签出的提交有任何差异,则拒绝此类推;当工作树和索引都与当前提交匹配时,它们将被更新以匹配分支的最新推。此钩子用于覆盖默认行为。

该钩子接收将用于更新当前分支尖端的提交。它可以以非零状态退出以拒绝推(当它这样做时,它不得修改索引或工作树)。或者,它可以对工作树和索引进行任何必要的更改,以将它们带到当前分支的尖端更新到新提交时的所需状态,并以零状态退出。

例如,钩子可以简单地运行 git read-tree -u -m HEAD "$1" 来模拟反向运行的 git fetchgit push,因为 git read-tree -u -m 的双树形式本质上与 git switchgit checkout 切换分支同时保留本地更改(这些更改不会干扰分支之间的差异)相同。

pre-auto-gc

此钩子由 git gc --auto 调用(请参阅 git-gc[1])。它不接受参数,脚本以非零状态退出将导致 git gc --auto 中止。

post-rewrite

此钩子由重写提交的命令调用(git-commit[1] 当使用 --amendgit-rebase[1] 调用时;然而,完整的历史(重)写工具,如 git-fast-import[1]git-filter-repo,通常不会调用它!)。其第一个参数表示调用它的命令:目前是 amendrebase。未来可能会传递其他依赖于命令的参数。

该钩子在标准输入上接收重写提交的列表,格式如下:

<old-object-name> SP <new-object-name> [ SP <extra-info> ] LF

extra-info 再次依赖于命令。如果为空,则前面的空格也将被省略。目前,没有命令传递任何 extra-info

该钩子总是在自动注释复制(请参阅 git-config[1] 中的 "notes.rewrite.<command>")之后运行,因此可以访问这些注释。

以下命令特定注释适用:

rebase

对于 squashfixup 操作,所有被 squashed 的提交都将被列为重写到 squashed 提交。这意味着将有多行共享相同的 new-object-name

保证按照 rebase 处理的顺序列出提交。

sendemail-validate

此钩子由 git-send-email[1] 调用。

它接受这些命令行参数。它们是:1.保存要发送的电子邮件内容的文件的名称。2.保存电子邮件 SMTP 头的文件的名称。

SMTP 头以与传递给用户的邮件传输代理 (MTA) 完全相同的方式传递。实际上,传递给用户 MTA 的电子邮件是 $2 的内容后跟 $1 的内容。

下面显示了一些常见头的示例。请注意大小写和多行制表符结构。

From: Example <from@example.com>
To: to@example.com
Cc: cc@example.com,
 A <author@example.com>,
 One <one@example.com>,
 two@example.com
Subject: PATCH-STRING

以非零状态退出将导致 git send-email 在发送任何电子邮件之前中止。

执行钩子时会设置以下环境变量

GIT_SENDEMAIL_FILE_COUNTER

一个从 1 开始的计数器,每发送一封电子邮件文件(不包括任何 FIFO)会增加一次。此计数器不遵循补丁系列计数器方案。它总是从 1 开始,并在 GIT_SENDEMAIL_FILE_TOTAL 结束。

GIT_SENDEMAIL_FILE_TOTAL

将要发送的文件总数(不包括任何 FIFO)。此计数器不遵循补丁系列计数器方案。无论是否有封面信,它总是等于要发送的文件数。

这些变量可以用于验证补丁系列。

Git 附带的示例 sendemail-validate 钩子会检查所有发送的补丁(不包括封面信)是否可以在不发生冲突的情况下应用到上游仓库的默认分支之上。为在应用给定系列的所有补丁后执行其他验证步骤留出了一些占位符。

fsmonitor-watchman

当配置选项 core.fsmonitor 设置为 .git/hooks/fsmonitor-watchman.git/hooks/fsmonitor-watchmanv2(取决于钩子版本)时,会调用此钩子。

版本 1 接受两个参数:版本号 (1) 和自 1970 年 1 月 1 日午夜以来的经过的纳秒数。

版本 2 接受两个参数:版本号 (2) 和用于标识自该标记以来的更改的令牌。对于 watchman,这将是时钟 ID。此版本必须在标准输出上输出新的令牌,然后是一个 NUL,然后是文件列表。

该钩子应在标准输出上输出自请求时间以来可能已更改的所有工作目录中文件的列表。逻辑应该是包含性的,以免错过任何潜在的更改。路径应相对于工作目录的根,并由单个 NUL 分隔。

包含实际上未更改的文件是可以的。应包含所有更改,包括新创建和删除的文件。重命名文件时,应同时包含旧名称和新名称。

Git 将限制它检查更改的文件以及检查未跟踪文件的目录,这取决于路径名。

告诉 git“所有文件都已更改”的一种优化方法是返回文件名 /

退出状态决定 Git 是否会使用钩子中的数据来限制其搜索。发生错误时,它将回退到验证所有文件和文件夹。

p4-changelist

此钩子由 git-p4 submit 调用。

p4-changelist 钩子在用户编辑了 changelist 消息后执行。它可以通过 --no-verify 选项绕过。它接受一个参数,即保存建议的 changelist 文本的文件名。以非零状态退出将导致命令中止。

钩子允许编辑 changelist 文件,并可用于将文本规范化为某些项目标准格式。它还可以用于在检查消息文件后拒绝提交。

有关详细信息,请运行 git-p4 submit --help

p4-prepare-changelist

此钩子由 git-p4 submit 调用。

p4-prepare-changelist 钩子在准备好默认 changelist 消息后、在编辑器启动之前执行。它接受一个参数,即包含 changelist 文本的文件名。脚本以非零状态退出将中止进程。

钩子的目的是就地编辑消息文件,并且不会被 --no-verify 选项抑制。即使设置了 --prepare-p4-only,也会调用此钩子。

有关详细信息,请运行 git-p4 submit --help

p4-post-changelist

此钩子由 git-p4 submit 调用。

p4-post-changelist 钩子在 P4 中的提交成功后调用。它不接受参数,主要用于通知,不能影响 git p4 submit 操作的结果。

有关详细信息,请运行 git-p4 submit --help

p4-pre-submit

此钩子由 git-p4 submit 调用。它不接受任何参数,也不从标准输入读取任何内容。脚本以非零状态退出将阻止 git-p4 submit 的启动。可以使用 --no-verify 命令行选项绕过它。运行 git-p4 submit --help 获取详细信息。

post-index-change

在 read-cache.c 的 do_write_locked_index 中写入索引时调用此钩子。

传递给钩子的第一个参数是正在更新的工作目录的指示符。“1”表示工作目录已更新,“0”表示工作目录未更新。

传递给钩子的第二个参数是索引是否已更新以及 skip-worktree 位是否可能已更改的指示符。“1”表示 skip-worktree 位可能已更新,“0”表示它们未更新。

钩子运行时,只有一个参数应设置为“1”。钩子运行时传递“1”、“1”是不可能的。

另请参阅

GIT

Git[1] 套件的一部分