git worktreeで作業フォルダをブランチの数だけ持つ、stashと切り替えをやめるための備忘録

新しい機能のブランチで作業している途中に、本番側の小さな不具合を直してほしいと頼まれる。これまでは、書きかけの変更をgit stashで退避し、git switch mainで切り替え、直してコミットし、元のブランチに戻ってgit stash popする、という手順を踏んでいた。そのたびにエディタは開いていたファイルを読み直し、ビルドの成果物は古いブランチの状態のまま残り、退避したことを忘れてstashが溜まっていく。小さな修正のはずが、戻ってきたときに何をしていたか思い出すところから始まるのが嫌だった。 この切り替えそのものをやめられるのがgit worktreeだ。1つのリポジトリに作業フォルダを何本でも足せて、フォルダごとに別のブランチを開いておける。修正を頼まれたら、別のフォルダに移って直すだけで済み、書きかけの作業には指一本触れない。仕組みと使い方、それに後片付けでつまずきやすい点を、手元のWindows 11に入っているGit 2.55.0で一通り試したので、その結果をまとめておく。 worktreeは作業フォルダを増やす機能で、リポジトリは1つのまま mainから枝を切り、作業してmainへ戻す。worktreeを使うと、この枝ごとに別のフォルダを持てるPhoto: TheresNoTime / CC BY-SA 4.0 ふつうのクローンは、.gitフォルダ(履歴やブランチの情報が入っている本体)が1つと、ファイルを編集するための作業フォルダが1つ、という組み合わせになっている。ブランチを切り替えると、この作業フォルダの中身が丸ごと書き換わる。同じリポジトリを2つの場所で開きたければ、もう1回クローンするのがこれまでのやり方だったが、それだと履歴が2倍の容量になり、片方で作ったブランチをもう片方から見るにはpushとfetchを挟む必要がある。 worktreeは、.gitの本体は1つのまま、作業フォルダだけを追加する。最初からある作業フォルダを「メインのワークツリー」、後から足したものを「リンクされたワークツリー」と呼ぶ。追加したフォルダの直下にあるのは.gitフォルダではなく、.gitという名前の小さなテキストファイルで、中身は1行だけだった。 gitdir: C:/Users/norio/AppData/Local/Temp/wtlab/repo/.git/worktrees/repo-feature 指している先は、メインのリポジトリの.git/worktrees/の下に作られた管理用のフォルダだ。ここにそのワークツリー専用のHEAD(今どのブランチを開いているか)とindex(ステージングの状態)が置かれ、commondirというファイルには本体への相対パス../..が、gitdirというファイルには逆向きに作業フォルダ側の.gitファイルの場所が書かれている。行きと帰りの両方向にパスが記録されていることが、後で出てくる「フォルダを動かしたときに壊れる」話の原因になる。 機能としては古く、2015年7月のGit 2.5で入った。当初は追加と掃除くらいしかできず、フォルダを消すremoveと移すmoveが加わったのは2018年のGit 2.17だ。その後も、空のブランチで作業フォルダを作る--orphanがGit 2.42で、パスを相対で記録する--relative-pathsがGit 2.48で足されている。古い解説記事では、フォルダを手で消してpruneで片付ける手順が紹介されていることがあるが、今はremoveで一度に済む。なお、サブモジュールを含むリポジトリでの複数ワークツリーは、公式の説明書きでも対応が不完全とされていて、サブモジュールのあるワークツリーはmoveできない。サブモジュールを多用するリポジトリでは、慎重に試したほうがいい。 基本はadd・list・removeの3つで足りる まずはブランチを1つ、隣のフォルダに開いてみる。リポジトリの中で次のように打つ。 git worktree add ../repo-feature feature # 既存のブランチ feature を開く git worktree add -b hotfix ../repo-hotfix # 新しいブランチ hotfix を作って開く git worktree list listの出力は、フォルダ、開いているコミット、ブランチ名の3列になる。 C:/Users/norio/AppData/Local/Temp/wtlab/repo 008158a [main] C:/Users/norio/AppData/Local/Temp/wtlab/repo-feature 008158a [feature] C:/Users/norio/AppData/Local/Temp/wtlab/repo-hotfix 008158a [hotfix] あとはcd ../repo-hotfixで移って、いつも通り編集・コミット・pushすればよい。コミットは本体の.gitに入るので、メインのフォルダに戻ってgit log hotfixと打てば、もうそこにある。pushもfetchも要らない。 ブランチ名を書かずにgit worktree add ../quickfixとフォルダだけ渡すと、フォルダ名と同じquickfixというブランチが今のコミットから作られた。もう1つ便利だったのは、手元にはまだ無く、リモートにだけあるブランチの名前を渡した場合だ。クローンしたリポジトリでgit worktree add ../clone-topic topicとすると、origin/topicを追いかけるtopicブランチが自動で作られ、branch 'topic' set up to track 'origin/topic'.と表示された。レビューを頼まれたブランチを開くときは、これがいちばん手数が少ない。 ...

2026年10月18日 · 2 分 · 407 文字 · kingsworksub-jpg