gitコマンドがgitリポジトリを探す順番
概要: 多くのgitコマンドは特定のgitリポジトリに対する操作であるから、現在位置から対応するリポジトリを発見する必要がある。環境変数かコマンドラインオプションで指定された場合を除き、gitはまず ./.git
ファイル、 ./.git/
ディレクトリ、 .
の3つを試し、それでだめなら再帰的に親ディレクトリを検索する。
gitリポジトリの検索結果を表示する
git rev-parse --git-dir
git rev-parse --show-toplevel
gitコマンドがgitリポジトリを探す順番
gitが処理をするときはまず、gitdirとworktreeと呼ばれる2つのディレクトリの位置を同定する必要がある。
gitコマンドがgitリポジトリを探す処理は、 setup.c
の中の setup_git_directory
→setup_git_directory_gently
→setup_git_directory_gently_1
に記述されている。
まず、環境変数 GIT_DIR
が設定されている場合は、これがそのままgitdirとして使われる。 (git
コマンド全体のオプションである --git-dir
は単に GIT_DIR
をその場で設定するオプションである。) この場合のworktreeの発見手順は複雑だが、例えば GIT_WORK_TREE
が設定されているときはこれがそのまま採用される。
GIT_DIR
が設定されていない場合はまず以下の順にチェックする。
./.git
という通常ファイルがあり、内容がgitdir:
で始まっている。また続く文字列は別のディレクトリへのパスになっており、そのディレクトリはgitdirにふさわしい構造を持っている。このとき、この時点での.
がworktreeになる。./.git/
というディレクトリがあり、そのディレクトリはgitdirにふさわしい構造を持っている。このとき、この時点での.
がworktreeになる。.
というディレクトリがあり、そのディレクトリはgitdirにふさわしい構造を持っている。このときこのリポジトリはbare扱いで、worktreeは設定されない。
以上のチェックをしてもgitdirが見つからない場合は、ひとつ上のディレクトリにcdして同じ探索を繰り返す。ただし、以下の条件で探索を打ち切る。
/
または、GIT_CEILING_DIRECTORIES
で指定されたディレクトリまで到達した。- 異なるファイルシステムに到達したが、
GIT_DISCOVERY_ACROSS_FILESYSTEM
が設定されていなかった。
ところで、gitdirにふさわしい構造かどうかは is_git_directory
で判定されている。これは次の3つ全てがあるときにgitdirと判定している。
- 適切にフォーマットされた
./HEAD
ファイル。ただし適切にフォーマットされているとは次のいずれかの条件を満たすことをいう - ディレクトリ
objects/
が存在する。ただし、GIT_OBJECT_DIRECTORY
環境変数が存在するなら、objects/
のかわりにこの環境変数の中身が使われる。 - ディレクトリ
refs/
が存在する。
まとめ
上の発見手順からわかるように、non-bareリポジトリ内でも、特に .git
内からコマンドを呼び出している場合はbareリポジトリに準ずる扱いを受ける。(worktreeの内部ではないと判定される。)