GPT老师的指导:恢复误删的git stash

You can often recover a dropped stash because Git keeps the underlying commit and blob objects for a while (until garbage collection). Act quickly and avoid commands that run aggressive GC.

What to try first (quick recovery)

  1. Find the stash commit via reflog:
  • git reflog show stash
    • If it lists the dropped entry, note its commit hash (e.g., 168db1867e3f... from your message).

If you see the hash
2) Recreate the stash reference:

  • Option A: Recreate as a branch to inspect:
    • git branch recover-stash 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
    • git checkout recover-stash
    • Your stashed changes will be in the commit’s tree (for “stash save/ push” with index/worktree, see notes below).
  • Option B: Restore as a new stash ref:
    • git update-ref refs/stash 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
    • git stash list
    • You should now see it again (likely as stash@{0}), and can git stash apply.

If stash isn’t in reflog
3) Search all reflogs and unreachable commits:

  • git reflog --all | grep 168db1867e3f
    • If not known, just list everything and look for “stash” or “WIP”:
    • git reflog --all | grep -i stash
    • git log -g --grep=stash --all
  • Use fsck to find dangling commits:
    • git fsck --lost-found --no-reflogs
    • Look for “dangling commit ” around the time you stashed.
  • Explore the commit objects by time:
    • git log --walk-reflogs --date=iso --all
    • Or show recent unreachable objects:
    • git fsck --no-reflogs --lost-found | grep commit | head -n 50

Once you find the stash commit hash
4) Understand stash structure to extract content:

  • A typical stash object is a merge commit with up to three parents:
    • Parent 1: the commit you were on when stashing (base).
    • Parent 2: the index (staged) state.
    • Parent 3: the worktree (unstaged) state (only present if there were unstaged changes).
  • To inspect:
    • git show --summary --no-patch 168db1867e3f
    • git show 168db1867e3f^1 # base
    • git show 168db1867e3f^2 # index tree
    • git show 168db1867e3f^3 # worktree tree (if exists)
  1. Recover files/changes from the stash commit:
  • To restore both index and worktree like “apply”:
    • git stash apply 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
  • If apply isn’t available (ref not under refs/stash), use checkout/restore of the trees:
    • To get working copy back to the stashed worktree:
      • git checkout 168db1867e3fe74ef7cbfc26d7dae39bebebcddf^3 -- .
        (If ^3 doesn’t exist, use ^2 for staged-only stash.)
    • To stage the index part:
      • git checkout 168db1867e3fe74ef7cbfc26d7dae39bebebcddf^2 -- .
  • Or create a branch at the worktree parent and merge:
    • git switch -c stash-recovered 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
    • git merge -s ours --no-commit 168db1867e3fe74ef7cbfc26d7dae39bebebcddf^1
    • git read-tree -mu 168db1867e3fe74ef7cbfc26d7dae39bebebcddf^3

If you only have the hash from the drop message

  • You do: 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
  • Try restoring the stash ref directly:
    • git update-ref refs/stash 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
    • Then: git stash list; git stash apply

Edge cases and tips

  • If git stash apply errors with “Not a stash reference”: ensure the ref is refs/stash or refs/stash@{n}. update-ref fixes that.
  • If no ^3 parent exists, your stash only had staged changes; use ^2.
  • If fsck shows dangling blobs but not the stash commit, you can still recover specific files:
    • git show > path/to/file
    • But prefer recovering the stash commit if possible.
  • Avoid garbage collection until you recover:
    • Do not run git gc --prune=now
    • If autoGC runs, it usually keeps recent objects, but time matters.
  • Make a safety clone before experimenting:
    • git clone --no-hardlinks . ../repo-recovery
    • Work in the recovery clone to avoid accidental prune.

Quick one-liner if your hash is valid right now

  • git update-ref refs/stash 168db1867e3fe74ef7cbfc26d7dae39bebebcddf && git stash apply

If this fails, paste the output of:

  • git rev-parse 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
  • git cat-file -t 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
  • git show --summary 168db1867e3fe74ef7cbfc26d7dae39bebebcddf
    And I’ll guide you through the next step.
posted @ 2025-08-29 09:17  Mr42Sir  阅读(15)  评论(0)    收藏  举报