在git钩子中操作repo时,-C和--git dir之间的差异
我正在编写一个GitPostReceiveHook,它将克隆一个单独的repo作为部署的一部分。它将repo克隆到某个文件夹,并使用后续git命令中的在git钩子中操作repo时,-C和--git dir之间的差异,git,githooks,Git,Githooks,我正在编写一个GitPostReceiveHook,它将克隆一个单独的repo作为部署的一部分。它将repo克隆到某个文件夹,并使用后续git命令中的-C选项将目录设置为签出repo的目录(如中所述) 当从命令行手动运行钩子时,钩子会按预期工作,但是当钩子由git运行时(即当接收到推送时),命令会失败,原因是致命:不是git存储库:'.。当我把-C换成--git dir时,它就工作了 这非常容易复制,创建一个裸repogit init--bare并使用以下内容创建一个可执行挂钩: #!/bin/
-C
选项将目录设置为签出repo的目录(如中所述)
当从命令行手动运行钩子时,钩子会按预期工作,但是当钩子由git运行时(即当接收到推送时),命令会失败,原因是致命:不是git存储库:'.
。当我把-C
换成--git dir
时,它就工作了
这非常容易复制,创建一个裸repogit init--bare
并使用以下内容创建一个可执行挂钩:
#!/bin/bash
set -xe
SOME_REPO_URL=???? # Some repo that is not this one
repopath=/tmp/somerepo
git clone $SOME_REPO_URL $repopath
# 1: This fails when run through the git hook
git -C $repopath checkout -b somebranch HEAD~1
# 2: This works every time
# git --git-dir $repopath/.git checkout -b somebranch HEAD~1
从命令行运行脚本将按预期工作,但是当您推到repo时,钩子将失败。注释1
和取消注释2
在这两种情况下都有效
我找不到任何文件表明这是预期行为-请解释
这是Ubuntu16.04上的git 2.7.4。以下内容之间的文字差异:
git-C目录git子命令…
以及:
git--git dir目录git子命令…
前端安装程序使用操作系统级的“将目录更改为”操作(OS.chdir
来自Python,chdir()
来自C等等)作为第一个操作,并为第二个操作设置环境变量$git\u DIR
。在任何一种情况下,它都会找到子命令并运行它。(请注意,实际上您可以同时执行这两项操作。),包括多个-C
选项的效果以及-C
和-git dir
之间的交互
然而,这只是将问题向下推了一个层次:现在您需要知道git checkout
(位于git--exec path
目录中)对$git_DIR
的作用与对当前工作目录的作用不同。直接的答案是:
GIT\u DIR
如果设置了
GIT\u DIR
环境变量,那么它将指定一个路径,以代替存储库基础的默认.GIT
。--git dir
命令行选项也设置此值
这就是我们的优势所在。在编写Git钩子时,您必须意识到Git可能会为您设置一些环境变量。如果$GIT_DIR
设置为相对路径名,并且您没有覆盖它,并且确实更改了目录,那么您将更改所有GIT子命令定位存储库的方式。因此,您必须取消设置它(以获取默认的$GIT_DIR
-未设置行为),或者显式地将其设置为绝对路径(以在目录更改期间保留),或者显式地将其设置为其他某个存储库的相对或绝对路径,具体取决于您想要的行为
请注意,
--work tree
设置了$GIT\u work\u tree
,还有其他类似的变量,但至少在迄今为止的所有GIT版本中,$GIT\u DIR
是唯一一个“为您预设”(或“为您的烦恼”:-))在Git hooks中。知道在hooks中设置了Git_DIR
环境变量可能会有所帮助。您可能希望在运行checkout命令时取消设置它。值得一提的是,如果您一直在使用古老版本的git:“git-C directory”选项是在中引入的(因为在git 1.8.3中我得到了“Unknown option:-C”)