0

I've recently come across this answer on SO. It provides a recipe on how to reverse changes made by applied stash but preserve other changes to files. I've tried going through the script provided as an example but my patch failed:

Checking patch messages... 
error: while searching for: 
Hello, world 
Hello again 

error: patch failed: messages:1

I've noticed that the answer is of 2009, is this approach valid today? What I'm also curios about is that AFAIK when git applies a patch is searches for context lines before and after the change, but in the example in the question the context after the change won't match, how's then a patch supposed to be applied?

Community
  • 1
  • 1
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488

1 Answers1

1

A stash is just a commit as any other and therefore can be reverted.

Let's assume you did

git stash

and later

git stash pop

which will restore the changes in your working directory. Now you keep on working and you modify other files. Finally you commit all changes as a new commit.

Now if you only want to revert only the changes that came from the stash you can do it if you know the stash's commit id. Since you did a stash pop it is gone and git will not make a reflog entry.

But you might recover it searching for dangling commits. E.g.

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

but it is easier if you use gitk

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

Look for a merge commit. Git stores stashs as merge commits, because it saves the actual staged changes in a commit named index on trunk: ... and the actual working dir changes as the merge commit of the staged changes and the HEAD the stash depends on.

In git a stash commit look like this:

  HEAD
    |
    V
A---B---D <-- stash commit
     \ /
      C <-- staged changes commit

If you found the stash commit you can revert it using it's id. According to the example above you would do a

git revert -m 1 D
René Link
  • 48,224
  • 13
  • 108
  • 140
  • Thanks, but my question is about the other thing, specifically why `git apply -R` fails but in the example it does not? I also think that `git revert` does the same job as `git stash show -p | git apply -R`: finds the difference introduced by the commit, makes a patch of it and applies it in reverse, correct? – Max Koretskyi Apr 25 '15 at 16:22
  • Also, I tried `git revert -m 1 stash@{0}` but it didn't remove the `Hello again` line also revert went without errors. I didn't stash popped my stash so I was able to refer to it as `stash@{0}` – Max Koretskyi Apr 26 '15 at 08:50