Rescue a missing git stash

DateReadtime 2 minutes Tags

I lost a git stash the other day mysteriously. Here is the process I used to recover a lost stash.

Where is my Stash?

Lets assume you have a git stash:

$ git stash
Saved working directory and index state WIP on master: 1f96501 Unmark two old posts as drafts, check spelling
HEAD is now at 1f96501 Unmark two old posts as drafts, check spelling

$ git stash list
stash@{0}: WIP on master: 1f96501 Unmark two old posts as drafts, check spelling

And you accidentally drop it:

$  git stash drop
Dropped refs/stash@{0} (7e765965bfdeb34647773af3b7b2cc0c1629843c)

Or you pop the stash and then lose it somehow...

$ git stash pop
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   content/2016/09/05-finding-files-without-newlines.rst

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (7e765965bfdeb34647773af3b7b2cc0c1629843c)

Recovery

Your stash doesn't show up in the stash list:

$ git stash list

Stashes aren't in the normal reflog output:

$ git reflog
0e47d62 HEAD@{0}: commit: Add newlines to the ends of posts
1f96501 HEAD@{1}: commit (amend): Unmark two old posts as drafts, check spelling
79df53a HEAD@{2}: commit: Unmark two old posts as drafts, check spelling

You might be able to see your stash in:

$ git reflog --all
0924cfe refs/stash@{0}: WIP on pipeline: 6ffcf23 Update packages
6ffcf23 refs/heads/master@{0}: pull origin master: Fast-forward

However if its not there, git provides access to them as a "dangling commit":

$ git fsck --no-reflog | awk '/dangling commit/ {print $3}'
Checking object directories: 100% (256/256), done.
Checking objects: 100% (724/724), done.
bb99ae9cde077bd807774d314760786742537df8
b2932a09d1e9a00349e1e9d968de5aace8bb65cd
7754cdc89aae40896419508e0f2c9bcb1112a9e5
32bdea0498f633c613491add06cf1fd606fe80bd
93dd0ecabc594a37047960665a4f4025ca577970
7e765965bfdeb34647773af3b7b2cc0c1629843c
91f681ad3cfc1ca29b441d20c547e24f3d38e42f
79df53ac5f83477694f48ad1a6db2fcc9b3a3a90

Once you have a list of the dangling commits, you can view them individually by using their git sha.

$ git show -p 79df53ac5f83477694f48ad1a6db2fcc9b3a3a90

Or use shell expansion to combine the two previous steps in case you have a lot of dangling commits.

$ git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

Read through the changesets to find your missing stash.

Rescue

Finally, now that you have found the missing stash you can use the apply subcommand to recover it:

$  git stash apply 7e765965bfdeb34647773af3b7b2cc0c1629843c
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   content/2016/09/05-finding-files-without-newlines.rst

no changes added to commit (use "git add" and/or "git commit -a")