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

名称

githooks - Git 使用的钩子

概要

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

描述

钩子是您可以放置在 `hooks` 目录中的程序,用于在 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 钩子,在启用时——并且当 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] 调用,可用于阻止分支被变基。此钩子可能带有一个或两个参数。第一个参数是系列所分叉的上游。第二个参数是被变基的分支,在变基当前分支时未设置。

post-checkout

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

除非使用 --no-checkout (-n) 选项,否则它也会在 git-clone[1] 之后运行。传递给钩子的第一个参数是 null-ref,第二个是新 HEAD 的引用,标志始终为 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

尽管将提供完整的对象名称。如果远程引用尚不存在,<remote-object-name> 将是全零对象名称。如果要删除引用,<local-ref> 将作为 (delete) 提供,并且 <local-object-name> 将是全零对象名称。如果本地提交是由除可展开名称(例如 HEAD~ 或对象名称)之外的其他内容指定的,它将按原始给定方式提供。

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

pre-receive

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

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

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

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

如果钩子以非零状态退出,则不会更新任何引用。如果钩子以零状态退出,则单个引用的更新仍可由 update 钩子阻止。

标准输出和标准错误输出都会转发到另一端的 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 并更新其仓库中的引用时。在更新远程仓库上的引用之前,会调用 update 钩子。其退出状态决定了引用更新的成功或失败。

此钩子为每个要更新的引用执行一次,并接受三个参数:

  • 正在更新的引用的名称,

  • 引用中存储的旧对象名称,

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

update 钩子以零退出允许引用被更新。以非零状态退出会阻止 git receive-pack 更新该引用。

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

它还可以用于记录旧..新状态。但是,它不知道分支的完整集合,因此如果简单使用,最终会为每个引用发送一封电子邮件。 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 钩子的每个命令都可以指向一个伪引用,并且其旧对象 ID 始终为零,而 proc-receive 钩子可以更新一个备用引用,并且该备用引用可能已经存在且具有非零的旧对象 ID。对于这种情况,此钩子将使用“option”指令来报告由开头的“ok”指令给出的引用的扩展属性。

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

post-receive

此钩子由 git-receive-pack[1] 调用,当它响应 git push 并更新其仓库中的引用时。此钩子在远程仓库上执行一次,在所有建议的引用更新都处理完毕并且至少有一个引用作为结果被更新之后。

此钩子不接受参数。它通过标准输入接收成功更新的每个引用的一行,格式与 pre-receive 钩子相同。

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

这取代了 post-update 钩子,因为它除了获取所有引用的名称外,还能获取它们的旧值和新值。

标准输出和标准错误输出都会转发到另一端的 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 并更新其仓库中的引用时。它在所有引用都更新后在远程仓库上执行一次。

它接受可变数量的参数,每个参数都是实际更新的引用的名称。

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

post-update 钩子可以识别哪些头被推送,但它不知道它们的原始值和更新值,因此它不是记录旧..新状态的好地方。 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-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 并更新其仓库中的引用时,以及当推送尝试更新当前检出的分支并且 receive.denyCurrentBranch 配置变量设置为 updateInstead 时。如果远程仓库的工作树和索引与当前检出的提交有任何不同,默认情况下会拒绝此类推送;当工作树和索引都与当前提交匹配时,它们会更新以匹配新推送的分支尖端。此钩子用于覆盖默认行为。

此钩子接收将用于更新当前分支尖端的提交。它可以通过非零状态退出以拒绝推送(此时,它不得修改索引或工作树)。或者,它可以在当前分支尖端更新为新提交时,对工作树和索引进行任何必要的更改,使其达到所需状态,并以零状态退出。

例如,钩子可以简单地运行 git read-tree -u -m HEAD "$1",以模拟以 git push 反向运行的 git fetch,因为 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 之一。将来可能会传递更多依赖于命令的参数。

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

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

extra-info 再次取决于命令。如果为空,则前面的空格也会被省略。目前,没有命令传递任何 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 的内容。

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

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 钩子在用户编辑完变更列表消息后执行。可以通过 --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 提交操作的结果。

运行 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