Subscribed unsubscribe Subscribe Subscribe

カレントディレクトリがGitリポジトリ下か否か判定する

zshのソースは
zsh / Code / [5e4db6]
このへん。

if VCS_INFO_check_com ${vcs_comm[cmd]} && ${vcs_comm[cmd]} rev-parse --is-inside-work-tree &> /dev/null ; then
...

という具合に判定されている。
Determine if directory is under git control - Stack Overflow
こちらでもgit rev-parseのリターンコードを見るのが良い、というようなことが書いてある。
ということでシェルスクリプト的には

if git rev-parse 2> /dev/null; then
    echo true;
else
    echo false;
fi

という感じで判定するのが良さそう。gitリポジトリ下でない場合は標準エラー出力にメッセージが出るので要らないなら捨てる。

蛇足

git rev-parseコマンドは"--is-inside-work-tree"オプションで".gitディレクトリ内にいるか否か"の判定ができるので便利。

$ git rev-parse
fatal: Not a git repository (or any of the parent directories): .git
$ git init
Initialized empty Git repository in /path/to/.git/
$ git rev-parse --is-inside-work-tree
true
$ cd .git
$ git rev-parse --is-inside-work-tree
false

蛇足その2

結局コレって副作用の無いgitコマンドを実行して、gitリポジトリ下じゃない場合にエラー吐いて死ぬか否かを判定する、ってことなのでgit rev-parseじゃなくても問題はないわけで例えばgit statusとかでも良いのですよね。
gitリポジトリ下か否かの判定は、主にsetup_git_directory_gently_1関数で行われている模様。ここで"正しい.gitディレクトリ"があるかどうかを見ているようだ。大抵はsetup_git_directory()関数が呼ばれたときに内部でこの判定を行い、正しい.gitディレクトリが見つからなかったときにエラーを吐いて死ぬようになっているようだ。builtin command群ではRUN_SETUPフラグがオプションに定義されているとコマンド本体に処理が渡る前にそれが呼ばれる。
git/git.c at v1.7.9.4 · gitster/git · GitHub
ので、commandsで定義されているbuiltin commandたちのうちRUN_SETUPが含まれているものはgitリポジトリ下じゃない場合にだいたいエラー吐いて死ぬはず。

$ git blame
fatal: Not a git repository (or any of the parent directories): .git
$ git gc
fatal: Not a git repository (or any of the parent directories): .git
$ git log
fatal: Not a git repository (or any of the parent directories): .git
$ git status
fatal: Not a git repository (or any of the parent directories): .git
$ git tag
fatal: Not a git repository (or any of the parent directories): .git

なのでこのへんのコマンドも判定に使えることは使える、と思う。
ちなみにgit rev-parseRUN_SETUPフラグは立っていなくて、処理の本体となるcmd_rev_parse内でsetup_git_directory()を呼んで判定を行っているようだ。
git/rev-parse.c at v1.7.9.4 · gitster/git · GitHub
builtin command本体まで処理が届いているか否かはTRACEを見てみると分かる。

$ GIT_TRACE=1 git status
fatal: Not a git repository (or any of the parent directories): .git
$ GIT_TRACE=1 git rev-parse
trace: built-in: git 'rev-parse'
fatal: Not a git repository (or any of the parent directories): .git

だから何だ、って話だけど…