I am interested in how git actually knows it is in a git repo. My first inkling is it just climbs up the folder structure to the root (which may involve permission errors). Is it documented anywhere?
I am interested in how git actually knows it is in a git repo. My first inkling is it just climbs up the folder structure to the root (which may involve permission errors). Is it documented anywhere?
The rule of thumb is that Git just looks up the file path to find a .git directory, but that's not really true. As Edward Thomson asks, what about bare repos with no .git directory?
Here's the gory details. It starts in setup_git_directory_gently_1 searching for Git directories.
If GIT_DIR or --git-dir is set it uses that. Else it begins searching from either the current working directory, or the paths given with -C.
.git file with the first line gitdir: <path> it will use that path..git/ (a non-bare repository) is a Git directory, it uses that../ (a bare repository) is a Git directory, it uses that.GIT_CEILING_DIRECTORIES.GIT_DISCOVERY_ACROSS_FILESYSTEM is not true and it has hit a filesystem boundary.It is a Git directory if ALL of these are true, from is_git_directory.
HEAD contains a syntactically valid reference.objects directory, or whatever GIT_OBJECT_DIRECTORY is set to.refs directory.It is a non-bare Git directory if it is a Git directory AND its parent is .git.
Here is the minimum to convince Git it has found a "Git directory".
$ ls -lR
.:
total 4
-rw-r--r-- 1 schwern staff 27 Dec 29 14:50 HEAD
dr-xr-xr-x 2 schwern staff 64 Dec 29 14:50 objects
drwxr-xr-x 2 schwern staff 64 Dec 29 14:50 refs
./objects:
total 0
./refs:
total 0
$ cat HEAD
ref: refs/heads/yarblockos
Accessible objects and refs directories, and a HEAD file with a syntactically valid reference.
If that is in a .git directory then it is a non-bare repository.
That's it. You can also tell it explicitly where all the pieces are, with options or environment variables.
The full docs are spelled out kind of piecemeal, you can search git help git for "discovery" to find the --git-dir option on the git command itself and, later on, an exact specification of its normal discovery discussed under the GIT_DISCOVERY_ACROSS_FILESYSTEM environment variable's docs, which is used to extend that discovery's scope.
Edit: there's two possible conditions: you could start inside a work tree, or you could start inside an actual repository (like the one conventionally kept in a .git dir at the top of a work tree). I answered for the "inside a work tree" case, Schwern answered for the "inside a repository proper" case, tl;dr: yes, it walks back up the directory nesting, until it finds either a work tree or a repository. A work tree has a .git with a repository in it, a repository has refs and objects and HEAD as described in that answer.
A Git repo is a directory with a .git directory in it. Git can recourse backwards until it encounters that folder, or cannot go back anymore.