Git-Config: diff.colormoved
New Line? Removed Line? Moved Line? Configure Git to Show the Difference at a Glance
Diffing is a Git habit worth cultivating: it’s the last chance to inspect what you’re actually about to stage or commit. Diffing helps you dive more deeply into the history of a repository and examine pull requests, too. A routine diff habit is also key to crafting finer-grained commits in cases where staging an entire file with git add
is just too ham-fisted.
Git’s diff output itself is a little ham-fisted. By default, git diff
highlights added lines in green and removed lines in red color-capable terminal environments. In all environments, removed lines are prefixed with a minus sign, -
, and added lines with a plus sign, +
:
There’s a shortcoming to Git’s default diff output, though: any line that has been cut and pasted will appear diffed out like any other pair of added and removed lines. Cuts and pastes are a typical part of refactored and reorganized code. But the two-color diff output burdens you with some unnecessary cognitive load when you’re trying to ensure the integrity of any moved lines: When you need to move something around or simply reformat it, it’s harder to tell whether the line truly is unchanged, apart from formatting or placement. Commas, curly braces, and semicolons are all too easy to leave out of a copy and paste operation.
For example, here’s a Markdown file with three lines moved from the top of the file to the end:
Even in that simple case, closer inspection is needed to determine whether the lines have been moved without modification. Let’s look at a few options to change Git’s diff.colormoved
configuration value to highlight cut and pasted lines differently from lines that are genuinely added, removed, or modified.
Customizing diff.colormoved
The diff.colormoved
configuration property can be set to any one of the permitted values for the--color-moved
option on git diff
. I prefer to set mine to zebra
. By rerunning the same git diff
command on the above JavaScript, it’s now much more obvious what’s been added and removed, and what’s simply been copied elsewhere. The original location of moved lines is shown in a fuchsia color, and the new location in turquoise:
With zebra
coloring, it should be more obvious when a line has been accidentally modified through, say, a sloppy cut and paste: the modified line will take the default red and green coloring.
When you want to more aggressively highlight smaller or insignificant moves, like the empty lines in the example above, you can pass in the plain
option directly togit diff
. (The zebra
value ignores moved blocks of fewer than 20 characters.) The plain
option can go a little overboard with highlighting trivial lines. So I don’t generally set it on diff.colormoved
. But it’s a useful enough option that it’s worth aliasing:
$ git config --global alias.dm "diff --color-moved=plain"
The zebra
setting did not highlight the instance of a moved, empty line above. But when you run the git dm
alias, plain
picks the empty lines right up, presenting them as moved — even if they’ve been reordered:
And hey: since we’re talking about aliases, have you ever prematurely run git add .
to stage your work for commit before diffing? And have you then seen how git diff
reports no output at all? Not a problem. There’s no need to unstage the file with git restore
: just add the --staged
argument onto the end of git diff
. Better yet? Make it an alias:
$ git config --global alias.ds "diff --staged"
Calling up git ds
will now diff your staged files — rather than the files in your working tree — against your most recent commit. It’ll use your preferred configuration value on diff.colormoved
, too.
In the next post, we’ll look more closely at a related diff-output configuration value, diff.colormovedws
, so that simple changes in whitespace (like when moved code is indented or outdented) are not reported as wholly changed, added/removed lines in Git’s diff output. We’ll also look at some general whitespace configuration-values to make a few thorny problems a little easier to handle in Git.
Karl Stolley’s book, Programming WebRTC: Build Real-Time Streaming Applications for the Web, is available in beta from The Pragmatic Bookshelf. You can save 35 percent with promo code git_config_2022 now through April 30, 2022. Promo codes are not valid on prior purchases.