19

我的服务器上有一个非裸存储库(dirs /home/andrew/web 和 /home/andrew/web/.git),将 receive.denyCurrentBranch 设置为忽略并创建 post-receive 钩子:

#!/bin/sh
GIT_WORK_TREE=/home/andrew/web git checkout -f

当我运行 sh .git/hooks/post-receive 时,一切正常。但是当我从我的电脑推送时,我收到了这个错误:

remote: fatal: Not a git repository: '.'

有没有办法解决这个问题?最终无需切换裸回购?

谢谢

编辑:这是我的新接收后挂钩。为什么会这样,已在接受的答案中进行了描述。

echo "\nChecking out $PWD"
GIT_DIR=/home/andrew/web/.git
GIT_WORK_TREE=/home/andrew/web git checkout -f
4

1 回答 1

30

[编辑,2017 年 2 月:这个旧答案仍然受到一点影响,所以让我们添加一些注释。(1) 这种实时更新通常是一个坏主意:确保您知道为什么要这样做,并且不会破坏自己的工作。(2) 在 Git 2.3 之后,您现在可以配置receive.denyCurrentBranchupdateInstead,以及 Git 2.4 及更高版本中的挂钩调整。有关详细信息,请参阅文档git config ]

post-receive 挂钩运行时$GIT_DIR设置为.。这会导致 git 查找./HEAD,./refs/heads/master等,而不是.git/HEAD,.git/refs/heads/master等。但是,由于您没有$PWD对钩子进行任何更改(如图所示),因此钩子将在.git子目录 ( /home/andrew/web/.git) 中运行,因此这个失败非常神秘:.实际上将是一个有效的 git 存储库。

避免硬编码路径名的一种标准技巧是cd ..; git checkout -f用作接收后挂钩。这就是设置$GIT_DIR成为问题的地方,因为在cd ..钩子运行之后(仍然假设这种情况)/home/andrew/web,当然此时,$GIT_DIR应该是.git而不是.. 对此的标准修复只是取消设置GIT_DIR(将其设置为.git也可以)。

不过,如图所示,您的 post-receive 钩子对我来说效果很好(通过适当的硬编码路径更改)。然后我再次从类似 Unix 的机器上推送,而不是 PC。是否有可能发生其他事情,将目录从.git子目录中更改出来?你可以做一些类似echo running in $PWD在钩子里的事情来看看你在哪里。

于 2012-05-09T09:49:36.420 回答