See full details in the Git docs: git-diff

Related - diff-index cheatsheet.

Help

Short help:

$ git diff -h
usage: git diff [<options>] [<commit> [<commit>]] [--] [<path>...]

Long help:

$ git diff --help

Long help output:

NAME
       git-diff - Show changes between commits, commit and working tree, etc

SYNOPSIS
       git diff [<options>] [<commit>] [--] [<path>...]
       git diff [<options>] --cached [<commit>] [--] [<path>...]
       git diff [<options>] <commit> <commit> [--] [<path>...]
       git diff [<options>] <blob> <blob>
       git diff [<options>] --no-index [--] <path> <path>

DESCRIPTION
       Show changes between the working tree and the index or a tree, changes between the index and a tree, changes between two
       trees, changes between two blob objects, or changes between two files on disk.

       ...

So you can run against zero, one or two commits. And can specify paths.

Basic

Show file names and line changes. Ignores staged files.

git diff [COMMIT_REF] [COMMIT_REF]

Compares possibly modified files to the files at the current commit.

git diff

Include stage files.

git diff HEAD

Check commit against previous commit.

git diff HEAD~

Show names of modified files and not lines changed. This is like a very short git status with no color and indentation. Note this is does not include untracked files.

git diff --names-only

e.g.

foo/bar.txt

Compare current commit against remote.

git diff origin/master

Compare two commit references. Note the order matters.

git diff HEAD~3..HEAD~5

git diff HEAD~3 HEAD~5

git diff feature-a feature-b

Select scope

What commits or files to run against.

Default - no arguments

$ git diff

This will include:

  • staged
  • unstaged

But not:

  • untracked

If you have no uncommit changes, you’ll see no output.

If you want untracked files, then git status works file. The line count doesn’t matter so much as the files are new and there is no lines changed.

Staged only

Show diff of stages files only.

All the other flags below also assume all files that are tracked, unless you specifically ask for staged/cached, which can include previously untracked files.

$ git diff --cached

Note --cached and --staged are synonyms.

Compare current against a commit

Specify target past commit only to compare against current HEAD. You might want to stash changes first.

$ git diff COMMIT

e.g.

$ git diff HEAD~

$ git checkout feature
$ git diff master

Compare two commits

$ git diff COMMIT COMMIT

The order doesn’t matter.

e.g.

$ git diff HEAD~5 HEAD~7
$ git diff master feature

This works too and is similar to what you’d run for git log.

$ git diff HEAD~5..HEAD~7

No index option

Compare when at least one of the filse is out the repo, or the entire command is run outside the repo.

$ git diff [<options>] --no-index [--] <path> <path>

Ignore submodules

--ignore-submodules[=<when>]

Ignore changes to submodules in the diff generation. can be either "none", "untracked", "dirty" or "all", which is the default.

Output modes

Patch

This is the default.

$ git diff -p

This can be hidden with s for --no-patch

Output to file

Output to a specific file instead of stdout.

--output=<file>

Raw

Generate the diff in raw format.

e.g.

$ git diff --raw
:100755 100755 0f5324b 0000000 M        genesis/install.sh
:100755 100755 b3858ab 0000000 M        genesis/upgrade.sh

Stat

--stat - see docs

$ git diff --stat
 genesis/install.sh |  5 ++---
 genesis/upgrade.sh | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

Short stat

Output only the last line of the –stat format containing total number of modified files, as well as number of added and deleted lines.

$ git diff --shortstat
 2 files changed, 16 insertions(+), 3 deletions(-)

Summary

--summary

Output a condensed summary of extended header information such as creations, renames and mode changes.

$ git diff --summary --staged
 create mode 100644 src/my-git.ts

Note this is only useful in certain cases such as when there is a new file AND it is staged. Otherwise you’ll see no output. The other flags would be more useful.

Compact summary

--compact-summary

Output a condensed summary of extended header information such as file creations or deletions (“new” or “gone”, optionally “+l” if it’s a symlink) and mode changes (“+x” or “-x” for adding or removing executable bit respectively) in diffstat. The information is put between the filename part and the graph part. Implies –stat.

e.g.

$ git diff --compact-summary
 genesis/install.sh |  5 ++---
 genesis/upgrade.sh | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)
 src/my-git.ts (new) | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

Name only

$ git diff --name-only
genesis/install.sh
genesis/upgrade.sh

Name and status

This is similar to git status.

--name-status

Show only names and status of changed files. See the description of the –diff-filter option on what the status letters mean.

e.g.

$ git diff --name-status
M       opm/datadog/Makefile
M       opm/datadog/README.md

That is the same as running:

$ git diff-index HEAD --name-status

Or

$ git status --short

Hook

Copied from sample hook:

git diff --cached --name-status -r

Breaking that down from the help:

--staged is a synonym of --cached

--name-status
    Show only names and status of changed files. See the description of the --diff-filter
    option on what the status letters mean.

--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]
    Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed
    (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T), are
    Unmerged (U), are Unknown (X), or have had their pairing Broken (B). Any combination
    of the filter characters (including none) can be used. When * (All-or-none) is added
    to the combination, all paths are selected if there is any file that matches other
    criteria in the comparison; if there is no file that matches other criteria, nothing
    is selected.