git diff
See exactly what changed in your files, comparing between commits, branches, or your working directory and staging area.
You've been editing code for the past hour, and you want to see exactly what you
changed before committing. Or you need to compare your feature branch with main
to understand how they differ. git diff shows the exact changes between two
states in your repository—line by line additions and deletions, helping you
review work before saving it or understand differences between versions.
Running git diff with no arguments shows unstaged changes in your working
directory. These are modifications you've made to tracked files but haven't run
git add on yet. The output shows which files changed, with lines you added
marked with + and lines you removed marked with -. Context lines around the
changes help you see where in the file the modifications occurred. This is your
last chance to review changes before staging them for commit.
Once you've staged files with git add, git diff no longer shows those
changes because they're no longer "unstaged." To see staged changes—what will go
into your next commit—use git diff --staged or git diff --cached (they're
the same thing). This shows exactly what you're about to commit, giving you a
final review opportunity before running git commit.
Comparing Branches and Commits
To see differences between branches, use git diff main..feature-branch. This
shows what's different between main and your feature branch, highlighting all
the work you've done. The order matters: git diff feature-branch..main shows
the reverse comparison. This is essential before merging or opening a pull
request, as it shows what will change when the branches combine.
You can also compare specific commits with their SHA hashes:
git diff a3f5b2c b8e9d1f. This shows what changed between those two commits,
which is useful when debugging to see what a specific commit did. To see what a
single commit changed, use git diff a3f5b2c^..a3f5b2c or the simpler
git show a3f5b2c.
Filtering and Focusing Diffs
Adding a filename shows changes only for that file: git diff filename.js. This
narrows the output to just what you care about, avoiding the noise of unrelated
changes. You can specify multiple files or use patterns:
git diff src/*.test.js shows changes to all test files in the src directory.
The --stat flag provides a summary instead of full diffs: git diff --stat
shows which files changed and how many lines were added or removed in each. This
overview helps you understand the scope of changes without reading through all
the code. For even more detail, --numstat provides machine-readable counts
useful for scripts or metrics.
Word-Level and Whitespace Handling
Sometimes changes are within a line rather than entire lines being added or
removed. The --word-diff flag shows word-by-word changes instead of
line-by-line, making it easier to spot small modifications like variable renames
or typo fixes within long lines. Words removed appear in brackets, words added
in braces, making subtle changes more visible.
Whitespace-only changes can clutter diffs, especially after running formatters.
The -w flag ignores whitespace changes, showing only substantive
modifications: git diff -w. This is useful when reviewing code where
indentation changed but logic didn't, or after reformatting files with Prettier
or similar tools.
Pull Request Review
In pull request workflows, diff is central to code review. When reviewing a PR
on GitHub, you're essentially looking at git diff main..feature-branch
formatted in a web interface. Understanding how to generate the same view
locally helps you review more thoroughly, especially for large PRs where you
want to test the code while reviewing.
Before opening a PR, running git diff main..HEAD shows exactly what you're
proposing to merge. If the diff is huge, you might want to split your work into
multiple PRs. If it includes files you didn't mean to change, you can fix those
before pushing. This review step catches mistakes before they become part of the
public PR discussion.
Diff Tools and Integration
Some changes are easier to understand with visual diff tools. Running
git difftool instead of git diff launches a configured visual diff program
like Meld, Beyond Compare, or Kaleidoscope. These tools show changes
side-by-side with highlighting and navigation controls, which can be easier than
reading terminal output for complex changes.
Many editors and IDEs integrate Git diff directly into their interface. VS Code,
IntelliJ, and others show changed lines in the gutter, let you click to see what
changed, and offer inline diff views. These integrated tools use git diff
under the hood but present the information in more accessible ways.
Diffing Between Different Files
You can compare two different files with
git diff --no-index file1.js file2.js, which doesn't require either file to be
in a Git repository. This turns Git into a general-purpose diff tool for any
text files, using its robust diff algorithm even outside version control
contexts.
Understanding diff means understanding that Git tracks changes, not files. Every commit is a set of changes relative to its parent. Diff exposes those changes, letting you see exactly what's different between any two points in your repository's history. Whether you're reviewing your own work before committing, understanding what a teammate changed in their PR, or debugging by comparing versions, diff is the tool that makes those comparisons clear and precise.
