git worktreeの使い方と便利コマンド
tech約3分で読めます・1064文字
はじめに
読者諸君、ぐんも!
この記事では、git worktreeの概要、記述方法、zshで使用可能な便利なコマンドを紹介します。
gitブランチ切り替えが煩雑になってきた方向けに、worktreeで並行作業を快適にする方法を紹介します。
なぜgit worktreeを使うのか?
最初はgit switch -c "branch-name"が私の相棒でした。
ところが、ブログを書くようになると、ブログ記事を書くブランチ、ブログ機能を実装するブランチが混ざって混乱することが増えるようになったのです。
また、claude codeを本格的に使うようになったこともあり、ブランチごとにディレクトリをわけて、ファイルに対する変更を混同しなくてすむようにもしたくなりました。
git worktreeとは
違い
git branchは同じディレクトリ上でファイル追跡branchを生成する。git worktreeはブランチを作る際にディレクトリのコピーを作成する。
つまり、ブランチ作成時にディレクトリをコピーするかどうかが分かれ目となります。
例えばチームで1つのリポジトリを管理するとき、それぞれの作業はリモートリポジトリをそれぞれのPCにgit cloneしますよね?
それと同じことを1つのPC内でやってしまうのがgit worktreeなんです。
基本コマンド
追加
- 新しいブランチと作業ディレクトリを作成する
../に"branch-name"のディレクトリが作成されます
git worktree add ../"branch-name"
- 既存ブランチを新しい作業ディレクトリに移す
現在作業中のブランチを"directory-name"に移動します。
git worktree add "directory-name" "existing-branch-name"
- ブランチ名と作業ディレクトリ名を指定し、特定のコミットからブランチを作成する
私の使用例では、"commit-name"は基本的にmainを使用します。
git worktree add -b "branch-name" "directory-name" "commit-name"
- ブランチ名と作業ディレクトリ名を指定して現在のコミットからブランチを作成する
git worktree add -b "branch-name" "directory-name"
現在のworktreeの一覧表示
git worktree list
削除
- 作業が完了したworktreeを削除します。
git worktree remove "directory-name"
- 未保存の変更があっても強制定期に削除します。
git worktree remove --force "directory-name"
zshで使っている便利関数
git worktreeの作成
現在のディレクトリに対し以下をチェックします。
- git repositoryか
- 初回コミットがあるか
その後、"repository-name"-"branch-name"というディレクトリを作成し、"branch-name"にチェックアウトします。
function git-plant() {
if ! git rev-parse --git-dir &>/dev/null; then
echo "not a git directory"
return
elif ! git rev-parse HEAD --git-dir &>/dev/null; then
echo "commitがありません"
return
elif [[ -z "$1" ]]; then
echo "ブランチ名を指定してください"
return
fi
local branchdir="../$(basename $(git rev-parse --show-toplevel))-$1"
git worktree add -b "$1" "$branchdir" "${2:-main}"
cd "$branchdir"
}
-
git rev-parse (HEAD) --git-dir &>/dev/null
現在の(HEAD コミットへの)HEADのコミットハッシュと.git directory``のパスを出力、stdout(標準出力)とstderr`(標準エラー出力)を捨てます。
true/falseを判定するために使用 -
git rev-parse --show-toplevel
現在のgit directoryのトップレベルのディレクトリパスを出力 -
basename
引数のディレクトリ名を出力
git worktreeの削除
mainにmerge済みのworktreeのディレクトリ・ブランチを削除します。
function git-cut() {
git fetch --prune
git branch -vv | grep ': gone' | awk '{
if ($1 == "+") {
gsub(/[()]/,"",$4); print $2,$4
} else { print $1,"" }
}' | while read branch wt_path; do
[[ -n "$wt_path" ]] && git worktree remove "$wt_path"
git branch -d "$branch"
done
echo
echo 💫残りのローカルブランチ💫
echo
git branch
}
git branch -vv | grep ': gone' | awk
mainにmergeされると、git branch -vvでfeature/foo abc1234 [origin/feature/foo: gone]のように表示されます。
そのため、: goneのブランチに対してawkの処理を実行します。
スコープ外の実装を別ワークツリーに分ける
# まず変更をstashする
git stash -m "stash message"
# ワークツリーを分ける
git worktree add -b "branch-name" "directory-name"
# (stash一覧を表示する)
git stash list
# 変更をstashから戻す
git stash index
さいごに
git branchのみの運用よりもはるかに利便性が高く、AIとのコーディングとも親和性の高いgit worktreeの紹介でした。
ぜひ皆さんの開発フローに取り入れてみてください。
