git diff Command: Show Changes Between Commits
Every change in a Git repository can be inspected before it is staged or committed. The git diff command shows the exact lines that were added, removed, or modified — between your working directory, the staging area, and any two commits or branches.
This guide explains how to use git diff to review changes at every stage of your workflow.
Basic Usage
Run git diff with no arguments to see all unstaged changes — differences between your working directory and the staging area:
git diffdiff --git a/app.py b/app.py
index 3b1a2c4..7d8e9f0 100644
--- a/app.py
+++ b/app.py
@@ -10,6 +10,7 @@ def main():
print("Starting app")
+ print("Debug mode enabled")
run()
Lines starting with + were added. Lines starting with - were removed. Lines with no prefix are context — unchanged lines shown for reference.
If nothing is shown, all changes are already staged or there are no changes at all.
Staged Changes
To see changes that are staged and ready to commit, use --staged (or its synonym --cached):
git diff --stagedThis compares the staging area against the last commit. It shows exactly what will go into the next commit.
git diff --cachedBoth flags are equivalent. Use whichever you prefer.
Comparing Commits
Pass two commit hashes to compare them directly:
git diff abc1234 def5678To compare a commit against its parent, use the ^ suffix:
git diff HEAD^ HEADHEAD refers to the latest commit. HEAD^ is one commit before it. You can go further back with HEAD~2, HEAD~3, and so on.
To see what changed in the last commit:
git diff HEAD^ HEADComparing Branches
Use the same syntax to compare two branches:
git diff main feature-branchThis shows all differences between the tips of the two branches.
To see only what a branch adds relative to main — excluding changes already in main — use the three-dot notation:
git diff main...feature-branchThe three-dot form finds the common ancestor of both branches and diffs from there to the tip of feature-branch. This is the most useful form for reviewing a pull request before merging.
Comparing a Specific File
To limit the diff to a single file, pass the path after --:
git diff -- path/to/file.pyThe -- separator tells Git the argument is a file path, not a branch name. Combine it with commit references to compare a file across commits:
git diff HEAD~3 HEAD -- path/to/file.pySummary with –stat
To see a summary of which files changed and how many lines were added or removed — without the full diff — use --stat:
git diff --stat app.py | 3 +++
config.yml | 1 -
2 files changed, 3 insertions(+), 1 deletion(-)
This is useful for a quick overview before reviewing the full diff.
Word-Level Diff
By default, git diff highlights changed lines. To highlight only the changed words within a line, use --word-diff:
git diff --word-diff@@ -10,6 +10,6 @@ def main():
print("[-Starting-]{+Running+} app")
Removed words appear in [-brackets-] and added words in {+braces+}. This is especially useful for prose or configuration files where only part of a line changes.
Ignoring Whitespace
To ignore whitespace-only changes, use -w:
git diff -wUse -b to ignore changes in the amount of whitespace (but not all whitespace):
git diff -bThese options are useful when reviewing files that have been reformatted or indented differently.
Quick Reference
For a printable quick reference, see the Git cheatsheet .
| Command | Description |
|---|---|
git diff |
Unstaged changes in working directory |
git diff --staged |
Staged changes ready to commit |
git diff HEAD^ HEAD |
Changes in the last commit |
git diff abc1234 def5678 |
Diff between two commits |
git diff main feature |
Diff between two branches |
git diff main...feature |
Changes in feature since branching from main |
git diff -- file |
Diff for a specific file |
git diff --stat |
Summary of changed files and line counts |
git diff --word-diff |
Word-level diff |
git diff -w |
Ignore all whitespace changes |
FAQ
What is the difference between git diff and git diff --staged?git diff shows changes in your working directory that have not been staged yet. git diff --staged shows changes that have been staged with git add and are ready to commit. To see all changes — staged and unstaged combined — use git diff HEAD.
What does the three-dot ... notation do in git diff?git diff main...feature finds the common ancestor of main and feature and shows the diff from that ancestor to the tip of feature. This isolates the changes that the feature branch introduces, ignoring any new commits in main since the branch was created. In git diff, the two-dot form is just another way to name the two revision endpoints, so git diff main..feature is effectively the same as git diff main feature.
How do I see only the file names that changed, not the full diff?
Use git diff --name-only. To include the change status (modified, added, deleted), use git diff --name-status instead.
How do I compare my local branch against the remote?
Fetch first to update remote-tracking refs, then diff against the updated remote branch. To see what your current branch changes relative to origin/main, use git fetch && git diff origin/main...HEAD. If you want a direct endpoint comparison instead, use git fetch && git diff origin/main HEAD.
Can I use git diff to generate a patch file?
Yes. Redirect the output to a file: git diff > changes.patch. Apply it on another machine with git apply changes.patch.
Conclusion
git diff is the primary tool for reviewing changes before you stage or commit them. Use git diff for unstaged work, git diff --staged before committing, and git diff main...feature to review a branch before merging. For a history of committed changes, see the git log guide
.







