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.