Git diff

git diff

Let’s stop for a minute to see how the git diff command can be used to show you the difference between the version of a file in the working directory, index and most recent commit. The 3 main types of git diff commands you would likely use are:

  • git diff: Show differences between your working directory and the index.
  • git diff –cached: Show differences between the index and the most recent commit.
  • git diff HEAD: Show the differences between your working directory and the most recent commit.

This example continues with where we left off at the end of What’s in the index? What’s changed? git status and git ls-files:

  • Both the index and the most recent committed version of the README file have just one line:
This is the README file.
  • The working directory version of the README file is newer and has an additional line:
    This is the README file.
    One more line.

    git diff: Differences between the Working directory and the Index

    The git diff command is used to show the differences between the working directory and the index:

    $ git diff
    diff --git a/README b/README
    index bccdfbd..b0ed415 100644
    --- a/README
    +++ b/README
    @@ -1 +1,2 @@
     This is the README file.
    +One more line.

    The above shows there is a difference between the version of README in the working directory when compared to the version in the index.

    If you have a gui tool such as kdiff3 on your system, you can see a visual representation of the differences by using git difftool:

    $ git difftool
    
    Viewing: 'README'
    Hit return to launch 'kdiff3':

    The following window will then be displayed showing the differences between the README file in the index (on the left) compared with the README file in the working directory (on the right):

    difftool.png

    git diff –cached: Differences between the Index and the most recent commit

    The version of README in the index is the same as the one most recent commit, so a git diff –cached shows no difference:

     $ git diff --cached

    diffs

    git diff HEAD: Show differences between the Working Directory and the most recent commit

    git diff HEAD shows the differences between the working directory and the most recent commit:

    $ git diff HEAD
    diff --git a/README b/README
    index bccdfbd..b0ed415 100644
    --- a/README
    +++ b/README
    @@ -1 +1,2 @@
     This is the README file.
     +One more line.

    Trying To Commit Without Changing the Index

    The job of git commit is to save the current state of the index to the most recent commit.

    However, if we try to git commit when the index and the most recent commit are the same (in our example, no changes have been made to the index since the last git commit), then we get an error:

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

    Update the Index

    The following command will copy any files in the current directory and any subdirectories (only one file in our example) to the index:

    $ git add .

    Now the version of README has been copied from the working directory to the object store and the index has been updated to refer to the new version of README:

    index updated

    The git diff output shows there are no differences between the working directory and the index:

    $ git diff

    There are differences between the index and the most recent commit, since the git commit has not yet been done:

    $ git diff --cached
    diff --git a/README b/README
    index bccdfbd..b0ed415 100644
    --- a/README
    +++ b/README
    @@ -1 +1,2 @@
     This is the README file.
    +One more line.

    The git status command agrees with git diff –cached that the README file has changed:

    $ git ls-files
    README
    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD ..." to unstage)
    #
    #       modified:   README
    #
    $ git commit -m "Added a second line."
    [master bb937de] Added a second line.
     Committer: Tim Flagg <me@gitguys.com>
     1 files changed, 1 insertions(+), 0 deletions(-)

    With the index committed to the repository, git status shows nothing to commit again:

    $ git ls-files
    README
    $ git status
    # On branch master
    nothing to commit (working directory clean)

    The git ls-files shows that README is still in the index: README doesn’t get removed from the index when you do a git commit.

    Another Change To README

    We’ll modify README again:

    $ echo Another line added. >> README
    $ git ls-files
    README
    $ git status
    # On branch master
    # Changed but not updated:
    #   (use "git add ..." to update what will be committed)
    #   (use "git checkout -- ..." to discard changes in working directory)
    #
    #       modified:   README
    #
    no changes added to commit (use "git add" and/or "git commit -a")

    This time we use the -a option to git commit which automatically adds any files that are different between the working directory and the index: In this case, the modified version of the README file is added to the index:

    $ git commit -a -m"Another commit."
    [master 7e2d129] Another commit.
     Committer: Tim Flagg <me@gitguys.com>
     1 files changed, 1 insertions(+), 0 deletions(-)
    $ git ls-files
    README
    $ git status
    # On branch master
    nothing to commit (working directory clean)

    Different in the Working Directory, Index AND Most Recent Commit

    We’ll next add another line to the README file and add the updated file to the git index:

    $ echo line4 added >> README
    $ git add README
    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD ..." to unstage)
    #
    #   modified:   README
    #

    With the updated version of README in the index, let’s not do the git commit and see what happpens when:

    • We modify the README file in the working directory.
    • But don’t do another git add README:
    $ echo line5 added >> README
    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD ..." to unstage)
    #
    #   modified:   README
    #
    # Changed but not updated:
    #   (use "git add ..." to update what will be committed)
    #   (use "git checkout -- ..." to discard changes in working directory)
    #
    #   modified:   README
    #

    The above is telling us:

    • Changes to be committed“: The version of README that was added to the index via the git add command, earlier.
    • Changed but not updated:” The version of README in the working directory was changed, but the changes were not yet added to the index with a git add README type of command.

    README in the working directory has 5 lines and is now:

    This is the README file.
    One more line.
    Another line added.
    line4 added
    line5 added

    README in the index has 4 lines and is now:

    This is the README file.
    One more line.
    Another line added.
    line4 added

    README in the most recent commit has 3 lines and is now:

    This is the README file.
    One more line.
    Another line added.

    It looks like this:

    all different

    Let’s see the differences between the working directory and the index:

    $ git diff
    diff --git a/README b/README
    index e821a27..c64b1f6 100644
    --- a/README
    +++ b/README
    @@ -2,3 +2,4 @@ This is the README file.
     One more line.
     Another line added.
     line4 added
    +line5 added

    The above shows the README file in the index would need to add the line: line5 added to be the same as the README file in the working directory. Or another way to say this is the README file in the working directory added the line: line5 added .

    The git difftool report with kdiff3 looks like this (the index version is on the left and the working directory version is on the right):

    diff2

    The differences between the index and the most recent commit are shown here:

    $ git diff --cached
    diff --git a/README b/README
    index 953937c..e821a27 100644
    --- a/README
    +++ b/README
    @@ -1,3 +1,4 @@
     This is the README file.
     One more line.
     Another line added.
    +line4 added

    The above shows the version of README in the most recent commit would need to add the line: line4 added to be the same as the README file in the index.

    Or, graphically, git difftool –cached shows the following (the most recent commit version is on the left and the index version is on the right):

    diff3

    Note that the diff shows that the version of README in the index has line4 added but not line5 added. The reason: line5 added is only in the working directory, but git diff –cached shows differences between the index and most recent commit and doesn’t look at the working directory at all.

    Next: Commits And Referring To Commits
    Previous: What’s in the index? What’s changed? git status and git ls-files

    Related: