git worktree を「別リポジトリ」ではなく「同じリポジトリの追加ワークスペース」として扱う。
新規 worktree の作成と切り替え、削除と復帰をこの skill でまとめて扱う。
基本方針
- まず現在位置のリポジトリルートを取得する。
- 以後のコマンドは、目的の worktree パスを
workdirに指定して実行する。 - デフォルトでは、worktree はリポジトリ親ディレクトリ直下に
"<repo>-wt-<branch-slug>"という名前で作る。 - ユーザーが基点ブランチや配置先を指定しない限り、現在の
HEADから新規ブランチを作る。 - 未コミット変更は新しい worktree へ引き継がれない。必要なら先に commit か stash を行う。
- 強制削除 (
git worktree remove --forceやgit branch -D) は、ユーザーが明示したときだけ行う。
事前確認
ROOT=$(git rev-parse --show-toplevel)
REPO=$(basename "$ROOT")
MAIN_ROOT=$(git worktree list --porcelain | awk '/^worktree /{print $2; exit}')
ROOTは現在の worktree のルート。MAIN_ROOTはメイン worktree。削除後に戻る先として使う。
追加ワークスペースを作って切り替える
使う場面
- 「新しい作業場所を作ってそこで作業したい」
- 「ブランチを切る感覚で別ワークスペースへ移動したい」
- 「今の tree は残したまま、別ブランチで並行作業したい」
手順
- 現在のルートと作成先パスを決める。
ROOT=$(git rev-parse --show-toplevel)
REPO=$(basename "$ROOT")
BRANCH="<new-branch>"
BRANCH_SLUG=$(printf '%s' "$BRANCH" | sed 's#[/:]#-#g')
WT_PATH="$(dirname "$ROOT")/${REPO}-wt-${BRANCH_SLUG}"
- 既存 branch / 既存 worktree の衝突を確認する。
git worktree list --porcelain
git show-ref --verify --quiet "refs/heads/$BRANCH"
- 同名 branch がまだ存在しないなら
-bで作成する。 - 同名 branch が存在し、どの worktree でも使用中でなければその branch を使って worktree を作る。
- 同名 branch が別 worktree で使用中なら、別名 branch を提案するか、ユーザーの指定を待つ。
- worktree を作る。
- 新規 branch を切るとき:
git worktree add -b "$BRANCH" "$WT_PATH"
- 既存 branch を使うとき:
git worktree add "$WT_PATH" "$BRANCH"
- 基点を明示されたとき:
git worktree add -b "$BRANCH" "$WT_PATH" "<start-point>"
- 以後のコマンドは
WT_PATHをworkdirにして実行する。
報告例:
worktree を作成しました: <WT_PATH>
以後の作業ディレクトリはこの worktree に切り替えます
最小コマンド例
ROOT=$(git rev-parse --show-toplevel)
REPO=$(basename "$ROOT")
BRANCH="feature/example"
BRANCH_SLUG=$(printf '%s' "$BRANCH" | sed 's#[/:]#-#g')
WT_PATH="$(dirname "$ROOT")/${REPO}-wt-${BRANCH_SLUG}"
if git show-ref --verify --quiet "refs/heads/$BRANCH"; then
git worktree add "$WT_PATH" "$BRANCH"
else
git worktree add -b "$BRANCH" "$WT_PATH"
fi
printf '%s\n' "$WT_PATH"
worktree を消してメインへ戻る
使う場面
- 「この追加ワークスペースはもう不要」
- 「作業が終わったので worktree を片付けたい」
- 「メインのワークスペースへ戻したい」
手順
- 削除対象 branch か worktree path を特定する。
git worktree list --porcelain
branch 名から path を引く例:
TARGET_BRANCH="<branch>"
TARGET_PATH=$(
git worktree list --porcelain | awk -v target="$TARGET_BRANCH" '
/^worktree / { wt=$2 }
/^branch refs\/heads\// {
br=$0
sub(/^branch refs\/heads\//, "", br)
if (br == target) {
print wt
exit
}
}
'
)
- 削除対象が dirty でないことを確認する。
git -C "$TARGET_PATH" status --short
- 出力があるなら、そのまま消さない。commit / stash / 破棄方針を決めてから進める。
- 先にメイン worktree を戻り先として確定する。
MAIN_ROOT=$(git worktree list --porcelain | awk '/^worktree /{print $2; exit}')
- 以後のコマンドは
MAIN_ROOTをworkdirにして実行し、対象 worktree を削除する。
git -C "$MAIN_ROOT" worktree remove "$TARGET_PATH"
- branch も不要なら削除する。
git -C "$MAIN_ROOT" branch -d "$TARGET_BRANCH"
報告例:
worktree を削除しました: <TARGET_PATH>
以後の作業ディレクトリはメイン worktree に戻します: <MAIN_ROOT>
最小コマンド例
TARGET_BRANCH="feature/example"
MAIN_ROOT=$(git worktree list --porcelain | awk '/^worktree /{print $2; exit}')
TARGET_PATH=$(
git worktree list --porcelain | awk -v target="$TARGET_BRANCH" '
/^worktree / { wt=$2 }
/^branch refs\/heads\// {
br=$0
sub(/^branch refs\/heads\//, "", br)
if (br == target) {
print wt
exit
}
}
'
)
git -C "$TARGET_PATH" status --short
git -C "$MAIN_ROOT" worktree remove "$TARGET_PATH"
git -C "$MAIN_ROOT" branch -d "$TARGET_BRANCH"
printf '%s\n' "$MAIN_ROOT"
注意
- 削除対象の worktree 自身を
workdirにしたまま消さない。先にMAIN_ROOT側へ戻してから削除する。 git worktree removeがworking trees contain modified or untracked filesで失敗したら、強制削除せず状態を報告する。- 使い終わったら
git worktree listで残存 worktree を確認する。 - ユーザーが「新しい repo」と言っていても、実際には同一 repo の追加ワークスペースとして扱う。