62

What are the differences between the following git commands?

  1. git diff HEAD
  2. git diff HEAD^
  3. git diff --cached or the synonym git diff --staged
  4. git diff
Matthew Rankin
  • 457,139
  • 39
  • 126
  • 163

5 Answers5

133
  1. git diff HEAD - Shows what has changed since the last commit.
  2. git diff HEAD^ - Shows what has changed since the commit before the latest commit.
  3. git diff --cached - Show what has been added to the index via git add but not yet committed.
  4. git diff - Show what has changed but hasn't been added to the index yet via git add.

It looks like this:

     Working
    Directory  <----+--------+------+
        |           |        |      |    
        |           |        |      |
        V           |        |      |    
    "git add"       |        |      |    
        |         diff       |      |    
        |           |        |      |    
        V           |        |      |    
     Index     <----+    diff HEAD  |            
        |           |        |      |       
        |           |        |      |
        V           |        |      |       
  "git commit"      |        |      |
        |     diff --cached  |      |
        |     diff --staged  |      |
        V           |        |      |
      HEAD     <----+--------+      |
        |                           |
        |                        diff HEAD^
        V                           |
previous "git commit"               |
        |                           |
        |                           |
        V                           |
      HEAD^    <--------------------+
Community
  • 1
  • 1
Amber
  • 507,862
  • 82
  • 626
  • 550
  • 1
    @Picasso Is it hand drawn or did you used some ASCII art tool? Is there any git command for this too? ;) – takeshin Sep 10 '10 at 20:41
  • @takeshin: Hand-drawn; it's not that hard. (But there is an emacs mode for drawing ascii art, not that I use it.) – Amber Sep 11 '10 at 02:38
  • 15
    +1 for the ascii-art alone. One image = 1000 words; One ascii-art = 1025 chars. – Thalis K. Mar 07 '14 at 15:48
  • `git diff - Show what has changed but hasn't been added to the index yet via git add.` : this isn't entirely correct, if working directory (WD), IDX and HEAD are not equal then `git diff` will show changes from IDX(red) -> WD(green), pls correct if I'm wrong. – dkjain Feb 17 '18 at 13:16
  • Something's confusing! "git add" alone doesn't change the files so there musn't be really a difference shown by "git diff" according to the diagram above... . It seems that git diff shows the difference between the working directory and the last commit... Am I wrong? – aderchox Nov 20 '18 at 18:17
  • @Narnia `git diff` by default shows the difference between the working directory and the *index*. The index's version of a file reflects any changes that were added by `git add`, even if they aren't committed yet. – Amber Nov 23 '18 at 06:21
11
  1. git diff HEAD : Diff between HEAD and the working directory.
  2. git diff HEAD^ : Diff between the direct ancestor of HEAD and the working directory.
  3. git diff --cached or the synonym git diff --staged : Diff between HEAD and the index.
  4. git diff : Diff between the index and the working directory.
Adriano
  • 19,463
  • 19
  • 103
  • 140
wRAR
  • 25,009
  • 4
  • 84
  • 97
  • 4
    Does anyone have a good way to remember this? I keep coming back here. – Kevin Wheeler Sep 13 '15 at 22:48
  • Could you please tell me why should index and working directory be different? "git add " doesn't change the file! It seems to me that git diff shows the difference between the working directory and the last commit... . I'm not sure though. – aderchox Nov 20 '18 at 18:20
  • 1
    @Narnia `git add ` changes the file *in the index*. It's hard to explain the index in the comments. – wRAR Nov 21 '18 at 22:00
  • @wRAR Then would you please ask the proper question and answer it yourself? (It is allowed and even AFAIK recommended by SO). – aderchox Nov 21 '18 at 22:03
  • 1
    @Narnia see e.g. https://stackoverflow.com/questions/3689838/whats-the-difference-between-head-working-tree-and-index-in-git – wRAR Nov 23 '18 at 10:42
11

From the Git Community Book:

git diff

will show you changes in the working directory that are not yet staged for the next commit.

git diff --cached

will show you the difference between the index and your last commit; what you would be committing if you run "git commit" without the "-a" option.

git diff HEAD

shows changes in the working directory since your last commit; what you would be committing if you run "git commit -a".

Matthew Rankin
  • 457,139
  • 39
  • 126
  • 163
6

Here's a simple way to remember these commands:

  • By default, git diff's source is assumed to be the working directory, and its target is the index.
  • Adding the --cached flag changes the source to be the index. It doesn't necessarily change the target once you add more arguments. But for convenience the target becomes the last commit if none is provided.
  • Adding a commit as an argument changes the target.
  • Adding two commits as arguments changes both the source and the target, respectively.

Have fun mixing them up to your own liking :)

gunby
  • 71
  • 1
  • 1
0

HEAD is the current HEAD pointer in the tree, HEAD^ is the commit before HEAD. --cached I'm not sure about.--cached will show you any changes you have made but haven't added to the index.

The git tutorial on kernal.org is a very good read.

Josh K
  • 28,364
  • 20
  • 86
  • 132
  • 2
    You got `--cached` slightly wrong: it shows you only changes that you *have* added to the index (but haven't committed). – Amber Sep 11 '10 at 02:39