git stash の概要と動作原理
Gitにおけるgit stashは、未コミットの状態にあるワークツリーやステージングエリアの変更を一時的に退避させるための標準コマンドです。開発進行中に緊急のタスク発生や他ブランチへの切替が必要となった際、現在の進捗を破棄することなく安全に保管し、後から復元できる仕組みを提供します。
内部データ構造としては、退避された差分は「stash スタック」と呼ばれる配列ベースのリスト領域に格納されます。このスタックは後入れ先出し(LIFO)で管理され、最新の退避エントリから順に取り出すことができます。また、オプション引数により追跡対象ファイルのみならず、新規追加予定の未追跡ファイル(untracked files)や無視対象ファイル(ignored files)を含めて一括で保管することも可能です。
主要な操作コマンド一覧
- git stash push [-m <メッセージ>]:現在の変更を退避します。Git 2.13以降では従来の
saveに代わりpushが正式な構文として採用されています。 - git stash list:登録されている退避履歴の一覧を表示します。各エントリには自動採番されたインデックスが割り当てられます。
- git stash show [-p] [<stash_ref>]:特定または最新のエントリに含まれるファイル差分を確認します。
- git stash apply [<stash_ref>]:指定した退避内容を実際のソースコードに反映させますが、元の退避データは保持します。
- git stash pop [<stash_ref>]:退避データを復元すると同時に、該当するエントリをスタックから削除します。
- git stash drop [<stash_ref>]:特定の退避記録を明示的に破棄します。
- git stash clear:退避リスト全体を一括で空にします。
- git stash branch <new_branch> [<stash_ref>]:退避データを含んだ新規ブランチを作成し、その場でワークツリーへ適用します。
実践的なワークフロー例
以下は、機能開発中のブランチで実装を進めている最中にホットフィックスが必要になった場合の典型的な運用パターンです。メッセージ表記やブランチ命名規則を実務の標準に合わせて再構成しています。
# 1. 進行中の機能開発分をコメント付きで一時退避
# リポジトリの状態をクリーンに保ち、緊急切替に対応可能にする
git stash push -m "feat/payment-gateway-refactor-work-in-progress"
# 2. パッチ対応用に別ブランチへ遷移
git checkout -b hotfix/v1.4.2-security-issue
# ... バグ修正・ローカルテスト・コミット手順 ...
# 3. 修正公開後に本来の開発環境へ戻還
git checkout feat/main-api-upgrade
# 4. 退避リストを確認し、該当インデックスを特定
git stash list
# 出力イメージ:
# stash@{0}: feat/payment-gateway-refactor-work-in-progress
# stash@{1}: feat/auth-module-initial-setup
# 5. 該当退避エントリをワークツリーへ復元
# インデックス「0」を指定して適用(元のデータは残るため衝突確認が可能)
git stash apply stash@{0}
# 6. 正常に展開されたことを確認後、不要となった退避データを削除
git stash drop stash@{0}
# ※ 適用と同時に削除を完了させたい場合は、代わりに 'git stash pop' を実行する
高度な利用シナリオ
特定の条件下でのみファイルを退避させたい場合、-u(未追跡ファイル含む)や-k(未追跡ファイルをワークツリーに残しつつ退避)などのフラグが用意されています。複数のコミット境界を跨いで段階的に変更を保存する必要がある場合、必要に応じてgit stash push --include-untrackedを併用することで、設定ファイルやドキュメント類もバージョン管理下のソースコードと同様に正確にスナップショット化できます。これにより、大規模なリファクタリングや複数担当者の並行開発時に生じる競合リスクを最小限に抑えることができます。