简体   繁体   中英

fatal: Not a git repository: '.'

I have a valid git repository named /tmp/A . When I cd to the /tmp/A and run any git command from bash it works good, but when I run git commands from callCommand call in haskell programm I get error:

fatal: Not a git repository: '.'

If I run in callCommand pwd and ls -la before git command, like:

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

It shows that it is at right path /tmp/A and ls shows that repository exists and has .git directory, but git returns error.

What wrong I do?

Upd.

ls output is

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

Upd. Upd.

Program which fails is called from hook post-receive of cloned git repository. When run same program not from hook of this repository, it works fine. Why self cloning repository from hook does not works?

TL;DR: you probably want unset GIT_DIR at the front of your script (well, however Haskell spells this operation).


The issue here is that while /tmp/A is a sensible Git repository, the actual repository itself is in the .git sub-directory. That is, /tmp/A/ is the work-tree and /tmp/A/.git is the repository proper .

In normal operation, we run git subcommand arguments ... , eg, git status or git commit -m message from our work-trees . The work-tree contains a .git directory or, in some cases, 1 a .git file. The top-level git command checks for .git , finds it, and says aha, the repository is ./.git . Or, it does not find .git , so it looks one level up—eg, from /tmp/A it would climb one level to /tmp itself, and check there for .git . This repeats until some sort of stopping point. 2

In all cases, this search process must either stop successfully—by finding the repository proper—or else git subcommand dies with the fatal: Not a git repository ... message. Now comes the critical, and hidden in plain sight, secret: At this point, the top-level git command sets an environment variable named GIT_DIR to contain the path name of the actual repository. It then runs the sub-command, which uses $GIT_DIR to locate the repository. In our normal use-case, where we are in /tmp/A and /tmp/A contains a .git directory, this sets $GIT_DIR to /tmp/A/.git and the sub-commands all work.

But in your case, $GIT_DIR is already set. Specifially, it's set to . . So now the top-level git command stops searching . It just verifies that $GIT_DIR is valid and names a Git repository, or dies with the fatal error message. Since /tmp/A isn't a repository—it's really /tmp/A/.git —this causes the problem.

Unsetting the environment variable turns the search back on, fixing the problem. You can also use --git-dir as an argument, or set a correct value in $GIT_DIR . Note that the same rules apply with $GIT_WORK_TREE : the --work-tree argument sets $GIT_WORK_TREE , and if you don't use that and $GIT_WORK_TREE isn't set, the front-end git command uses its climb up the file system tree to a .git directory or file code to find the root of your work-tree. So if $GIT_DIR or $GIT_WORK_TREE are set when you run git subcommand , Git obeys them unless you override them with --git-dir and/or --work-tree .

Hooks always have $GIT_DIR set. They may or may not have $GIT_WORK_TREE set as well. Most of them run in the top level of the work-tree, but, as the githooks documentation notes, pre-receive , update , post-receive , post-update , and push-to-checkout all run in $GIT_DIR .


1 The .git -as-a-file trick is used by both submodules and added work-trees, in modern Git. Git 1.7 and early 1.8 left submodules with embedded .git directories, and does not support added work-trees.

2 The obvious stopping point is upon reaching / , when there is nowhere left to climb. However, Git is by default careful, at least on Unix and Unix-like systems, to avoid climbing through a mount point . Mount points allow you to graft different file system layers and/or storage pools into a single tree-structured hierarchy. Typically /tmp itself might be a memory file system, for instance, and large systems might isolate "system storage" ( / and the like) from "user storage" ( /home ). Docker uses mount points to restructure file systems in the docker image, and so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM