X Xerobit

Git Diff Guide — Reading and Using git diff Commands

git diff shows what changed between commits, branches, or the working tree. Here's how to read git diff output, diff specific files, compare branches, and use diff flags to...

Mian Ali Khalid · · 5 min read
Use the tool
Text Diff
Compare two text blocks line-by-line or word-by-word. Unified and split view. Shows added, removed, and changed segments with full color coding.
Open Text Diff →

git diff shows what changed between states of your repository. Understanding the output and knowing which flags to use makes reviewing changes and debugging history much faster.

Use the text compare tool to compare any two texts side by side.

Basic git diff commands

# Unstaged changes (working tree vs last commit):
git diff

# Staged changes (what will be committed):
git diff --staged
git diff --cached  # same thing

# All changes (staged + unstaged):
git diff HEAD

# Specific file:
git diff README.md
git diff src/components/Header.tsx

# Two commits:
git diff abc1234 def5678

# Last n commits:
git diff HEAD~3 HEAD    # last 3 commits
git diff HEAD~1         # just the most recent commit changes

# Two branches:
git diff main feature-branch

# What's on feature-branch but not main:
git diff main...feature-branch

Reading git diff output

diff --git a/src/utils.js b/src/utils.js
index 3a4b5c6..7d8e9f0 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -15,7 +15,10 @@ function parseConfig(filePath) {
   const data = fs.readFileSync(filePath, 'utf8');
-  return JSON.parse(data);
+  try {
+    return JSON.parse(data);
+  } catch (err) {
+    throw new Error(`Invalid JSON in ${filePath}: ${err.message}`);
+  }
 }

Line by line:

  • diff --git a/... b/... — files being compared
  • index 3a4b5c6..7d8e9f0 — git object hashes of the two versions
  • --- a/src/utils.js — the “before” file
  • +++ b/src/utils.js — the “after” file
  • @@ -15,7 +15,10 @@ — hunk header: -15,7 means original file at line 15 for 7 lines; +15,10 means new file at line 15 for 10 lines
  • - lines — deleted
  • + lines — added
  • lines — context (unchanged)

Useful diff flags

# Word-level diff (highlights specific words changed):
git diff --word-diff

# Ignore whitespace:
git diff -w                      # ignore all whitespace
git diff --ignore-blank-lines    # ignore blank line additions/removals

# Show just file names that changed:
git diff --name-only
git diff --name-status  # also shows A/M/D status

# Stat summary (shows +/- counts per file):
git diff --stat

# No color output (for piping):
git diff --no-color

# Compact summary:
git diff --compact-summary

Diffing specific content

# Changes to a directory:
git diff src/components/

# Changes matching a pattern:
git diff '*.ts'
git diff -- '*.test.js'

# Ignore changes to generated files:
git diff ':!package-lock.json' ':!*.min.js'

# Only show certain file extensions:
git diff -- '*.py' '*.js'

Comparing branches in detail

# All changes on feature branch relative to main:
git diff main...feature-branch

# Two-dot vs three-dot diff:
git diff main..feature-branch   # direct comparison of tips
git diff main...feature-branch  # changes on feature since branching from main

# See what will be merged:
git diff main...HEAD

# Show branch history summary:
git log --oneline main..feature-branch

Diff in scripts and CI

# Exit code 0 if no diff, 1 if diff found:
git diff --quiet && echo "No changes" || echo "Changes found"

# Check if specific files changed:
if git diff --name-only HEAD~1 HEAD | grep -q "package.json"; then
  echo "package.json changed, running npm install"
  npm install
fi

# Get list of changed files as an array:
changed_files=$(git diff --name-only HEAD~1 HEAD)

Viewing diffs in different tools

# Open in vimdiff:
git difftool -t vimdiff

# Use VSCode as diff tool:
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
git difftool

# Open GitHub PR diff in browser (with gh CLI):
gh pr diff 123

Generating patch files

# Create a patch file from unstaged changes:
git diff > my-changes.patch

# Create a patch from a commit:
git format-patch HEAD~1

# Apply a patch:
git apply my-changes.patch
git am < formatted.patch  # for format-patch patches

Common workflows

Review before committing

# 1. Stage your changes:
git add -p  # interactive staging — reviews each hunk

# 2. See exactly what will be committed:
git diff --staged

# 3. Commit:
git commit -m "fix: handle invalid JSON in parseConfig"

Find when a line was introduced

# git log -S searches for when a string appeared/disappeared:
git log -S "parseConfig" --oneline

# git log -G searches commit diffs for a regex:
git log -G "throw new Error" --oneline

# git blame shows who last touched each line:
git blame src/utils.js
git blame -L 15,25 src/utils.js  # only lines 15–25

Related posts

Related tool

Text Diff

Compare two text blocks line-by-line or word-by-word. Unified and split view. Shows added, removed, and changed segments with full color coding.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.