4
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

gitリポジトリのルートディレクトリを得るスクリプト

はじめに

Gitリポジトリのルートディレクトリを知りたいことがあって、調べるとだいたいgit rev-parse --show-toplevelが出てきます。しかしこのコマンドでは、submoduleになっているリポジトリにて親リポジトリのルートディレクトリを得ることはできません。

たとえばmainリポジトリがsubmoduleとしてsubリポジトリを含んだケースの場合、以下のようになります。

$ cd /work
$ git clone http://xxx main
$ tree main
main
`-- sub
$ cd main: git rev-parse --show-toplevel
/work/main
$ cd sub: git rev-parse --show-toplevel
/work/main/sub

ここではsubディレクトリにおいても親のリポジトリルート/work/mainを得るスクリプトを紹介します。

Git 2.13以降

Git 2.13から--show-superproject-working-treeなるオプションが追加されました。これはsubmodule内から親リポジトリのルートを表示するオプションです。しかしsubmodule外では何も出力されないので--show-toplevelと一緒に使って両方表示させた上でhead -1で1行目を抜いてきます。

git rev-parse --show-superproject-working-tree --show-toplevel | head -1

headしなかった場合の出力はこんな感じです。

$ cd main; git rev-parse --show-superproject-working-tree --show-toplevel
/work/main
$ cd sub; git rev-parse --show-superproject-working-tree --show-toplevel
/work/main
/work/main/sub

Git 2.13より前

例えばRHEL7/CentOS7ではGitはいまだに1.8.3.1です。ビルドスクリプトとして配布したい場合など、2.13以降を期待するのが難しい場合もありますが、このようにすればルートディレクトリが得られます。

readlink -f $(git rev-parse --git-dir) | sed 's/\/\.git.*//g'

--git-dirオプションは.gitディレクトリのパスを表示するオプションです。submodule内から見た場合も.gitディレクトリは親リポジトリの.git/modules/subになるので、sedで/.git以降を削ることで親リポジトリのルートが得られます。

sedしなかった場合の出力は以下です。

$ cd main: readlink -f $(git rev-parse --git-dir)
/work/main/.git
$ cd sub: readlink -f $(git rev-parse --git-dir)
/work/main/.git/modules/sub

ここでreadlink -fしているのは--git-dirの微妙な挙動を補正するためです。
--git-dirは通常.gitディレクトリの絶対パスを表示しますが、リポジトリルートで実行した場合に限り.gitだけを出力します。そのため絶対パスに揃えるためにreadlink -fを使っています。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
4
Help us understand the problem. What are the problem?