Git
英语 ▾ 主题 ▾ 最新版本 ▾ git-receive-pack 最后更新于 2.43.0

名称

git-receive-pack - 接收推送到存储库的内容

概要

git receive-pack <git-dir>

描述

git send-pack 调用,并使用从远程端馈送的信息更新存储库。

此命令通常不会被最终用户直接调用。协议的 UI 在 git send-pack 端,该程序对旨在用于将更新推送到远程存储库。对于拉取操作,请参阅 git-fetch-pack[1]

此命令允许在远程端创建和快进 sha1 ref(heads/tags)(严格来说,这是 git-receive-pack 运行的本地端,但对于坐在 send-pack 端的用户来说,它是更新远程端。困惑了吗?)。

在 Documentation/howto 目录中,还有其他使用 update 和 post-update 钩子的实际示例。

git-receive-pack 遵守 receive.denyNonFastForwards 配置选项,该选项指示它是否应拒绝对 ref 的更新,前提是它们不是快进。

有许多其他 receive.* 配置选项可用于调整其行为,请参阅 git-config[1]

选项

<git-dir>

要同步到的存储库。

--http-backend-info-refs

git-http-backend[1] 用于提供 $GIT_URL/info/refs?service=git-receive-pack 请求。请参阅 git-upload-pack[1] 中的 --http-backend-info-refs

PRE-RECEIVE 钩子

在更新任何 ref 之前,如果 $GIT_DIR/hooks/pre-receive 文件存在且可执行,则将调用它一次,不带任何参数。钩子的标准输入将是每个要更新的 ref 的一行

sha1-old SP sha1-new SP refname LF

refname 值相对于 $GIT_DIR;例如,对于 master 头,它是“refs/heads/master”。每个 refname 之前的两个 sha1 值是 refname 在更新前后对应的对象名称。要创建的 ref 将具有 sha1-old 等于 0{40},而要删除的 ref 将具有 sha1-new 等于 0{40},否则 sha1-old 和 sha1-new 应该是存储库中的有效对象。

当接受签名推送(请参阅 git-push[1])时,签名推送证书将存储在一个 blob 中,并且可以查询环境变量 GIT_PUSH_CERT 以获取其对象名称。请参阅 post-receive 钩子的描述以获取示例。此外,证书将使用 GPG 进行验证,并且结果将使用以下环境变量导出

GIT_PUSH_CERT_SIGNER

签署推送证书的密钥所有者的名称和电子邮件地址。

GIT_PUSH_CERT_KEY

签署推送证书的密钥的 GPG 密钥 ID。

GIT_PUSH_CERT_STATUS

使用与 git log 系列命令中的 %G? 格式相同的助记符来表示推送证书的 GPG 验证状态(请参阅 git-log[1])。

GIT_PUSH_CERT_NONCE

该进程要求签名者在推送证书中包含的随机字符串。如果这与推送证书中“nonce”头记录的值不匹配,则可能表明证书是有效的证书,正在从单独的“git push”会话中重播。

GIT_PUSH_CERT_NONCE_STATUS
UNSOLICITED

“git push --signed”在未要求它发送时发送了一个随机字符串。

MISSING

“git push --signed”未发送任何随机字符串头。

BAD

“git push --signed”发送了一个伪造的随机字符串。

OK

“git push --signed”发送了我们要求它发送的随机字符串。

SLOP

“git push --signed”发送的随机字符串与我们现在要求它发送的随机字符串不同,但在之前的会话中发送过。请参阅 GIT_PUSH_CERT_NONCE_SLOP 环境变量。

GIT_PUSH_CERT_NONCE_SLOP

“git push --signed”发送的随机字符串与我们现在要求它发送的随机字符串不同,但在不同的会话中发送过,该会话的开始时间与当前会话的开始时间相差这么多秒。只有当 GIT_PUSH_CERT_NONCE_STATUS 显示 SLOP 时才有意义。另请阅读 git-config[1] 中有关 receive.certNonceSlop 变量的内容。

此钩子在更新任何 refname 之前以及执行任何快进检查之前被调用。

如果 pre-receive 钩子以非零退出状态退出,则不会执行任何更新,并且 update、post-receive 和 post-update 钩子也不会被调用。这对于在不支持更新时快速退出很有用。

请参阅下面关于隔离环境的说明。

UPDATE 钩子

在更新每个 ref 之前,如果 $GIT_DIR/hooks/update 文件存在且可执行,则将为每个 ref 调用它一次,并带三个参数

$GIT_DIR/hooks/update refname sha1-old sha1-new

refname 参数相对于 $GIT_DIR;例如,对于 master 头,它是“refs/heads/master”。两个 sha1 参数是 refname 在更新前后对应的对象名称。请注意,钩子在更新 refname 之前被调用,因此 sha1-old 为 0{40}(表示尚未存在此类 ref),或者它应该与 refname 中记录的内容匹配。

如果钩子希望禁止更新指定的 ref,则应以非零状态退出。否则,它应该以零状态退出。

此钩子的成功执行(零退出状态)并不能确保 ref 将真正被更新,它只是一个先决条件。因此,从该钩子发送通知(例如电子邮件)不是一个好主意。请考虑改用 post-receive 钩子。

POST-RECEIVE 钩子

在所有 ref 更新(或尝试更新)之后,如果任何 ref 更新成功,并且如果 $GIT_DIR/hooks/post-receive 文件存在且可执行,则将调用它一次,不带任何参数。钩子的标准输入将是每个成功更新的 ref 的一行

sha1-old SP sha1-new SP refname LF

refname 值相对于 $GIT_DIR;例如,对于 master 头,它是“refs/heads/master”。每个 refname 之前的两个 sha1 值是 refname 在更新前后对应的对象名称。已创建的 ref 将具有 sha1-old 等于 0{40},而已删除的 ref 将具有 sha1-new 等于 0{40},否则 sha1-old 和 sha1-new 应该是存储库中的有效对象。

接受签名推送后,可以检查 GIT_PUSH_CERT* 环境变量,就像在 pre-receive 钩子中一样。

使用此钩子,可以轻松地生成邮件来描述存储库的更新。此示例脚本会为每个 ref 发送一封邮件,其中列出了推送到存储库的提交,并将签名推送的推送证书(具有良好的签名)记录到日志记录服务中

#!/bin/sh
# mail out commit update information.
while read oval nval ref
do
	if expr "$oval" : '0*$' >/dev/null
	then
		echo "Created a new ref, with the following commits:"
		git rev-list --pretty "$nval"
	else
		echo "New commits:"
		git rev-list --pretty "$nval" "^$oval"
	fi |
	mail -s "Changes to ref $ref" commit-list@mydomain
done
# log signed push certificate, if any
if test -n "${GIT_PUSH_CERT-}" && test ${GIT_PUSH_CERT_STATUS} = G
then
	(
		echo expected nonce is ${GIT_PUSH_NONCE}
		git cat-file blob ${GIT_PUSH_CERT}
	) | mail -s "push certificate from $GIT_PUSH_CERT_SIGNER" push-log@mydomain
fi
exit 0

此钩子调用的退出代码将被忽略,但是非零退出代码将生成错误消息。

请注意,当此钩子运行时,refname 可能没有 sha1-new。如果其他用户在 git-receive-pack 更新 ref 后但钩子能够评估它之前修改了 ref,则很容易发生这种情况。建议钩子依赖于 sha1-new 而不是 refname 的当前值。

POST-UPDATE 钩子

在所有其他处理完成后,如果至少更新了一个 ref,并且如果 $GIT_DIR/hooks/post-update 文件存在且可执行,则将调用 post-update,并带有一系列已更新的 ref。这可用于实现任何存储库范围的清理任务。

此钩子调用的退出代码将被忽略;此时,git-receive-pack 要做的唯一事情就是退出自身。

例如,如果存储库已打包并通过哑传输提供服务,则可以使用此钩子运行 git update-server-info

#!/bin/sh
exec git update-server-info

隔离环境

receive-pack 接收对象时,它们将被放置到 $GIT_DIR/objects 目录中的一个临时“隔离”目录中,并且只有在 pre-receive 钩子完成之后才迁移到主对象存储中。如果推送在此之前失败,则将完全删除临时目录。

这具有一些用户可见的影响和注意事项

  1. 由于传入包、缺少对象或 pre-receive 钩子问题导致的推送失败不会留下任何磁盘数据。这通常有助于防止重复的失败推送填满您的磁盘,但可能会使调试变得更加困难。

  2. pre-receive 钩子创建的任何对象都将在隔离目录中创建(并且仅在成功时才会迁移)。

  3. pre-receive 钩子**绝不能**更新任何引用指向隔离的对象。其他访问存储库的程序将无法看到这些对象(如果 pre-receive 钩子失败,这些引用将变得损坏)。出于安全考虑,来自 pre-receive 内部的任何引用更新将自动被拒绝。

GIT

git[1] 套件的一部分

scroll-to-top