Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to recover a dropped stash in Git?

I frequently use git stash and git stash pop to save and restore changes in my working tree. Yesterday, I had some changes in my working tree that I had stashed and popped, and then I made more changes to my working tree. I'd like to go back and review yesterday's stashed changes, but git stash pop appears to remove all references to the associated commit.

I know that if I use git stash then .git/refs/stash contains the reference of the commit used to create the stash. And .git/logs/refs/stash contains the whole stash. But those references are gone after git stash pop. I know that the commit is still in my repository somewhere, but I don't know what it was.

Is there an easy way to recover yesterday's stash commit reference?

like image 806
Greg Hewgill Avatar asked Sep 18 '08 01:09

Greg Hewgill


People also ask

Can I recover a dropped stash git?

Git Stashing Recover a dropped stashYou can replace gitk there with something like git log --graph --oneline --decorate if you prefer a nice graph on the console over a separate GUI app. Or you can use the context menu in gitk to create branches for any unreachable commits you are interested in.

How do I reopen a git stash?

To make this simple, you have two options to reapply your stash: git stash pop - Restore back to the saved state, but it deletes the stash from the temporary storage. git stash apply - Restore back to the saved state and leaves the stash list for possible later reuse.

What is git drop stash?

git stash temporarily shelves (or stashes) changes you've made to your working copy so you can work on something else, and then come back and re-apply them later on.

How do I find my git stashed files?

The Git stash list command will pull up a list of your repository's stashes. Git will display all of your stashes and a corresponding stash index. Now, if you wish to view the contents of a specific stash, you can run the Git stash show command followed by stash@ and the desired index.


3 Answers

Once you know the hash of the stash commit you dropped, you can apply it as a stash:

git stash apply $stash_hash

Or, you can create a separate branch for it with

git branch recovered $stash_hash

After that, you can do whatever you want with all the normal tools. When you’re done, just blow the branch away.

Finding the hash

If you have only just popped it and the terminal is still open, you will still have the hash value printed by git stash pop on screen (thanks, Dolda).

Otherwise, you can find it using this for Linux, Unix or Git Bash for Windows:

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

...or using PowerShell for Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }

This will show you all the commits at the tips of your commit graph which are no longer referenced from any branch or tag – every lost commit, including every stash commit you’ve ever created, will be somewhere in that graph.

The easiest way to find the stash commit you want is probably to pass that list to gitk:

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

...or see the answer from emragins if using PowerShell for Windows.

This will launch a repository browser showing you every single commit in the repository ever, regardless of whether it is reachable or not.

You can replace gitk there with something like git log --graph --oneline --decorate if you prefer a nice graph on the console over a separate GUI app.

To spot stash commits, look for commit messages of this form:

        WIP on somebranch: commithash Some old commit message

Note: The commit message will only be in this form (starting with "WIP on") if you did not supply a message when you did git stash.

like image 86
Aristotle Pagaltzis Avatar answered Oct 20 '22 00:10

Aristotle Pagaltzis


If you didn't close the terminal, just look at the output from git stash pop and you'll have the object ID of the dropped stash. It normally looks like this:

$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(Note that git stash drop also produces the same line.)

To get that stash back, just run git branch tmp 2cae03e, and you'll get it as a branch. To convert this to a stash, run:

git stash apply tmp
git stash

Having it as a branch also allows you to manipulate it freely; for example, to cherry-pick it or merge it.

like image 20
Dolda2000 Avatar answered Oct 20 '22 01:10

Dolda2000


Just wanted to mention this addition to the accepted solution. It wasn't immediately obvious to me the first time I tried this method (maybe it should have been), but to apply the stash from the hash value, just use "git stash apply ":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

When I was new to git, this wasn't clear to me, and I was trying different combinations of "git show", "git apply", "patch", etc.

like image 293
Wade Avatar answered Oct 20 '22 02:10

Wade