Inspecting changes

Author

Marie-Hélène Burle

While git status gives you information on the files that were changed since the last commit, it doesn’t provide any information on what those changes are.

In this section, we will see how we can get information on the changes to the files contents.

The three trees of Git

Before we can jump into this section, we need to understand a bit more how Git works.

One useful mental representation is to imagine three file trees:

noshadow

The working tree

Let’s imagine that you are starting to work on a project.

First, you create a directory.
In it, you create several sub-directories.
In those, you create a number of files.

You can open these files, read them, edit them, etc. This is something you are very familiar with.

In the Git world, this is the working directory or working tree of the project.
That is: an uncompressed version of your files that you can access and edit.
You can think of it as a sandbox because this is where you can experiment with the project. This is where the project gets developed.

Now, Git has two other important pieces in its architecture.

The index

If you want the project history to be useful to future you, it has to be nice and tidy. You don’t want to record snapshots haphazardly or you will never be able to find anything back.

Before you record a snapshot, you carefully select the elements of the project as it is now that would be useful to write to the project history together. The index or staging area is what allows to do that: it contains the suggested future commit.

git diff

The command git diff prints the differences between any two Git objects. In particular, it allows to compare any two of the three trees with each other.

Diff between working directory & index

noshadow

git diff displays the differences between the working directory (the uncompressed files) and the index (the staging area):

git diff

Right now, git diff does not return anything because our working tree and staging area are at the same point.

Let’s make some changes in our proposal:

nano ms/proposal.md

Now, if we run git diff again, we get:

diff --git a/ms/proposal.md b/ms/proposal.md
index 0fb5cc8..4fdc1b0 100644
--- a/ms/proposal.md
+++ b/ms/proposal.md
@@ -16,4 +16,4 @@ We hope to achieve a lot.

 # Conclusion

-This is truly a great proposal.
+This is truly a great proposal, but it needs a little more work.

Diff between index & last commit

noshadow

To see what would be committed if you ran git commit (that is the differences between the index and the last commit), you need to run instead:

git diff --cached

We aren’t getting any output because we haven’t staged anything that isn’t in our last commit. Let’s stage our changes and try again:

git add .
git diff --cached
diff --git a/ms/proposal.md b/ms/proposal.md
index 0fb5cc8..4fdc1b0 100644
--- a/ms/proposal.md
+++ b/ms/proposal.md
@@ -16,4 +16,4 @@ We hope to achieve a lot.

 # Conclusion

-This is truly a great proposal.
+This is truly a great proposal, but it needs a little more work.

The changes are now between the staging area and HEAD.

If we run git diff now, we aren’t getting any output because the staging area has caught up with the working tree: they are now the same, so no differences.

git diff --cached is very convenient to check what will enter in the next commit.

Diff between working directory & last commit

noshadow

Finally, to see the differences between your working directory and HEAD, you run:

git diff HEAD

This will be the sum of the previous two.

Right now, git diff --cached and git diff HEAD print the same result, but if we make new changes, they will become different since git diff HEAD will reflect all the changes between the working tree and the last commit, while git diff --cached will only contain the differences between the staging area and the last commit.

Your turn:

Modify one of the tracked files to visualize this.