TIL: git diff anywhere

Many are familiar with the output of git diff when reviewing changes before a commit or when browsing through a repo’s history. What fewer people know is that this same tool can compare regular files outside of any git repo. And it’s very convenient compared to the default diff command.

Consider the following alias:

alias diff='git --no-pager diff --color=auto --no-ext-diff --no-index'

Here’s the rundown on the command:

  • git --no-pager diff: execute git diff but don’t pipe output into a pager
  • --color=auto: colorize output if possible
  • --no-ext-diff: compute differences using git itself, not by an external diff driver
  • --no-index: never try to treat the files as part of a git repo, regardless of whether an index exists

git diff

Whether to use -p (pipe through pager) or --no-pager (never pipe through pager) is really up to you, I prefer the unpaged output.

Also note that git diff will work recursively if the parameters are directories instead of files. Which is a sensible default, no more diff -r, yay.

But wait, there’s more!

git diff ignore-all-space

Specifying -w (or its longer spelling --ignore-all-space) ignores all differences in whitespaces. Notice how the line “Hello” is not displayed as changed in the screenshot above. This is particularly useful when enclosing code into a new block (e.g. when wrapping code in an if statement) or when switching from tabs to spaces. Some IDEs do this automatically and make it hard to review changes before committing. -w to the rescue!

git diff word-diff

The option --word-diff aggregates changes in juxtaposed words and displays the difference in a compact manner. It even works across multiple lines or when the whole paragraph has been reflowed.

That’s an invaluable help when diff’ing markdown documents, where changing parts of a sentence and reflowing at the 80 character mark would otherwise show every single line in a paragraph as changed.

Talking about beautiful diffs, git 2.9 comes with a new heuristic:

It tries to keep hunk boundaries at blank lines, shifting the hunk “up” whenever the bottom of the hunk matches the bottom of the preceding context, until we hit a blank line.

If that sounds awfully complicated, refer to the example below. It’s straight from beautiful diffs on the Github blog.

git-diff-compaction-heuristic

Enable the new heuristic by passing the delightfully obvious option --compaction-heuristic. Or, more practically, set diff.compactionHeuristic in your git config:

> git config --global diff.compactionHeuristic true

Resources:


← back to main page

Comments