何が起きたのか
作業をスタッシュして別の作業をした後、git stash pop を実行したら、こんなエラーが出た:
error: Your local changes to the following files would be overwritten by merge:
src/main.py
Please commit your changes or stash them before you merge.
Aborting
スタッシュは適用されなかった。しかし何も失われていない — スタッシュはまだスタックに残っている。src/main.py にコミットされていない変更がすでに存在するため、スタッシュを適用するとそれらが上書きされてしまう。だから Git は処理を中断した。
Git が中断する理由
git stash pop を実行すると、スタッシュされた差分をワーキングツリーにマージしようとする。ファイルにすでにコミットされていない編集がある場合、Git はその上にスタッシュを安全に適用する方法がない — そのままでは作業中の内容がサイレントに消えてしまう。だから早めに処理を中止する。
このエラーが起きる最もよくあるパターン:
src/main.pyの変更をスタッシュする。- 別のブランチに切り替えてちょっとした修正をして、また戻る。
- あるいは — これがよくある — スタッシュの存在を忘れて
src/main.pyをまた編集し始める。 git stash popを実行する。エラーが起きる。
まず今の状況を正確に把握しよう:
# スタッシュが触れているファイルを確認する
git stash show
# 現在コミットされていないものを確認する
git status
git diff src/main.py
修正方法 1 — 現在の変更を先にコミットまたはスタッシュする(推奨)
pop の前にワーキングツリーをきれいにする。2つの方法がある:
# オプション A: 今の変更をコミットする
git add src/main.py
git commit -m "WIP: current changes before stash pop"
git stash pop
# オプション B: 今の変更をその上にスタッシュする
git stash # 現在の変更を stash@{0} として保存する
git stash pop stash@{1} # 元のスタッシュを取り出す(インデックスが1にシフトされている)
# 競合があれば解決して、次に:
git stash pop # 先ほど作成した WIP スタッシュを取り出す
オプション B はすべてをスタッシュスタックに保持する。最初の pop の後にマージ競合が発生することがある — それは正常だ。Git は競合箇所に <<<<<<< マーカーを付けるので、手動で解決できる。
修正方法 2 — 現在のワーキングツリーの変更を破棄する
ブロックしている変更が保存する価値のないものの場合もある — 途中で止まった実験、デバッグ用のprint文など。思い切って捨てよう:
# 特定のファイルへの変更を破棄する
git checkout -- src/main.py
# その後リトライする
git stash pop
コミットされていないすべての変更を消したい場合:
git restore . # Git 2.23以降
# または
git checkout -- .
**警告:**この操作は元に戻せない。破棄されたワーキングツリーの変更は消えてしまう — Git にはゴミ箱がない。いずれかのコマンドを実行する前に git diff で必ず確認すること。
修正方法 3 — git apply で3ウェイマージを強制する
両方の変更が重要なのに git stash pop が中断し続ける場合、スタッシュをパッチとしてエクスポートして Git 自身にマージを試みさせよう:
git stash show -p | git apply --3way
競合で中断する代わりに、--3way を使うと Git は最善を尽くして処理し、自動解決できなかったファイルに競合マーカー(<<<<<<< / >>>>>>>)を残す。それを手動で修正する。
# 対応が必要なファイルを確認する
git status
# src/main.py を編集して競合マーカーを解決し、次に:
git add src/main.py
# スタッシュエントリを削除する — 手動で適用済みのため
git stash drop
修正方法 4 — スタッシュを削除せずに適用する
適用がうまくいくか不安な場合は、pop の代わりに git stash apply を使おう:
# 削除せずに適用する(スタッシュはスタックに残る)
git stash apply
# 競合を解決してから、スタッシュを手動で削除する
git stash drop
pop との唯一の違い:明示的に削除するまでスタッシュエントリが残る。何かおかしくなっても、スタッシュがセーフティネットとして残っている。結果に完全な自信がないときの無難な選択だ。
確認
次に進む前に簡単なサニティチェックをしよう:
# スタッシュスタックが空(またはエントリが1つ減っている)であることを確認する
git stash list
# ワーキングツリーが想定した変更だけを示していることを確認する
git diff HEAD
# 競合マーカーが残っていないことを確認する
grep -r '<<<<<<<' src/
git stash list が空で git status もきれいな状態?完了だ。
次回から防ぐには
これを完全になくすためのいくつかの習慣:
- **
git stash popの前にgit statusを実行する。**30秒の確認で、競合の解消に費やす10分を節約できる。 - **どのスタッシュを取り出すか明示する。**スタックに複数のエントリがある場合、Git に任せるより
git stash pop stash@{1}と指定する方がはるかに安全だ。 - **数分以上の作業にスタッシュを頼らない。**1時間や1日かかるコンテキストの切り替えには、一時ブランチへの WIP コミットの方がずっと信頼できる。
- スタッシュに名前をつける。
git stash push -m "refactor: before adding auth layer"は5秒余分にかかるが、git stash listが格段に読みやすくなる。

