作業が開きっぱなしのところに緊急修正が来た
目標
1つのリポジトリに、作業ディレクトリを3つまで付けて、片付けます。終わると、stashなしでブランチを乗り換える手が身につき、ワークツリーが残した管理ファイルの片付け方がわかります。
なぜ重要なのか
ブランチを切り替えることがなぜこんなに面倒なのかを考えてみると、ワーキングツリーが1つしかないからです。リポジトリは、オブジェクトとブランチの参照を持っていて、ワーキングツリーは、そのうちの1つのコミットを広げたコピーです。広げる場所を増やせるなら、乗り換え自体が必要なくなります。git worktreeが、まさにそれを行います。ただし、ブランチの参照はリポジトリが1つだけ持っているため、同じブランチを2か所で開こうとすると、gitが止めます。この制約を理解することが、このラボの半分です。残りの半分は、後始末です。ディレクトリだけを削除すると、管理ファイルが残り、その場所がprunableのまま、ずっと一覧に表示されます。
ステップ
/root/gitx4/repoに、コミット3つのリポジトリを作り、releaseブランチを作成します。releaseを、/root/gitx4/relにワークツリーとして付けます。mainを/root/gitx4/dupに、もう一度付けてみて、拒否メッセージをnotes/dup.txtに残します。repoに保存していない変更を残したまま、/root/gitx4/hotにhotfixブランチを新しく作って付け、そこでhotfix.txtをコミットします。git worktree list --porcelainをnotes/list.txtに残します。/root/gitx4/tmpを付けてから、ディレクトリだけをrm -rfし、prunableの表示とpruneの結果をnotes/prune.txtに残します。/root/gitx4/usbを付けてlockをかけ、removeが拒否するのをnotes/lock.txtに残してから、解除して削除します。notes/report.mdに、worktree・stash・cloneをいつ使うかをまとめます。
参考
- このイメージには、gitの作成者情報がグローバルにはありません。リポジトリを作ったら、
git config user.emailとgit config user.nameをそのリポジトリに指定しないと、コミットできません。 - コミットの時刻は、
GIT_AUTHOR_DATEとGIT_COMMITTER_DATEで固定します。採点が時刻に左右されないようにするためで、実務でも、再現可能な履歴を作るときに使う手です。 - よくある間違い: ステップ4で、
repoの変更をgit stashやコミットで片付けてしまうことです。このラボの要点は、片付けなくても済むことなので、そのままにしておく必要があります。 - よくある間違い: ステップ6で、
git worktree removeを使うことです。そこでは、ディレクトリを先にrm -rfで消し、残った管理ファイルをpruneが片付ける流れを見る必要があります。
リポジトリとリリースブランチを作る
/root/gitx4/repoに、コミット3つのリポジトリを作り、releaseブランチを作成します。
git init -b mainで始めます。このイメージにはグローバルな作成者情報がないので、リポジトリごとにgit config user.emailとuser.nameを指定しないと、コミットできません。コミットの時刻は、GIT_AUTHOR_DATEとGIT_COMMITTER_DATEの2つの環境変数で固定します。
リリースブランチを2つ目の場所に付ける
releaseを、/root/gitx4/relにワークツリーとして付けます。
git worktree add <경로> <브랜치>です(プレースホルダーは、パスとブランチです)。付けたあと、新しいディレクトリの.gitがディレクトリではなくファイルであることを、catで確認してみてください。その1行が、元のリポジトリの管理ディレクトリを指しています。
同じブランチを2か所で開けない理由
mainを/root/gitx4/dupに、もう一度付けてみて、拒否メッセージをnotes/dup.txtに残します。
git worktree add /root/gitx4/dup mainをそのまま実行してみると、fatal:で始まる行が出ます。その行を要約せずにそのままファイルに入れ、なぜ止めるのかを1行付け足してください。ブランチの参照は、リポジトリが1つだけ持っています。
保存していない変更をそのままにして、ホットフィックス
repoに保存していない変更を残したまま、/root/gitx4/hotにhotfixブランチを新しく作って付け、そこでhotfix.txtをコミットします。
repoにdraft.txtを作っておいてください。コミットもstashもしません。その状態で、git worktree add -b <새브랜치> <경로> <기준>で場所をもう1つ作り、そのディレクトリの中でコミットします(プレースホルダーは、新しいブランチ、パス、基準です)。終わってからrepoを見ると、draft.txtがそのまま残っています。
今いくつの場所があるかを、機械が読める形式で
git worktree list --porcelainをnotes/list.txtに残します。
--porcelainは、人ではなくスクリプトが読むために作られた出力です。桁をそろえた表の代わりに、worktree・HEAD・branchが1行ずつ出ます。リダイレクトで、そのままファイルに入れてください。
ディレクトリだけを削除すると管理ファイルが残る
/root/gitx4/tmpを付けてから、ディレクトリだけをrm -rfし、prunableの表示とpruneの結果をnotes/prune.txtに残します。
git worktree add -b tmpwork /root/gitx4/tmpで場所を作ってから、そのディレクトリをrm -rfします。その状態でgit worktree listを見ると、1行にprunableが付きます。git worktree prune -vが何を削除したと言うのか、そしてブランチは残るのかまで確認して書いてください。pruneの説明は標準エラー出力に出るため、ファイルに入れるには2>&1が必要です。
ロックされた場所はremoveが拒否する
/root/gitx4/usbを付けてlockをかけ、removeが拒否するのをnotes/lock.txtに残してから、解除して削除します。
git worktree lock --reason '<사유>' <경로>でロックします(プレースホルダーは、理由とパスです)。ロックされた場所にgit worktree removeを行うと、拒否メッセージが出ます。その行をそのまま残してください。そのあとunlockしてremoveし、一覧とディレクトリが一緒に消えることまで確認します。
いつ場所を増やし、いつ退避するのか
notes/report.mdに、worktree・stash・cloneをいつ使うかをまとめます。
3つの方法が、それぞれ何を節約して何を失うかで分けて書いてください。今回自分で見たこと2つ、つまり同じブランチを2か所で開けないことと、ディレクトリを削除しても管理ファイルが残ることも、必ず入れてください。