git worktree コマンドと運用
やりたいこと
- 複数のブランチを手元に置きたい
- でもそれぞれ git clone するのは無駄に思う
概念: git worktree を活用する
git worktree コマンドを使えば良い(例はあえて冗長な名前にしてみた)
bash
# repo1 に branch-1 が既に居るとする
git clone <repo-url> repo1
cd repo1
git worktree add ../repo1-branch-1-dir branch-1
cd ../repo1-branch-1-dir
一覧するには
bash
git worktree list
削除するには
bash
git worktree remove ../repo1-branch-1-dir
この通りに作ると以下の構成になりそうだが、どれが依存してるか分かりづらくなりそう(と思ったけど命名次第かも)
txt
repo1/ ← これが本体。中の .git/ が他で参照されているので、ここを消すと他が壊れる
repo1-branch-1/
repo1-branch-2/
※ ハマりポイントメモ: 同じブランチで別名 worktree を作ったりはできない
応用: トピックブランチも考えた場合
構成
- チームで開発中の本線のブランチを phase-N としたとして
- 各開発者が機能追加のために作ったトピックブランチを feature/phase-N/sugoi-henkou とする
- 紛らわしくなるので phase-N ディレクトリでは switch しないことにする
txt
repo1/ ← これはただのフォルダ
main/ ← これが本体。(中の .git/ を)消すと他が壊れる
phase-01/
phase-02/ ← チームで開発中の本線ブランチ(リモートが既にある)
phase-02-sugoi-henkou/ ← 機能追加のためのトピックブランチ(リモートは push 時に作る)
コマンド
1. worktree 作成
bash
mkdir repo1
cd repo1
git clone <repo-url> main
# worktree 作成 (リモートの origin/phase-N ブランチを元にローカルに phase-N ブランチを作成している)
cd main
git worktree add ../phase-01 -b phase-01 origin/phase-01
git worktree add ../phase-02 -b phase-02 origin/phase-02
# worktree の upstream 設定 (デフォルトの push, pull 対象を決めている)
cd ../phase-01
git branch --set-upstream-to=origin/phase-01 phase-01
cd ../phase-02
git branch --set-upstream-to=origin/phase-02 phase-02
# トピックブランチ作成
cd ../main
git fetch origin
git worktree add ../phase-02-sugoi-henkou -b feature/phase-02/sugoi-henkou origin/phase-02
※ ちなみに、git fetch は、どの worktree でやっても、最新化される(同じ main の origin を見ているから)
2. 開発
bash
cd ../phase-02-sugoi-henkou
(いろいろ修正する..)
git add -A
git commit -m '...'
3-1. 本線への合流(GitHubの場合)
(1) リモートのトピックブランチを作成(push)
bash
cd ../phase-02-sugoi-henkou
git push origin feature/phase-02/sugoi-henkou
- 以降を
git pushだけで済ませたい場合は--set-upstreamオプションをつける - この例では 1 回プッシュしたら終わりなので、つけないでおく
(2) プルリクエスト (GitHubの場合のみ必要)
bash
gh pr create --base phase-02 --head feature/phase-02/sugoi-henkou --title "sugoi henkou" --body "sugoi henkou wo kuwae mashita"
(3) 取り込み
ここは Web 画面でやるものかも
gh pr list --base phase-02 # ここで変更番号が 15 だったとする
gh pr view 15 # --web 引数をつければ Web 画面で確認可
gh pr merge 15
3-2. 本線への合流(gitの場合)
bash
cd ../phase-02
# 最新化(他の人の変更があったら取り込まれるということ)
git fetch origin
git pull --ff-only origin phase-02
# トピックブランチの変更を取り込む
git merge --no-ff feature/phase-02/sugoi-henkou
# 本線をリモートに適用!
git push origin phase-02 # git push で省略可能だが、事故防止で明示する
余談: 他に考えた案(bare repo 作る版)
この構成もきれいかも、と思ったが、うまく origin/ を見れるように設定できなかったのと、ちょっとトリッキーな気もするので、概念だけ残しておくが、不採用とする。
txt
repo1/ ← これはただのフォルダ(.git/ が存在することでぱっと見リポジトリに見える)
.git/ ← bare repo。 これが本体。消すと他が壊れる
branch-1-dir/
branch-2-dir/
案3のコマンド例
bash
mkdir repo1
cd repo1
git clone --bare <repo-url> .git
git --git-dir=.git fetch --all
git --git-dir=.git worktree add main main
git --git-dir=.git worktree add branch-1-dir branch-1
git --git-dir=.git worktree add branch-2-dir branch-2
以下広告