23

I wrote considerable code for a feature and stashed the changes in git.

After that I pushed several changes into the repository and did a git stash and apply multiple times (read over 100 times).

After almost 2 months I now want to retrieve the changes from git stash – but I cant find them no matter what.

Tried several git stash apply, git stash list, git stash list -p. Nothing works. I cant find those old stashed changes.

Wish I had taken a backup instead of trusting git to stash them...sigh...

Can anyone help?

SQB
  • 3,926
  • 2
  • 28
  • 49
user811433
  • 3,999
  • 13
  • 53
  • 76
  • possible duplicate of [Git: how to unstash only certain files?](http://stackoverflow.com/questions/15264553/git-how-to-unstash-only-certain-files) – Luceos Jan 15 '14 at 06:49
  • 1
    A stash is held only in the repository which stored them originally - it is not copied with clone, push or pull. Are you running in the same repository? Did you ever check these changes in to HEAD? – Alex Brown Jan 15 '14 at 06:49
  • Did the output from `git stash list` show *anything* – Alex Brown Jan 15 '14 at 06:51
  • Git stash is not a reliable long term store for changes. It's generally better to commit and them move them aside into a separate branch. – Alex Brown Jan 15 '14 at 06:51
  • @Alex Brown - yes it is the same repository, not cloned after that fateful git stash. "git stash list" shows a whole big list. – user811433 Jan 15 '14 at 06:53
  • @Luceos - That other question seems to be talking about the {0} stash. But my problem is I dont know where my changes are stashed and which stash number they are on – user811433 Jan 15 '14 at 06:55
  • 2
    well, look through the stashes like `git show 'stash@{0}'`, `git show 'stash@{1}'` etc to find your code. the single quotes are important, because `{` is a bash metacharacter. – Alex Brown Jan 15 '14 at 06:55
  • Ah, can you reword your question - such as 'I stashed some code but don't know which stash it is in' – Alex Brown Jan 15 '14 at 06:56
  • Thank you @Alex Brown - the tip about 'stash@{0}' helped – user811433 Jan 15 '14 at 07:23
  • FYI: You can use git stash show 0, git stash show 1, etc... I haven't seen it documented anywhere, but it works at least in git version 2.19.0 – DylanYoung Jan 08 '19 at 21:26

6 Answers6

18

Try this:

git stash list -p | grep 'diff --git' | grep <your file name>

That will find your files in the list. It might take a while.

One thing: git stash apply does not discard a stash. After a successful apply, you should git stash drop so it dos not clutter your list. Personally, I apply the stash using git stash pop.

Alex Siri
  • 2,856
  • 1
  • 19
  • 24
17

To search inside the changes in your stashes, use git stash list with the pickaxe option -G (from git log):

git stash list -G regex_matching_some_added_or_removed_string
Dag Høidahl
  • 7,873
  • 8
  • 53
  • 66
6

Note: in case of stashed merged commit, a git stash list -p would return nothing.
That will change with Git 2.2 (Q4 2014) and commit 288c67c by Jeff King (peff):

stash: default listing to working-tree diff

When you list stashes, you can provide arbitrary git log options to change the display. However, adding just "-p" does nothing, because each stash is actually a merge commit.

This implementation detail is easy to forget, leading to confused users who think "-p" is not working. We can make this easier by defaulting to "--first-parent -m", which will show the diff against the working tree.
This omits the index portion of the stash entirely, but it's simple and it matches what "git stash show" provides.

People who are more clueful about stash's true form can use "--cc" to override the "-m", and the "--first-parent" will then do nothing.
For diffs, it only affects non-combined diffs, so "--cc" overrides it.
And for the traversal, we are walking the linear reflog anyway, so we do not even care about the parents.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
6

This is the command I use. It helps me identify which stash is being referred to.

git stash list | while IFS=: read STASH ETC; do echo "$STASH: $ETC"; git diff --stat $STASH~..$STASH --; done | grep -e 'stash\|<partial_name_of_file_being_searched_for>'

I also use it in conjunction with an alias in my .bashrc file like so:

function gitsearch()
{
   searchCrit='stash\|'$1
   git stash list | while IFS=: read STASH ETC; do echo "$STASH: $ETC"; git diff --stat $STASH~..$STASH --; done | grep -e $searchCrit
}
alias githunt=gitsearch

The end result being that I can search my git stashes thus:

githunt LoanApplicationFee

and get the following results where I can quickly see that stash 45 has what I'm looking for:

enter image description here

Uncle Iroh
  • 5,748
  • 6
  • 48
  • 61
5

If you have only a few stashes listed in git stash list then you can examine them one by one to see if they are the correct one:

git show 'stash@{0}'
git show 'stash@{1}'

etc.

If you have some code in many stashes, and can remember a string or keyword you typed in a file which (almost) uniquely identifies that code (I use DUNKIRK here), search for it using the following bash command.

for i in `git reflog --pretty=format:%H stash`; do git grep DUNKIRK $i; done

note that git grep searches the whole checkout - not just the changes.

Compare the answer from @siri, which searches for filenames which are changed in the stashes - which is another useful strategy.

Alternatively, to search only the diffs

 git reflog -p stash | less

and then search for your strings OR files, or just browse it. This might be large.

Alex Brown
  • 41,819
  • 10
  • 94
  • 108
1

A combination of git commands from the above answers helped me with what I need. Posting my answer here as it might help others and because I cant accept any one single answer/comment

git stash list -p - showed me the list of stashes

git stash pop 'stash@{12}' - popped out the 12th stash which contains my code.
user811433
  • 3,999
  • 13
  • 53
  • 76