git worktree についてのメモ

git worktree

git worktree というコマンドがあることを知ったので、メモ。

Git - git-worktree Documentation

ブランチの切り替えをしなくてよくなるコマンド git worktree がすごい!


git worktree

git worktree は Git 2.5.0 から導入されているコマンドで、1つのリポジトリに複数のワークツリーを持つことができる。

何が便利なのかを見ていく

あるブランチ(branchA)で作業しているときに、(branchB) で修正が必要となった時のことを考えてみる。

git worktree を使わない場合

git checkout branchB

上記のように branchB へ切り替えて作業を行う。 作業の内容によっては git stash savebranchA で先に行っていた修正を退避させておく必要があったり、一旦コミットをして working tree をきれいにしておくかもしれない。

時間のかかるデプロイやタスクを実行していた場合は終わるまで待つか、別の作業用ディレクトリを切ってそこにリポジトリを clone して…という感じになる。


git worktree を使うと branchA に対する修正をしつつ、別のワーキングツリーに branchB をチェックアウトできるので、作業フォルダを移動するだけで済む。

実際に下で書いてあるコマンドを叩いていってみる。

Git - git-worktree Documentation

ローカルのブランチを作業ディレクトリにチェックアウトする

git worktree add <ブランチ名>

git worktree add working 

working ブランチがローカルに存在していなければ HEAD からブランチが作られ、working ブランチが作成される。

指定したブランチと同じ名前のフォルダがプロジェクトディレクトリ配下に作成される。

project
├── .git
├── README.md
└── working
    ├── .git
    └── README.md

worktree を使って作られたワークツリーの中には .git ファイルが作成されている。 中身を直接見てみるとわかるが、こいつは git リポジトリではなく、リポジトリの参照先を書いただけのテキストファイルになっている。

gitdir: /project/.git/worktrees/working

作業フォルダを別名にする

ローカルにブランチがある場合は下のように実行することで任意の場所にチェックアウトできる。

git worktree add <作業ディレクトリ> <ブランチ名>
git worktree add dev working

これで dev フォルダ以下に working ブランチがチェックアウトされる。

ローカルにないけどリモートにある場合は -b オプションをつけて実行すればよい。

git worktree add -b dev ../dev master

すでに先述のコマンドを打ったりしていて、working ブランチがチェックアウトされている状態だとここでエラーになる。

fatal: 'working' is already checked out at '/worktree/working'

git checkout と同様に、git worktree でも同じブランチを2回チェックアウトすることはできない。

作成した worktree を確認する

作成した worktree 一覧は git worktree list でどこになんのブランチをチェックアウトしているかを確認できる

git worktree list
# /worktree          f7be93b [master]
# /worktree/working  f7be93b [working]

worktree の path を変更する

作成した worktree の 作業ディレクトリを移動したい場合には git worktree move <worktree> <new-path> で可能。

ここで書かれている <worktree> とは、worktree list で左側に表示される worktree の作業フォルダの場所のことっぽい。わかりにくい。

git worktree move /worktree/working /newPath

特定の worktree を削除する

追跡されていないファイルも追跡されているファイルの変更もない作業ツリーであれば git worktree remove [-f] <worktree> で worktree を削除できる。

git worktree remove /worktree/working

強制的に削除したい場合は -f オプションを有効にして実行する。

すべての worktree を削除する

git worktree prunegit worktree list で表示される全ての worktree が綺麗さっぱり削除できる

worktree を lock する

worktree はどこの好きな場所へチェックアウトできる。もちろんネットワークドライブやクラウドストレージにも。 ただネットワークドライブやクラウドストレージは常に接続されている保証がないため、見えていないときに worktree pruneworktree remove で削除してしまわないようにロックをかけておくことができる。

git worktree lock /worktree/working

ロックをかけることで moveprune remove ができなくなる。 ロックを外したいときには unlock で外せる

git worktree unlock /worktree/working

冒頭の記事で紹介されているように、worktree でチェックアウトするディレクトリ名を決めておき、gitignore で無視しておいたり関数を作っておくと便利そう。

※ ちなみにgit worktree movegit worktree remove は git 2.17.0 以降に追加されたもののようなので、git のバージョンがそれより前だと使えないので注意。