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

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

fatal: Not a git repository: '.'

如果我在callCommandpwd命令之前运行ls -lagit/tmp/A命令,例如:
callCommand $ "pwd; ls -la; git status"

它表明,在正确路径ls.git显示存储库存在并且具有ls目录,但是Git返回错误。
我做错什么了?
升级版。
post-receive输出为
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存储库的hook调用失败的程序。当不从这个存储库的钩子运行同一个程序时,它可以正常工作。
为什么hook中的自我克隆存储库不起作用?


最佳答案:

TL;DR:您可能希望脚本前面有unset GIT_DIR(不过Haskell拼写这个操作)。
这里的问题是,虽然/tmp/A是一个合理的Git存储库,但实际的存储库本身在.git子目录中。也就是说,/tmp/A/是工作树,/tmp/A/.git是正确的存储库。
在正常操作中,我们从工作树运行git subcommand arguments ...,例如git statusgit commit -m message。工作树包含一个.git目录,或者在某些情况下,包含一个.git文件。顶级git命令检查.git,找到它,然后说aha,存储库是./.git。或者,它找不到.git,所以它看起来是一个级别-例如,从/tmp/A它将爬一个级别到/tmp本身,并在那里检查.git。一直重复到某个停止点。2
在所有情况下,此搜索过程必须通过找到合适的存储库而成功停止,否则git subcommand将随着fatal: 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:参数sets--work-tree也适用相同的规则,如果不使用该参数并且未设置$GIT_WORK_TREE,则前端的$GIT_WORK_TREE命令使用其爬升文件系统树到git目录或文件代码来查找工作树的根。因此,如果在运行.git时设置了$GIT_DIR$GIT_WORK_TREE,则Git会遵从它们,除非您使用git subcommand和/或--git-dir覆盖它们。
钩子总是有--work-tree设置。它们也可以设置或不设置$GIT_DIR。它们大多运行在工作树的顶层,但正如the githooks documentation所述,$GIT_WORK_TREEpre-receiveupdatepost-receivepost-updatepush-to-checkout都运行在$GIT_DIR中。
在现代Git中,子模块和添加的工作树都使用.git-as-a-file技巧。Git 1.7和早期的1.8留下了嵌入.git目录的子模块,并且不支持添加的工作树。
2当无处可爬时,最明显的停止点是到达/。但是,Git在默认情况下是非常小心的,至少在Unix和类Unix系统上是这样,以避免爬过装载点。挂载点允许您将不同的文件系统层和/或存储池移植到一个树状结构的层次结构中。例如,通常/tmp本身可能是一个内存文件系统,大型系统可能将“系统存储”(/等)与“用户存储”(/home)隔离开来。Docker使用挂载点来重组Docker映像中的文件系统,等等。

公众号