タイトルどおりのトピックです
Gitには便利なことにgit-worktree(1)が存在する。しかし、普通にgit-cloneしてきたレポジトリの中でgit-worktreeで他のブランチをチェックアウトしてくると、当然だがgitとしてはそのチェックアウトしてきた別のブランチのあるディレクトリがまるっとuntracking filesに出てきて、大変ジャマなことこの上ない、という欠点があるのである……
解決方法
git-clone(1)にはいくつかcloneの方法がある。--mirror
や--bare
などである。今回は--bare
を取り上げる。
mkdir my_project
cd my_project
git clone --bare git@github.com/orumin/my_project .bare
このようにcloneすると、my_project/.bare配下にgitのレポジトリ本体だけがcloneされる。レポジトリで管理されているファイル群やコミットも全てgitレポジトリでgit objectとして管理されている状態にのみなっており、ファイルの実体はどこにもcheckoutされていない状態となる
cd my_project
echo "gitdir: .bare" > .git
git worktree add main
こうすると、実際はgitレポジトリではないmy_projectディレクトリ直下に居るときでもgitレポジトリとしてgitコマンドが認識してくれるので、git-worktree(1)
も利用できる状態となっている。この場合、ここでgit worktree add main
をすることで、my_project/main
というディレクトリにorigin/main
のブランチがcheckoutされて、gitで管理しているファイル群にアクセスできるようになる。同様に、他のブランチに関してもmy_project
直下でgit worktree add
すればディレクトリの形でぽこぽこブランチがcheckoutできる、というわけである。
また、
git worktree -b add_new_feature feature_branch origin/main
などとすれば、origin/main
をベースとして新規ブランチadd_new_feature
を切り、これをfeature_branch
というディレクトリ名でworktreeを作成してくれる。べんり!
remote branchをfetchできない!
以上でよいように思うが、git-pull
などをするとき途端に困った事実に直面する。remote branchをfetchできないのである。これは、--bare
ではなく普通にgit-clone
するときに設定される値が、git clone --bare
では設定されないためである。
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
簡単に言えば、この設定を追加すればoriginとして設定しているremote repositoryに対してgit-fetch
したときちゃんとlocal repositoryに紐付けてダウンロードしてくれるようになる。これで、オールオッケー!
ブランチごとにディレクトリを作成する……?
でもこれってSVNみたいじゃないですか?
はい……でも便利だし……