Which git diff options help you summarize or filter a very large diff?
answer
- Do not read; triage first
- Counts, then names, then patch
- One flag filters by change kind
- Whitespace noise has its own switch
- Prose needs word-level rendering
basics
~20 sUse --stat or --shortstat for a per-file summary, --name-only or --name-status to list touched paths, --diff-filter to keep only additions, deletions or renames, -w to hide whitespace-only noise, and --word-diff for prose where line diffs read badly.
solid answer
~40 sThe first move on a big diff is to stop reading the patch. `git diff --stat` gives one line per file with the number of changed lines, `--shortstat` collapses that to a single summary line, and `--numstat` gives machine-readable added/deleted counts. `--name-only` lists just the paths; `--name-status` prefixes each path with its status letter. `--diff-filter` then narrows by kind of change: `--diff-filter=A` for added files, `D` for deleted, `M` modified, `R` renamed, `T` type changed; a lowercase letter **excludes** that kind, so `--diff-filter=d` drops deletions. Two options fix readability rather than volume: `-w` (`--ignore-all-space`) suppresses reindentation noise, and `--word-diff` highlights changed words inside a line, which is far more readable for prose, long lines or one-token changes. All of these work identically on `git show` and `git log -p`.
go deeper
Know --stat and --name-only exist and reach for them before scrolling a long patch. Being able to say how large a change is, per file, is the baseline expectation.
Explain the ladder from --shortstat to full patch, what the --diff-filter letters select, and why lowercase letters invert the selection.
Show judgment about noise: rename detection, whitespace flags used interactively rather than configured, and excluding generated files from a review pass without hiding them from the commit.
Argue about what belongs in the repository at all — generated artifacts that make every diff unreadable are a repository-design problem, not a flag problem, and the fix is attributes and policy rather than reviewer heroics.
## The triage ladder A ten-thousand-line diff is not read; it is triaged. Git's options let you descend from a single number to the full patch in stages, and knowing the ladder is what separates someone who can review a large change from someone who scrolls. **Level 1 — one line.** `git diff --shortstat` prints something like `12 files changed, 340 insertions(+), 118 deletions(-)`. Enough to judge magnitude. **Level 2 — one line per file.** `git diff --stat` lists each path with its change count and a small `+`/`-` bar. This is where you spot the surprises: a lockfile with 4,000 changed lines next to three source files with twenty. `--stat=<width>` widens the output when long paths get truncated. **Level 3 — paths only.** `git diff --name-only` prints bare paths, ideal for piping into another command. `git diff --name-status` adds the status letter, so you see at a glance which files were added versus renamed. `--numstat` is the scripting form: added, deleted and path separated by tabs, with `-` for binary files. **Level 4 — the patch, narrowed.** Add a pathspec (`git diff --stat -- src/`) or a filter, then read the real diff for the part that matters. ## Filtering by kind of change `--diff-filter=<letters>` selects entries by status: - `A` added, `D` deleted, `M` modified - `R` renamed, `C` copied, `T` type changed (for example a file becoming a symlink) - `U` unmerged, `B` broken pairing, `X` unknown Lowercase letters invert: `--diff-filter=d` means "everything except deletions". Typical uses are `git diff --diff-filter=A --name-only main...feature` to list every file a branch introduces, or `--diff-filter=R` to check that a large refactor really is renames rather than delete-plus-add. Rename and copy detection is on by default in modern Git (`diff.renames`), and `-M`/`--find-renames` and `-C`/`--find-copies` tune it explicitly; without detection a move shows up as one large deletion plus one large addition, which is the usual reason a diff looks enormous. ## Suppressing noise rather than content Sometimes the diff is not large, it is *noisy*. - `-w` / `--ignore-all-space` ignores whitespace entirely when matching lines; `-b` / `--ignore-space-change` ignores changes in the amount of whitespace but not its presence; `--ignore-space-at-eol` handles trailing-whitespace churn; `--ignore-blank-lines` hides pure blank-line changes. Re-indenting a block after wrapping it in a condition is the classic case where `-w` turns a hundred-line diff into three. - `--word-diff` re-renders hunks so that changed **words** are marked inside otherwise unchanged lines. `--word-diff=color` uses colour alone, `=plain` uses `[-removed-]{+added+}` markers that survive copy-paste, and `--color-words` is the common shorthand. `--word-diff-regex=<regex>` redefines what counts as a word, which helps for languages or markup where the default word boundaries are wrong. Word diff is the right tool for Markdown, long single-line configuration values, and one-identifier renames buried in long lines. ## Binary and generated files Git prints `Binary files a/x and b/x differ` rather than a patch for binaries. When generated files (lockfiles, bundles, snapshots) drown a diff, the durable fix is a `.gitattributes` entry marking them, but for one-off reading a negative pathspec works: `git diff -- . ':(exclude)package-lock.json'`. ## The same options everywhere Because `git diff`, `git show` and `git log -p` share Git's diff machinery, every option above applies unchanged: `git show --stat <commit>`, `git log --stat`, `git log -p -w`. Learning them once pays off across all three commands, and the same option names appear in `git diff --staged` and range comparisons too. ## Making the defaults permanent Options you always want can move into configuration rather than being retyped, using `git config` keys in the `diff.*` namespace. Keep the aggressive ones out of configuration, though: making `-w` permanent means one day you will miss a real whitespace-sensitive change, in Python or in a here-document, precisely because you told Git never to show it.
- How do you list only the files a branch adds, without any patch text?Combine the filters: git diff --diff-filter=A --name-only main...feature. The three-dot form limits the comparison to the branch's contribution, --diff-filter=A keeps only additions, and --name-only suppresses the patch so you get a clean list of paths.
- Why does a pure file move sometimes produce a huge diff, and what fixes it?Because rename detection failed — usually the content also changed enough to fall below the similarity threshold — so Git reports a full deletion plus a full addition. Raise or force detection with -M<n> or -C, and check the result with --diff-filter=R --name-status.
- When is --word-diff clearly better than the default line diff?When lines are long or prose-like: Markdown paragraphs, single-line configuration values, or a renamed identifier inside a long expression. The default marks the whole line changed, hiding a one-token edit; word diff marks just the changed words, using [-old-]{+new+} in plain mode.
- What is the risk of putting -w into your Git configuration permanently?You stop seeing whitespace changes that matter — indentation in Python, content inside here-documents or string literals, and trailing-whitespace policy violations. Use it interactively when reviewing a reformat, but leave the default honest so real whitespace bugs remain visible.
saying these in an interview costs you the question
- Reads a huge patch top to bottom
- Thinks --stat hides files rather than patches
- Cannot narrow a diff to one directory
- Believes -w silently drops modified lines
- Treats a moved file's diff as unavoidable