Git
英语 ▾ 主题 ▾ 最新版本 ▾ 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] 中的“模板目录”部分。当本文档的其余部分提到“默认钩子”时,它指的是与 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 钩子(如果已启用)会防止使用非 ASCII 文件名(当 hooks.allownonascii 配置选项未设置或设置为 false 时)。

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] 调用,可用于阻止分支被重新基底。此钩子可能被调用一次或两次参数。第一个参数是系列分支的源分支。第二个参数是被重新基底的分支,当重新基底当前分支时,它不会被设置。

post-checkout

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

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

此钩子可用于执行存储库有效性检查、自动显示与之前 HEAD 的差异(如果不同)或设置工作目录元数据属性。

post-merge

此钩子由 git-merge[1] 调用,当在本地存储库上执行 git pull 时会发生这种情况。此钩子接受一个参数,一个状态标志,指定执行的合并是否是压缩合并。此钩子无法影响 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 做出反应并在其存储库中更新引用时。在开始更新远程存储库中的引用之前,会调用 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 钩子阻止单个 ref 的更新。

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

可以在 git push --push-option=... 的命令行上提供的推送选项数量从环境变量 GIT_PUSH_OPTION_COUNT 中读取,选项本身可以在 GIT_PUSH_OPTION_0GIT_PUSH_OPTION_1、…​ 中找到。如果协商不使用推送选项阶段,则不会设置环境变量。如果客户端选择使用推送选项,但没有传输任何选项,则计数变量将设置为零,GIT_PUSH_OPTION_COUNT=0

有关一些注意事项,请参阅 git-receive-pack[1] 中的“隔离环境”部分。

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 命令的环境中,此钩子可用于实现访问控制,而无需依赖文件系统所有权和组成员资格。有关如何使用登录 shell 限制用户访问权限以仅限于 git 命令,请参阅 git-shell[1]

标准输出和标准错误输出都会转发到另一端的 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 钩子的每个命令都可能指向一个伪引用,并且始终将其旧 oid 设为零,而 proc-receive 钩子可能会更新一个备用引用,并且该备用引用可能已经存在,并具有非零旧 oid。对于这种情况,此钩子将使用“选项”指令来报告由前导“ok”指令给出的引用的扩展属性。

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

post-receive

此钩子由 git-receive-pack[1] 调用,当它对 git push 做出反应并在其存储库中更新引用时。如果至少更新了一个 ref 作为结果,则此钩子将在远程存储库上执行一次,在处理所有提议的 ref 更新之后执行。

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

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

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

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

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

可以在 git push --push-option=... 的命令行上提供的推送选项数量从环境变量 GIT_PUSH_OPTION_COUNT 中读取,选项本身可以在 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 钩子确实获得了 ref 的原始值和更新后的值。如果您需要它们,可以考虑使用它。

启用后,默认的 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-name> 是引用的完整名称。当强制更新引用,无论其当前值如何,或者当要新建引用时,<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 并更新其存储库中的引用(s)时,以及当推送尝试更新当前签出的分支并且 receive.denyCurrentBranch 配置变量设置为 updateInstead 时,此钩子会被调用。默认情况下,如果远程存储库的工作树和索引与当前签出的提交有任何差异,则此类推送将被拒绝;当工作树和索引都与当前提交匹配时,它们将更新以匹配分支的新推送顶端。此钩子用于覆盖默认行为。

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

例如,钩子可以简单地运行 git read-tree -u -m HEAD "$1" 来模拟 git fetch,它以相反的方向运行 git 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] 在使用 --amend 调用时和 git-rebase[1];但是,完整的历史记录(重新)写入工具,如 git-fast-import[1]git-filter-repo 通常不会调用它!)。它的第一个参数表示调用它的命令:目前是 amendrebase 之一。将来可能会传递更多与命令相关的参数。

钩子从 stdin 接收重写提交的列表,格式为

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

extra-info 再次取决于命令。如果它为空,则前面的 SP 也被省略。目前,没有命令传递任何 extra-info

钩子始终在自动笔记复制发生后运行(参见 git-config[1] 中的 "notes.rewrite.<command>"),因此可以访问这些笔记。

以下特定于命令的注释适用

rebase

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

这些提交保证按 rebase 处理它们的顺序列出。

sendemail-validate

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

它采用以下命令行参数。它们分别是:1. 存放要发送的电子邮件内容的文件名称。2. 存放电子邮件 SMTP 标头的文件名称。

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

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

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

执行钩子时,将设置以下环境变量。

GIT_SENDEMAIL_FILE_COUNTER

一个以 1 为基数的计数器,每个存放要发送的电子邮件的文件(不包括任何 FIFO)都会增加 1。此计数器不遵循补丁系列计数器方案。它始终从 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。此版本必须将新令牌输出到 stdout,后跟一个 NUL,然后是文件列表。

钩子应将工作目录中所有可能自请求时间以来已更改的文件的列表输出到 stdout。逻辑应具有包容性,以确保不遗漏任何潜在的更改。路径应相对于工作目录的根目录,并用单个 NUL 分隔。

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

Git 将根据给定的路径名限制它检查更改的文件以及检查未跟踪文件的目录。

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

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

p4-changelist

此钩子由 git-p4 submit 调用。

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

钩子被允许编辑变更列表文件,可以用来将文本规范化为某种项目标准格式。它也可以用来在检查完消息文件后拒绝提交。

运行 git-p4 submit --help 以获取详细信息。

p4-prepare-changelist

此钩子由 git-p4 submit 调用。

p4-prepare-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] 套件的一部分

scroll-to-top