git worktreeの説明を読んだとき、自分のプロジェクトディレクトリと同じ階層にワークツリーディレクトリが作成されることに、危うさを感じました。
例えば、feature-loginというブランチ名でワークツリーを作ろうものなら、以下のようになります。
~/projects/
├── projA/
├── projB/
└── feature-login/ ← どのプロジェクトの???
気になった点
- ワークツリーがプロジェクトと同階層に増える
- どのリポジトリのものか分かりづらい
- 別プロジェクトで同じブランチ名を使うと衝突しそう
そこでchatGPTと相談して、「bare repository」と「worktree」を分離する構成を採用しました。
採用した構成
projA
├── repo.git/ ← bare repository
└── worktrees/
├── main/ ← worktree
├── feature-a/
└── fix-bug
この構成のメリット
- worktree がプロジェクト内に閉じる
- main も含めて全ブランチを同じ扱いにできる
- 複数プロジェクトで衝突しない
.worktree ディレクトリを使う運用もありますが、main ブランチも worktree として扱いたかったため、この構成にしました。
自分用のメモとしてこの記事を投稿します。
セットアップ方法
bare repositoryを作成する
すでにgithubにリポジトリを作成している場合
mkdir myproj
cd myproj
git clone --bare <repo-url> repo.git
ローカルから新規作成する場合
worktreeを作成する元となるブランチが必要なので、コミットが入ったmainブランチを作成します。
通常リポジトリ.gitは不要になるので、bare repositoryを作成した後に削除します。
mkdir myproj
cd myproj
git init
git switch -c main
echo "# myproj" > README.md
git add .
git commit -m "Initial commit"
git clone --bare . repo.git
rm -rf .git
worktree用ディレクトリを作成する
mkdir worktrees
main worktreeを追加する
git --git-dir=repo.git worktree add worktrees/main main
これで通常の作業ディレクトリとして利用できます。
新しいworktreeを作成
mainブランチをベースに新しいfeatureブランチでworktreeを作る例:
git --git-dir=repo.git worktree add -b feature-login worktrees/feature-login main
worktreeを削除
git --git-dir=repo.git worktree remove worktrees/feature-login
git --git-dir=repo.git worktree prune
git --git-dir=repo.git branch -d feature/login # branchも削除
※ prune はgit内の古いメタ情報削除のため推奨。
worktreeの一覧
git --git-dir=repo.git worktree list
エイリアス設定(おすすめ)
いちいち、git --git-dir=repo.gitするのが大変なので、エイリアスを作成します。
alias gw='git --git-dir=repo.git'
以降は
gw worktree list
まとめ
通常の worktree 運用では、プロジェクトディレクトリと同じ階層にワークツリーのディレクトリができてしまいますが、
この構成では、bare repository = Git の本体、worktree = 作業環境
という役割分離が明確になり、ワークツリーがプロジェクトディレクトリの外に散らかりません。
この投稿が誰かのお役に立てれば幸いです。