猫より犬好きプログラマのにゃんです。主な仕事はマサカリの投擲とベランダに来る野良猫の餌やりです。よろしくお願いします。
皆さんバージョン管理システムを使ってますか?今では多くの現場でGitを使っていると思います。ゲーム開発など巨大なバイナリのアセットが多い現場ではGitではなくプロプライエタリのPerforceを使用されているかもしれません。他にもGitと同時期に開発されたMercurialというツールもありますが、いずれにせよ現在のdevシーンではバージョン管理システムはあって当たり前のツールの一つになっています。
弊社ではGitを使っています。Gitは機能豊富ですがその分知られていない機能も多く、ネットを見渡せば色々な記事が転がっていますが、今回は私も一つGitの便利機能を紹介したいと思います。
worktreeで複数の作業ディレクトリを作る
複数のブランチを同時並行で修正したくなったらどうしてますか?都度stashしてcheckout(switch)しますか?いっそ新たにcloneしちゃいますか?
それでもいいのですが、Gitは1つのリポジトリに対して複数のワークツリー(作業ディレクトリ)を作成することができるのです。
ワークツリーの作成
git worktree add <チェックアウトするディレクトリ> [-b] <チェックアウトするブランチ名>
-bは新しいブランチを作成します。checkout -b
のbと同じですね。
試しにローカルの適当なリポジトリで、new_workdirディレクトリに新しいワークツリーを作ってfeature/testブランチをチェックアウトしてみます
~/.dotfiles $ git worktree add new_workdir -b feature/test Preparing worktree (checking out 'feature/test') HEAD is now at dd92ad4 add https url support
作成したワークツリーに行ってみましょう。feature/testブランチがチェックアウトされています。
~/.dotfiles $ cd new_workdir ~/.dotfiles/new_workdir $ git status On branch feature/test nothing to commit, working tree clean
今回は既存のワークツリー内部に新しいワークツリーを作成しましたが、新しいワークツリーは自動的に既存ワークツリーのコミット対象外になるので安心して作成してください。もちろん既存ワークツリーの外に作成することもできます。ファイルの変更をwatchする機能を使っている場合などは外に作った方がいいかもしれません。
なお、複数のワークツリーで同じブランチをチェックアウトすることはできません。
~/.dotfiles/new_workdir $ git switch master fatal: 'master' is already checked out at '/Users/nyan-wang/.dotfiles'
これは地味に役立つ制限で、2カ所にcloneして作業した場合、2カ所で同じブランチを弄ってしまうような悲劇が発生しますが、worktreeではそんな事故を防げます。worktreeを知る前には2カ所で同じブランチを修正して泣く泣く手動マージとか地味な作業をしたこともありました。
ワークツリーの一覧
作成したワークツリーは git worktree list
で確認できます
~/.dotfiles/new_workdir $ git worktree list /Users/nyan-wang/.dotfiles dd92ad4 [master] /Users/nyan-wang/.dotfiles/new_workdir dd92ad4 [feature/test]
ワークツリーの削除
ワークツリーが不要になったらgit worktree remove
で削除できます。
git worktree remove new_workdir
実はrmコマンドでワークツリーを消してしまっても問題ありません。あくまで同一のリポジトリの別ワークツリーなのでコミットした変更は全て残っています。ただし、ワークツリーの管理情報が残っておりworktree listすると消したワークツリーが表示されてしまいます。そんなときは git worktree prune
で消したワークツリーの管理情報を掃除できます。
特に既存ワークツリーの外に作るとうっかりrm -rfで消してしまいがちですが、消してしまっても安心です。
worktreeのcloneに対する利点
worktreeを使った場合cloneに対して以下の利点があります
- git hook設定やuser.nameなどconfigのカスタマイズが共有されている
- 作業完了後にリモートにpushせず削除してしまっても、コミットは残っているので安全安心
- 二箇所で同じブランチを弄ってしまう失敗を防げる
それでは皆さま、よきGitライフをお過ごしください〜