致命:不是git存储库:“。”

时间:2019-03-22 11:01:15

标签: linux git

我有一个名为git的有效/tmp/A存储库。 当我cd/tmp/A并从bash运行任何git命令时,效果很好,但是当我从git运行callCommand命令时,在haskell程序中调用得到错误:

fatal: Not a git repository: '.'

如果我在callCommand命令之前在pwd ls -lagit中运行,例如:

callCommand $ "pwd; ls -la; git status"

它表明它在正确的路径/tmp/A上,ls表明该存储库存在并且具有.git目录,但是git返回错误。

我怎么了?

更新。

ls的输出是

drwxrwxr-x 11 xxx xxx 4096 Mar 22 11:44 .
drwxrwxr-x  3 xxx xxx 4096 Mar 22 11:44 ..
drwxrwxr-x  8 xxx xxx 4096 Mar 22 11:44 .git
-rw-rw-r--  1 xxx xxx  270 Mar 22 11:44 .gitignore
drwxrwxr-x  7 xxx xxx 4096 Mar 22 11:44 dir2
drwxrwxr-x  8 xxx xxx 4096 Mar 22 11:44 dir1
drwxrwxr-x  9 xxx xxx 4096 Mar 22 11:44 test

已更新。更新。

从克隆的git存储库的钩子post-receive中调用失败的程序。当不是从该存储库的钩子运行同一程序时,它可以正常工作。 为什么从钩子进行自我克隆存储库不起作用?

1 个答案:

答案 0 :(得分:1)

TL; DR:您可能希望在脚本的开头使用unset GIT_DIR(不过,Haskell拼写了此操作)。


这里的问题是,尽管/tmp/A 一个明智的Git存储库,但实际的存储库本身却位于.git子目录中。也就是说,/tmp/A/工作树,而/tmp/A/.git存储库专有

在正常操作中,我们从工作树运行git subcommand arguments ...,例如git statusgit commit -m message。工作树包含一个.git目录,或者在某些情况下包含 1 一个.git文件。顶级git命令检查.git并找到它,然后说 aha,存储库./.git 。或者,它找不到.git,因此它看起来向上了一层,例如,它从/tmp/A爬到了/tmp本身的一层,并在那里检查了.git。重复此操作直到出现某种停止点。 2

在所有情况下,该搜索过程必须都必须成功停止(通过找到适当的存储库),或者git subcommandfatal: Not a git repository ...消息一起死亡。现在是关键的,并且是秘密的:这时,顶层git命令设置了一个名为GIT_DIR的环境变量,以包含实际存储库的路径名。 然后运行子命令,该命令使用$GIT_DIR来定位存储库。在我们的常规用例中,我们在/tmp/A中,并且/tmp/A包含一个.git目录,这会将$GIT_DIR设置为/tmp/A/.git,并且所有子命令都工作。

但是对于您而言,已经设置了 $GIT_DIR具体来说,它已设置为.。因此,现在顶级git命令停止搜索。它只是验证$GIT_DIR是有效的并命名一个Git存储库,或者死于fatal错误消息。由于/tmp/A不是存储库(实际上是/tmp/A/.git),因此会引起问题。

取消设置环境变量将重新打开搜索,从而解决了该问题。您也可以使用--git-dir作为参数,或在$GIT_DIR中设置正确的值。请注意,$GIT_WORK_TREE适用相同的规则:--work-tree参数设置$GIT_WORK_TREE,如果您不使用它而$GIT_WORK_TREE不是集,前端git命令使用其爬升文件系统树到.git目录或文件代码中,以找到工作树的根目录。因此,如果在运行$GIT_DIR时设置了$GIT_WORK_TREEgit subcommand ,则Git会遵循它们,除非您用--git-dir和/或{{1 }}。

挂钩始终设置为--work-tree。他们可能也未设置$GIT_DIR。其中大多数运行在工作树的顶层,但是,如the githooks documentation所述,$GIT_WORK_TREEpre-receiveupdatepost-receive和{ {1}}全部在post-update中运行。


1 在现代Git中,子模块和添加的工作树都使用push-to-checkout即文件操作。 Git 1.7和1.8早期版本的子模块带有嵌入的$GIT_DIR目录,并且不支持添加的工作树。

2 最明显的停止点是到达.git时,无处可爬。但是,默认情况下,至少在Unix和类似Unix的系统上,Git会非常小心,以避免爬过挂载点。挂载点使您可以将不同的文件系统层和/或存储池移植到单个树结构层次结构中。例如,通常.git本身可能是一个内存文件系统,而大型系统可能会将“系统存储”(/等)与“用户存储”(/tmp)隔离开。 Docker使用挂载点来重组Docker映像中的文件系统,等等。