社内の共有フォルダをgit管理する方法(git separate-git-dir)

遅まきながらgit initやcloneにあるseparate-git-dirオプションを使いました。
ちょろっとググると、Dropboxでの応用があるみたいですね。
このエントリではトリッキーかもしれませんが、git initでの違う応用を紹介します。

separate-git-dirを使うと何ができるの?

チームで使っているWindowsの共有フォルダをローカルで版管理しています。
これは、個人的なバックアップと差分チェックを兼ねたものです。


この共有フォルダは、
諸事情によりPJに関係ない人でもアクセスできるフォルダなので、
gitレポジトリ(.gitディレクトリ)を作りたくありません。
PJに関係ないファイルということと、レポジトリを壊されたくないからです。
共有フォルダの中身を、rsyncでローカルへ同期してから版管理していました。


separate-git-dirを使うことで、
共有フォルダとは別の場所へレポジトリを作ることができますので、
ローカルにレポジトリを作ることで、当初の目的を果たせます。


最初に注意です。
本エントリは共有フォルダを直接、作業フォルダにする方法を書いています。
これは言い換えると、gitのcheckoutやresetコマンドで、
共有ファイル上の変更を虚空の闇に葬り去ることが可能であることを言っています。
くれぐれもメンバに恨まれないように。。。

共有フォルダをgit管理する方法

$ git --version
git version 1.8.1.msysgit.1
$


worktreeを別のホスト上にある共有フォルダとします。
# zドライブへ割り当てているとします。

$ mkdir -p /z/path/to/worktree
$ cd /z/path/to/worktree/
$ git init --separate-git-dir=/c/route/to/repo
Initialized empty Git repository in c:/route/to/repo/
$

これで共有フォルダworktreeとは別に、
ローカルPCにあるrepoへレポジトリを作成できました。


worktree、repoの双方でレポジトリに対するアクセスが可能です。

$ pwd
/z/path/to/worktree
$ touch foo
$ git add foo
$ git status --short
A  foo
$ cd /c/route/to/repo/
$ git status --short
A  foo
$


initしたタイミングで、worktreeに「.git」というファイルが作られます。
.gitファイルにはレポジトリのパスが書かれています。
worktree側でもレポジトリにアクセスできるのは、この内容を伝っているのでしょう。

$ ls -a /z/path/to/worktree/
./  ../  .git  foo
$ cat /z/path/to/worktree/.git
gitdir: /c/route/to/repo
$

つまりworktreeにある.gitファイルは、
共有フォルダ→ローカルホストのレポジトリへのアクセスに必要です。

共有フォルダにPJとは関係のないファイルを置きたくない

ここまでの手順では、共有フォルダ側に.gitファイルが置かれていることになります。
.gitディレクトリがファイルになっただけです。
レポジトリの破壊は免れるでしょうが、PJとは関係の無いファイルがあることに変わりはありません。
どうしましょう。


結論から言うと、共有フォルダにある.gitファイルは消してしまっても版管理はできました。
ただし共有フォルダ側からレポジトリアクセスはできなくなります。

$ pwd
/z/path/to/worktree/
$ rm .git
$ git status
fatal: Not a git repository (or any of the parent directories): .git
$


この状態では、レポジトリ側から一方的に共有フォルダの変更が見えます。

$ pwd
/z/path/to/worktree/
$ touch bar
$ ls -a
./  ../  bar  foo
$ cd /c/route/to/repo/
$ git status --short
A  foo
?? bar
$


版管理もできます。

$ pwd
/c/route/to/repo
$ git commit --quiet -m 'initial'
$ git add bar
$ git commit --quiet -m 'modified'
$ git log --abbrev-commit --oneline master
5a6c4df modified
a96ad94 initial
$ ls -a /z/path/to/worktree/
./  ../  bar  foo
$ git checkout --quiet HEAD^
$ git rev-parse HEAD
a96ad94174f4559ab4bfffddd49ba184c9b9324a
$ ls -a /z/path/to/worktree/
./  ../  foo
$

ただしコマンドラインで作業していて困る点は、
レポジトリ側で補完が効かないことです。
これはまあ仕方ないですね。

.gitファイルを消したのにレポジトリ側から変更が見える理由

これはレポジトリのconfigファイルにcore.worktreeというオプションが設定されているためです。

$ git config --local --get core.worktree
/z/path/to/worktree
$

これが、ローカルホスト→共有フォルダのレポジトリへのアクセスに必要となるようです。