Git Stashとは?
機能開発の途中で、緊急の対応が必要になることがあります。メインbranchでバグを修正する必要があったり、チームメイトのpull requestをレビューする必要があったり。作業中のコードをcommitする準備はできていないけれど、uncommitの変更がある状態ではbranchを切り替えられません。まさにこの問題を解決するためにgit stashは作られました。
Git stashは、uncommitの変更(stagingに入っているものもそうでないものも)を取り出して、一時的な保管領域に保存します。作業ディレクトリは最後のcommitに一致するクリーンな状態に戻ります。準備ができたら、それらの変更を戻すことができます。棚に作業を一時的に置いて別のことに対応し、終わったら元の場所から作業を再開するようなものだと考えてください。
基本的な使い方:Stash、Apply、Pop
変更をstashに保存する
最もシンプルな形は:
git stash
これは追跡されている変更済みファイルとstagingに入っているファイルをすべて取り出して保存します。作業ディレクトリはクリーンになります。なお、未追跡ファイル(Gitに一度も追加したことのないファイル)はデフォルトではstashされません。それらを含めるには:
git stash -u
または、無視されたファイルも含めてすべてをstashするには:
git stash -a
applyで変更を戻す
別の作業を終えてstashした作業を戻したい場合は:
git stash apply
これはstashされた変更を作業ディレクトリに復元しますが、stashのエントリはそのまま残ります。stashはまだ棚の上にあるので、同じ変更を複数のbranchに適用したい場合に便利です。
popで変更を戻す
git stash pop
popはapplyと同じように動作しますが、適用後にstashのエントリも削除します。単純に作業を戻したいだけでstashを保持する必要がない場合は、こちらがより一般的な選択です。
主な違い:applyはstashを保持し、popは復元後に削除します。stashを再度使う可能性がある場合はapplyを使いましょう。もう不要な場合はpopを使いましょう。
Stashにメッセージを追加する
デフォルトでは、GitはWIP on main: a3b4c5d commit messageのような自動生成された説明でstashにラベルを付けます。複数のstashがある場合、これはあまり役に立ちません。説明的なメッセージを追加できます:
git stash push -m "refactoring the auth module"
これにより、後でstashを一覧表示する際に各stashの内容を識別しやすくなります。
複数のstashを管理する
stashの一覧を表示する
Gitはstashのスタックを管理しています。すべてのstashを確認するには:
git stash list
出力は次のようになります:
stash@{0}: On main: refactoring the auth module
stash@{1}: WIP on feature/checkout: 9f2e1d0 add cart logic
stash@{2}: WIP on main: 7c8d9e1 update dependencies
最新のstashは常にstash@{0}です。新しいstashが追加されるたびに、古いstashはスタックの下に押し下げられます。
特定のstashをapplyまたはpopする
デフォルトでは、applyとpopは最新のstashに対して動作します。特定のstashを対象にするには、インデックスで参照します:
git stash apply stash@{2}
git stash pop stash@{1}
stashの内容を確認する
stashを適用する前に、中身を確認したい場合があります:
git stash show stash@{0}
これは変更されたファイルの概要を表示します。完全なdiffを見るには、-pを追加します:
git stash show -p stash@{0}
特定のファイルをstashする
すべてをstashしたくない場合もあります。1つか2つのファイルの変更だけを退避させたいかもしれません。Git 2.13以降、次のようにできます:
git stash push -m "sidebar layout changes" src/components/Sidebar.tsx src/styles/sidebar.css
指定されたファイルだけがstashされます。それ以外はすべて作業ディレクトリに残ります。
Stashの削除とクリア
単一のstashを削除する
特定のstashが不要になった場合、次のコマンドで削除します:
git stash drop stash@{1}
これはそのstashエントリを削除します。残りのstashは自動的に再インデックスされます。
すべてのstashをクリアする
すべてのstashを一度に削除するには:
git stash clear
このコマンドには注意してください。元に戻す方法はありません。stashされたすべての変更が完全に削除されます。
Stashからbranchを作成する
変更をstashした後、それらが独自のbranchに値すると気づくことがあります。stashを適用してからbranchを作成する代わりに、Gitにはショートカットがあります:
git stash branch new-feature-branch stash@{0}
これはstashが元々作成されたcommitから新しいbranchを作成し、stashを適用して削除します。現在のbranchにstashを適用するとコンフリクトが発生する場合に特に便利です。
よくある落とし穴
- Stashを忘れる。stashは忘れやすいものです。定期的に
git stash listを実行して、適用または削除すべき残りのstashがないか確認しましょう。 - Stashのコンフリクト。stashしてからコードが大きく変わっている場合、stashを適用するとmergeコンフリクトが発生することがあります。通常のmergeコンフリクトと同じ方法で解決してください。
- Commitの代わりにstashに頼る。頻繁にstashしている場合は、代わりに作業中のコードをcommitすることを検討してください。後でいつでもそれらのcommitをamendやsquashできます。stashは短期間のコンテキスト切り替えに最適であり、長期保存には向いていません。
GitSquidでstashを操作する
GitSquidはcommitグラフ上にstashを直接表示するので、どのstashが存在し、どのcommitから作成されたかが一目でわかります。stashを右クリックすると、apply、pop、drop、またはすべてのstashをクリアするオプションのあるコンテキストメニューが開きます。これにより、特に複数のstashがあってそれらを確認したり整理したりする必要がある場合に、コマンドを入力するよりも素早くstashを管理できます。
クイックリファレンス
| コマンド | 動作 |
|---|---|
git stash |
追跡されている変更をstashする |
git stash -u |
未追跡ファイルも含めてstashする |
git stash push -m "msg" |
説明メッセージ付きでstashする |
git stash list |
すべてのstashを一覧表示する |
git stash apply |
stashを復元し、エントリを保持する |
git stash pop |
stashを復元し、エントリを削除する |
git stash drop stash@{n} |
特定のstashを削除する |
git stash clear |
すべてのstashを削除する |
git stash show -p |
stashの完全なdiffを表示する |
git stash branch <name> |
stashからbranchを作成する |
Git stashは、必要になるまでは些細なツールに思えるものの一つです。使い慣れると、タスク間のコンテキスト切り替えがシームレスになります。メッセージでstashを整理し、古いstashを定期的にクリーンアップし、stashを保持する必要がない場合はapplyよりもpopを使いましょう。