88

How can I diff my current working copy against a stash?

My use case: my working copy already contains a subset of the changes in my stash@{0}, but I don't want to apply all the changes in stash@{0}. I want to do a diff to help determine which desirable changes in stash@{0} are still missing from my working copy.

Max Wallace
  • 3,609
  • 31
  • 42
Laughing monster
  • 889
  • 1
  • 6
  • 4

10 Answers10

56

If it was your most recent stash, git diff stash@{0} will do it. If not, you can use git stash list to get the index of which stash you want to compare to.

To see the difference between the actual working copy and the stash you would need to commit it first. You could then rollback the commit.

git add -A                   <- Add all the files
git commit -m "temp"         <- commit them
git diff stash@{0}..HEAD     <- diff the commit with your stash
git reset HEAD~              <- roll your commit back
Magne
  • 16,401
  • 10
  • 68
  • 88
Andy
  • 44,610
  • 13
  • 70
  • 69
  • 1
    And did it not work? What were you expecting and what did you get? – Andy Nov 08 '11 at 23:58
  • I've only stashed a few files. 'git diff stash@{0}' result showed pages and pages of diff results. I expect just a one page with the diffs which are about the files which were stashed. But the diff result was showing me diffs about files which i did not stash. – Laughing monster Nov 09 '11 at 00:18
  • Do any of the changes look familiar? Are you sure you're checking the right stash against the correct working dir? – Andy Nov 09 '11 at 00:48
  • no the diff results are not from my stash.:( Anyway, to get moving along, I applied the stash and merged/removed the changes anyway. So I don't need to do this diff anymore... Thanks alot for helping anyway. Cheers. – Laughing monster Nov 09 '11 at 03:25
  • 13
    this only diffs against the latest commit, not the working (dirty) copy, right? – Magne Jan 21 '13 at 12:24
  • 2
    It should diff against your working dir. If you want to diff against what you have checked out, you would need `git diff HEAD stash@{0}` – Andy Jan 21 '13 at 14:18
  • If you see: `fatal: ambiguous argument 'stash@0': unknown revision or path not in the working tree.` Then escape the {} with \: `git diff stash@\{0\}` – Sooth Aug 31 '15 at 21:46
  • 5
    This diffs against the latest commit indeed. – Iulian Onofrei May 10 '17 at 07:22
  • 5
    Why is this upvoted when it clearly doesn't do what is asked. Downvoted. – lucid_dreamer Jul 20 '17 at 00:03
  • Downvoted. This does not answer the question. You should edit to clarify that it only compares against the last commit (not working treee). – Alexandros Sep 04 '19 at 15:39
  • I'm glad to see my suggested solution https://stackoverflow.com/a/14439846/380607 has made it into this answer, so that it now diffs the working (dirty) copy with the stash. – Magne Jun 01 '20 at 06:08
29

If your working tree is dirty, you can compare it to a stash by first committing the dirty working tree, and then comparing it to the stash. Afterwards, you may wish to undo the commit of your working tree (to keep your history clean).

  • Commit your dirty working tree:

    git add .
    git commit -m "Dirty commit"
    
  • Diff the stash with that commit:

    git diff stash@{0}
    
  • Then, afterwards, you may revert the commit, and put it back in the working dir:

    git reset --soft HEAD~1
    git reset .
    

Now you've diffed the dirty working tree with your stash, and are back to where you were initially.

Max Wallace
  • 3,609
  • 31
  • 42
Magne
  • 16,401
  • 10
  • 68
  • 88
  • 5
    This should be more heavily upvoted. For starters, it actually does what the question asks (most answers compare to last commit, not working tree). Furthermore it is complete as even though it uses a "temporary commit" of the working tree to achieve the goal, it also shows you how to revert that commit and go back to your working tree. – Alexandros Sep 04 '19 at 14:24
23

You can't do this without either commiting or stashing your working copy. Stashing is probably lower-risk:

git add -A                    # Stage all changes in your working copy.
git stash save --keep-index   # Stash your working copy and leave it intact
git diff stash@{0} stash@{1}

To get rid of the stash you just made for the sake of diffing, use git stash pop or git stash drop stash@{0}.

If you want to use a commit instead, see @Magne's answer.

Community
  • 1
  • 1
Max Wallace
  • 3,609
  • 31
  • 42
  • 1
    That is really a good way to compare the working copy to a stash, thanks! – Peter T. Jul 02 '18 at 11:39
  • 2
    +1 This is also handy if you use stashes as a form of "checkpoint" when making a large change that you don't want to commit until it is fully formed. Make changes then stash them, make some more and stash again. Then use something like `git difftool -d stash@{3} stash@{0}` to see a directory diff of all the changes made between two stashes of interest. – Eric Mutta Jul 22 '21 at 17:40
15

I think OP wanted the answer to see what difference the stash contains other than the files present in the working copy.

The following command shows what stash contains.

git stash show -p stash@{0}
niksvp
  • 5,545
  • 2
  • 24
  • 41
6

You can use git stash show -l. It shows what you want without extra stash or commit.

MOHRE
  • 1,096
  • 4
  • 15
  • 28
  • Although the `-l` option works, it isn’t mentioned in `git help stash`. Where is it documented? – Chris Page Feb 19 '19 at 23:44
  • I don't know. I find it by accident. – MOHRE Feb 20 '19 at 06:32
  • 2
    I remember having used this in the past. As I always end up forgetting I come often to this answer. In my newer version of git it throws an error `error: switch l requires a value` – Iker Nov 27 '19 at 03:23
4

To do a diff of a file or folder present in the working directory with that in a stash you can do:

git diff stash@{0} -- /path/to/fileorfolder

Here stash@{0} just represents a commit HASH, so it works exactly as git diff works. stash@{0} is just a handler.

Wilson F
  • 1,250
  • 1
  • 20
  • 37
alpha_989
  • 4,882
  • 2
  • 37
  • 48
  • +1 to get a dir diff of the entire working directory vs the contents in the stash, you do `git difftool --dir-diff --no-prompt stash@{0} -- /source/folder/path/here` – Eric Mutta Jan 22 '22 at 22:53
2

You can use the Unix diff command in conjunction with two Git commands just like so:

diff <(git diff) <(git stash show -p stash@{0})

Of course you can change the stash@{0} to whatever stash you want. This command is actually comparing the actual working directory (git diff) with one of your stashes.

UPDATE

You can also install colordiff and see a much much better result:

Installation:

  • Ubuntu/Debian: sudo apt-get install colordiff
  • OS X: brew install colordiff

and then just change command to :

colordiff <(git diff) <(git stash show -p stash@{0})
Petros Mitakos
  • 151
  • 1
  • 5
  • This usage of colordiff didn't work as expected in Windows 10's bash (inside ConEmu, diff 3.3). – o.v Mar 19 '20 at 18:26
0

Not sure what the OP wanted, but I use this to see what the actual diff set of the stash is:

git difftool stash@{0}^!

or

git diff stash@{0}^!

or

git diff stash@{0}^! > patchfile

Wayne Walker
  • 2,316
  • 3
  • 23
  • 25
  • @Wayne, Thanks for your answer..Could you explain what does the `^!` do here? Haven't seen this before... – alpha_989 Jun 19 '18 at 16:02
  • 1
    @alpha_989 From https://git-scm.com/docs/revisions: `The 'r1^!' notation includes commit 'r1' but excludes all of its parents. By itself, this notation denotes the single commit 'r1'.` – heidi Aug 08 '18 at 20:34
  • 1
    This does not answer the question. It only shows the diff of the stash, not how it compares to the working tree. – Chris Page Aug 09 '18 at 22:06
0

Yes you can use git stash show -p , check this Git diff against a stash for more information.

Community
  • 1
  • 1
0
diff <(git diff --color) <(git stash show -p --color)
diff <(git diff --color) <(git stash show -p --color stash@{1})

Based on @petros-mitakos answer, this one about git --color option and diff's ability to show git diff's colors.

o.v
  • 835
  • 10
  • 15