いつから.git
がディレクトリだと錯覚していた?
$ ls -la foo
total 8
drwxr-xr-x 3 pasela wheel 102 11 2 18:31 ./
drwxrwxrwt 29 root wheel 986 11 2 18:31 ../
-rw-r--r-- 1 pasela wheel 29 11 2 18:31 .git
$ cat foo/.git
gitdir: /tmp/foo.git
というわけで、実はgitは.git
の中身を別の場所で管理することができます。
この作業は手動でいじってもできなくはないですが、git init
やgit clone
に--separate-git-dir=<git dir>
を指定することで自動的にやってくれます。
cd /tmp
$ git init --separate-git-dir=/tmp/foo.git foo
Initialized empty Git repository in /tmp/foo.git/
こうすると、.git
にはリポジトリのパスが書かれたファイルが作成され、
$ cat foo/.git
gitdir: /tmp/foo.git
/tmp/foo.git
に管理ファイルが生成されます。
$ ls -la /tmp/foo.git
total 24
drwxr-xr-x 9 pasela wheel 306 11 2 18:45 ./
drwxrwxrwt 29 root wheel 986 11 2 18:45 ../
-rw-r--r-- 1 pasela wheel 23 11 2 18:45 HEAD
-rwxr--r-- 1 pasela wheel 140 11 2 18:45 config*
-rw-r--r-- 1 pasela wheel 73 11 2 18:45 description
drwxr-xr-x 11 pasela wheel 374 11 2 18:45 hooks/
drwxr-xr-x 3 pasela wheel 102 11 2 18:45 info/
drwxr-xr-x 4 pasela wheel 136 11 2 18:45 objects/
drwxr-xr-x 4 pasela wheel 136 11 2 18:45 refs/
そして/tmp/foo.git/config
にはワークツリーの位置を示すcore.worktree
が設定されます。
$ cat /tmp/foo.git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
worktree = /tmp/foo
ignorecase = true
これらの値はコマンド実行時にグローバルオプションの--git-dir=<path>
, --work-tree=<path>
や、環境変数のGIT_DIR
, GIT_WORK_TREE
でも指定できます。
gitリポジトリに関連したツールを作る際は、.git
がファイルであることも考慮したほうがよいでしょう。
git worktree (2016-01-08追記)
Git 2.5から追加されたgit worktreeはこの仕組みが利用されているようです。
$ git worktree add ../bar master
$ ls -lA ../bar
合計 8
-rw-rw-r-- 1 pasela pasela 36 1月 8 14:35 2016 .git
-rw-rw-r-- 1 pasela pasela 4 1月 8 14:35 2016 foo.txt
$ cat ../bar/.git
gitdir: /tmp/foo/.git/worktrees/bar
$ ls -lA .git/worktrees/bar
合計 24
-rw-rw-r-- 1 pasela pasela 20 1月 8 14:35 2016 HEAD
-rw-rw-r-- 1 pasela pasela 6 1月 8 14:35 2016 commondir
-rw-rw-r-- 1 pasela pasela 14 1月 8 14:35 2016 gitdir
-rw-rw-r-- 1 pasela pasela 12 1月 8 14:35 2016 gitfile
-rw-rw-r-- 1 pasela pasela 137 1月 8 14:35 2016 index
drwxrwxr-x 2 pasela pasela 4096 1月 8 14:35 2016 logs/
gitdirの指す先が/tmp/foo/.git
ではなくworktree用のディレクトリを指していて、何やら特殊な構造を持っている模様。