## 名称

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`说时才有意义`SLOP`。`receive.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-receive`hook，接受签字推后。

使用这个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]