git receive-pack

优质
小牛编辑
125浏览
2023-12-01

名称

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

概要

git-receive-pack <directory>

描述

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

该命令通常不由最终用户直接调用。该协议的用户界面位于git send-pack侧面,程序对旨在用于将更新推送到远程存储库。对于拉操作,请参阅git-fetch-pack。

该命令允许在远端创建和快速转发sha1 refs(heads/tags)(严格来说,这是本地最终git-receive-pack运行,但对于坐在发送包端的用户,它正在更新遥远的。)

在Documentation/howto目录中还有其他一些使用update和post-update钩子的真实例子。

git-receive-pack 尊重receive.denyNonFastForwards配置选项,该选项告诉它是否应该拒绝对ref的更新,如果它们不是快进的。

其他一些receive.* config选项可用于调整其行为,请参阅git-config。

选项

<directory>

要同步到的存储库。

预接收hook

在任何ref被更新之前,如果$ GIT_DIR/hooks/pre-receive文件存在并且是可执行文件,它将被调用一次而没有参数。钩子的标准输入将被更新为每个参考线一行:

sha1-old SP sha1-new SP refname LF

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

当接受一个签名推送(参见git-push [1])时,签名推送证书存储在一个blob中,并且GIT_PUSH_CERT可以查询其对象名称的环境变量。有关post-receive示例,请参阅hook的说明。另外,使用GPG验证证书,并使用以下环境变量导出结果:

GIT_PUSH_CERT_SIGNER

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

GIT_PUSH_CERT_KEY

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

GIT_PUSH_CERT_STATUS

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

GIT_PUSH_CERT_NONCE

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

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说时才有意义SLOPreceive.certNonceSlop在git-config中阅读有关变量。

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

如果预接收hook以非零退出状态退出,则不会执行更新,更新,接收后和更新后钩子也不会被调用。如果更新不被支持,这可以快速救助。

请参阅下面的隔离环境注意事项。

更新hook

在更新每个ref之前,如果$ GIT_DIR/hooks/update文件存在并且是可执行文件,则每个ref都会调用一次,其中包含三个参数:

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

refname参数是相对于$ GIT_DIR; 例如,对于主人的头,这是“refs/heads/master”。这两个sha1参数是更新之前和之后refname的对象名称。请注意,钩子在更新refname之前被调用,所以sha1-old是0 {40}(意味着还没有这样的ref),或者它应该匹配在refname中记录的内容。

如果要禁止更新指定的参考值,则hook应该以非零状态退出。否则它应该以零退出。

hook的成功执行(零退出状态)并不能确保引用实际上会被更新,它只是一个先决条件。因此,从这个hook发送通知(例如电子邮件)并不是一个好主意。考虑使用post-receive hook来代替。

接收后hook

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

sha1-old SP sha1-new SP refname LF

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

GIT_PUSH_CERT*环境变量可以被检查,就如同在pre-receivehook,接受签字推后。

使用这个hook,很容易生成描述存储库更新的邮件。此示例脚本每次发送一条邮件消息,列出推送到存储库的提交,并将具有良好签名的签名推送推送证书记录到记录器服务:

#!/bin/sh
# mail out commit update information.while read oval nval refdo        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 anyif test -n "${GIT_PUSH_CERT-}" && test ${GIT_PUSH_CERT_STATUS} = Gthen        (
                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

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

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

更新后的hook

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

该hook调用的退出代码被忽略;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钩子不得更新任何指向隔离对象的参考。访问存储库的其他程序将无法看到对象(并且如果预接收挂钩失败,则这些引用会损坏)。为了安全起见,任何来自内部的ref更新都会pre-receive被自动拒绝

另请参阅

git-send-pack[1], gitnamespaces[7]