Skip to content

git diff

Description

The git diff command is used to compare changes between commits, the working tree, and the staging area. It takes two input data sets and outputs the modifications between them. Commonly, it is used in combination with git status and git log commands for analyzing the state of a git repository.

gitdiff

Diff outputs

Diffing can have multiple outputs that will be discussed below.

Raw output format

Take a look at the commands below to create a simple repository:

git diff

bash
mkdir test_repo
cd test_repo
touch test.txt
echo "this is a git diff test example" > test.txt
git init .
#Initialized empty Git repository in /Users/kev/code/test/.git/
git add test.txt
git commit -am "add diff test file"
#[master (root-commit) 9e2dcac] add diff test file
#1 file changed, 1 insertion(+)
#create mode 100644 test.txt

If you want the git diff to have an output, you have to change the content of the test.txt file after adding it to the created repository. You can do it by executing the following command:

git diff

bash
echo "this is a diff example" > test.txt

Only now we can view a diff and discuss output. Executing git diff will produce the following:

git diff

bash
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Diff input sources

Below you can find the comparison input of diff. As a result, a/test.txt and b/test.txt will be passed to the diff.

git diff

bash
diff --git a/test.txt b/test.txt

Meta data

This line shows some internal Git meta data. The numbers in this output match to Git object version hash identifiers.

git diff

bash
index 6b0c6cf..b37e70a 100644

Symbols for changes

These lines show the symbols assigned to each diff input source. Changes from a/test.txt are marked with a --- and the changes from b/test.txt are marked with the +++ symbol.

git diff

bash
--- a/test.txt
+++ b/test.txt

Diff chunks

A diff doesn’t show the whole file. It shows only modified lines. That modified portion is called a "chunk". The advantage of the chunks is that they show lines before and after the changes, so you can have a better understanding of the modifications.

git diff

bash
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

The first line is the chunk header. Each chunk is placed by a header within @@ symbols. The changes made to the file are summarized in the header.

Common flags

Git provides several useful flags for different workflows:

  • --staged (or --cached): Compares the staged changes in the index against the HEAD commit.
  • --stat: Shows a condensed summary of changed files instead of the full diff.
  • --name-only: Outputs only the names of changed files.

Highlighting changes

You can use the following 2 tools for highlighting changes so that they will be more visible.

git diff --color-words

The first way of highlighting changes is the special mode that git diff proposes: --color-words. It tokenizes added and removed lines by whitespace and then diffs those.

git diff

bash
git diff --color-words
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

(Note: --color-words highlights inline changes using terminal colors. In plain text, the output format matches standard diff.)

git diff-highlight

In the case of cloning the git source, a sub-directory called contrib will be found. This sub-directory contains tools that are related to Git. One of these tools is called diff-highlight. It highlights changed sub-word pieces. Note that this tool filters standard input and requires terminal coloring to be visible.

git diff

bash
git diff | git diff-highlight
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Diffing binary files

Git diff can be run not only on text files, but also on binary ones. The default option can sometimes be not very useful.

git diff

bash
git diff
Binary files a/script.pdf and b/script.pdf differ

Git has a feature allowing you to specify a shell command to convert the binary files content into text prior to performing the diff. However, a little set up may be required. First of all, you should define a textconv filter with the description of the conversion way of a certain type of binary to a text. For example, you can use a simple utility called pdftohtml (available through homebrew) to convert PDF into HTML. There are two ways of setting it up: by editing the .git/config file, or globally, by editing .gitconfig.

git diff

bash
[diff "pdfconv"]
textconv=pdftohtml -stdout

Then you need to connect one or more file patterns with the pdfconv filter, which can be done by creating a .gitattributes file in the root of the repository.

git diff

bash
*.pdf diff=pdfconv

After the configuration, git diff will firstly run the binary file via the configured converter script and diff the output of the converter. Using the same technique, you can also have helpful diffs from all types of a binary file (zips, jars, and other archives).

Comparison of files: git diff file

The git diff command has also an explicit file path option. The git diff operation will process the specific file once the file path is passed to it. In the example below, the ./path/to/file argument will compare the modifications in the working directory against the HEAD commit.

git diff

bash
git diff HEAD ./path/to/file

Comparison of all changes

In order to compare changes throughout the whole repo, you should run git diff without a file path. So, you can invoke the examples above without the ./path/to/file argument and have the same results across all files in the local repository.

Changes since the recent commit

By default, git diff compares the working directory against the staging area (index). To see all uncommitted changes since the most recent commit:

git diff

bash
git diff

Comparison of files between two commits

The git diff command can be passed to Git refs, such as names of heads, tags, and branches. Every commit in Git has a unique commit ID, which you can find by executing git log. You can also pass two commit IDs to compare them directly:

git diff

bash
git diff <commit-hash-1> <commit-hash-2>

Comparison of branches

The comparison of branches is executed similarly to other ref inputs to git diff. Let’s see dot operator examples:

git diff

bash
git diff branch1..branch2

The two dots in the example above show that the diff input is the tips of both branches. You will have the same result if the dots are left out and space is used between the branches. Besides, there is a three-dot operator:

git diff

bash
git diff branch1...branch2

The three-dot operator changes the first input parameter branch1 initiating the diff. It transforms branch1 into a ref of the shared common ancestor commit between the two diff inputs. The last input parameter stays the same as the tip of branch2.

Comparison of the files from two branches

In order to compare a specific file in branches, you should pass in the path of the file as the third argument to git diff:

git diff

bash
git diff master new_branch ./test.txt

Practice

What are the functionalities and options of the 'git diff' command?

Dual-run preview — compare with live Symfony routes.