我的 post-receive,一个 git 挂钩,有两个命令不起作用

my post-receive, a git hook, with two commands doesn't work

我有三个 git 存储库:

  1. 我的 git 服务器上的裸存储库
  2. 我笔记本电脑上的本地存储库(A)(我在这台机器上开发网页。)
  3. 托管服务器上的本地存储库 (B)(我将其用作 http 服务器。)

我在裸存储库上设置了一个 post-receive,一个服务器端挂钩,让存储库 (B) 从裸存储库中拉出,并让 git 服务器在以下时间发送通知电子邮件我从存储库 (A) 提交并推送到裸存储库。我在裸仓库上制作的post-receive文件如下:

#!/bin/sh
ssh -l MYUSER -i PRIVKEY www.HOSTINGSERVER.com "cd GITDIRECTORY;git pull"
. $(dirname [=12=])/post-receive-email

我还在裸仓库上设置了环境变量:

git config hooks.mailinglist "MyMailAddress"
git config hooks.announcelist "MyMailAddress"
git config hooks.emailprefix "FooBar"
echo FooBar > description

当我提交并推送到裸存储库时,我希望存储库 (B) 被拉取并且 git 服务器通过 post-receive-email 发送了一封通知电子邮件,但是 post-receive 没有像我希望的那样工作。它有存储库 (B) 拉取但没有 git 服务器发送任何电子邮件。我在 git 服务器的日志中没有看到任何电子邮件错误。

当我注释掉 post-receive 的 ssh 部分时,我收到了一封电子邮件。当我注释掉 post-receive-email 部分时,存储库 (B) 正确提取。当 ssh 部分和 post-receive-email 部分都处于活动状态时,post-receive 只有存储库 (B) 拉取并且没有发送任何电子邮件。

我不知道为什么当 ssh 部分和 post-receive-email 部分同时存在时 post-receive 不能像我预期的那样工作。

欢迎任何提示和评论。 提前谢谢你。

TL;DR: ssh -n.

背景资料:

  1. post-receive 挂钩在其标准输入上获取输入。阅读 stdin,您将在 the githooks documentation.

    中描述的形式中为每个更新的参考获取一行
  2. 所有接收 stdin 输入的 Git 钩子都是在管道上进行的。 (我认为这是一个坏主意——他们应该将输入作为在临时文件上打开的文件描述符来接收——但这是一场单独的战斗。即使情况并非如此,你仍然需要另一个技巧。)

  3. 读取管道上可用的输入会消耗该输入。一旦阅读,它就消失了。

    (顺便说一下,这就是为什么 read 内置的 shell 如此低效:有必要 一次读取一个字节的输入, 因此只消耗 read 将要读取的内容。)

考虑到这一点,考虑 ssh 命令,以及它的 documentation 中的这段摘录:

-n     Redirects stdin from /dev/null (actually, prevents reading from stdin).

那么,如果你 运行 ssh 没有 -n 会怎样?当然,它会读取标准输入。但是......它会读到多少much?好吧,严格来说,这取决于:ssh 运行s 几个进程 and/or 线程,如果远程端有大量的标准输入和命令 运行,就会发生竞争执行速度很快,但一般来说,ssh读取的量是all of stdin.

现在参考背景事实 #3,并回答问题:当 ssh 完成时,stdin 上还剩下什么?

现在,想一想发送电子邮件的 post-receive 挂钩的作用。它必须,必然地,读取其标准输入以查看更新了哪些引用。它将在其标准输入中获得哪些数据?

如果您阻止 ssh 读取(并因此消耗)所有输入,post-receive 挂钩将能够读取(并消耗,但现在这无关紧要了) more) 所有输入,因此功能正常。