tags:

views:

387

answers:

3

I have a small patch saved away in my git stash. I've applied it to my working copy using git stash apply. Now, I'd like to back out those changes by reverse applying the patch (kind of like what git revert would do but against the stash).

Does anyone know how to do this?

Clarification: There are other changes in my working copy. My particular case is hard to describe but you can imagine some debugging or experimental code that's in the stash. Now it's mixed in my working copy with some other changes and I'd like to see the effect with and without the changes from the stash.

It doesn't look like stash supports this currently, but a git stash apply --reverse would be a nice feature.

A: 

Can't just just create a reversed patch by diffing between the current and previous revision? And then apply that one?

Magnus Skog
A: 

"git stash [save]" takes your working directory state, and your index state, and stashes them away, setting index and working area to HEAD version.

"git stash apply" brings back those changes, so "git reset --hard" would remove them again.

"git stash pop" brings back those changes and removes top stashed change, so "git stash [save]" would return to previous (pre-pop) state in this case.

Jakub Narębski
+5  A: 

According to the git-stash manpage, "A stash is represented as a commit whose tree records the state of the working directory, and its first parent is the commit at HEAD when the stash was created," and git stash show -p gives us "the changes recorded in the stash as a diff between the stashed state and its original parent.

To keep your other changes intact, use git stash show -p | patch --reverse as in the following:

$ git init
Initialized empty Git repository in /tmp/repo/.git/

$ echo Hello, world >messages

$ git add messages

$ git commit -am 'Initial commit'
[master (root-commit)]: created 1ff2478: "Initial commit"
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 messages

$ echo Hello again >>messages

$ git stash

$ git status
# On branch master
nothing to commit (working directory clean)

$ git stash apply
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   messages
#
no changes added to commit (use "git add" and/or "git commit -a")

$ echo Howdy all >>messages

$ git diff
diff --git a/messages b/messages
index a5c1966..eade523 100644
--- a/messages
+++ b/messages
@@ -1 +1,3 @@
 Hello, world
+Hello again
+Howdy all

$ git stash show -p | patch --reverse
patching file messages
Hunk #1 succeeded at 1 with fuzz 1.

$ git diff
diff --git a/messages b/messages
index a5c1966..364fc91 100644
--- a/messages
+++ b/messages
@@ -1 +1,2 @@
 Hello, world
+Howdy all

Edit:

A light improvement to this is to use git apply in place of patch:

git stash show -p | git apply --reverse

I've been finding this really handy lately...

Greg Bacon
Awesome, thanks. Seems like this might be a nice feature for stash.
Pat Notz