For all those little papers scattered across your desk
Following mention of a new diff algorithm in Edition 114 of Git Rev News, I dissect problems with the post “This developer tool is 40 years old: can it be improved?”. I offer clarifications for the misinformation in the article, and I mention free, builtin ways to get diff improvements.
Bill Harding writes:
Since IDEs are refreshed every few years, maybe you’ve guessed that your oldest tool in active use is “git.” It was first released nearly 20 years ago, back in 2005. Or maybe you prefer to code with the classic old-school text editors, like Sublime Text (2008) or vim (1991).
Yet Vim and Git are under active development, getting “refreshed” perhaps more regularly than other major (unnamed?) IDEs due to their distributed, collaborative open-source practices. The core model may have changed little, but Vim 9.1 in 2025 is not your 1991 Vim, nor is Git 2.48.1 in 2025 your Git from 2005.
It is true that the Myers diff algorithm (no air quotes necessary, thank you) originates in 1986, but the colors on GitHub are not its byproduct; rather, I believe an edit script is the typical output. This is also demonstrated on page 3, the same figure which Harding cites.
As Git Rev News mentions, Git supports other algorithms including
minimal
,
patience
, and
histogram
. Some research
exists on their properties.
This remains an active area of improvement, I believe.
Harding writes:
The Myers diff algorithm classifies all code change lines as binary: either “add” or “delete.”
The Commit Cruncher algorithm tested recognizes three times more types of changed operations: Added, Deleted, Updated, Moved, Find/Replaced, and Copy/Pasted
Yet Git can detect moved lines with --color-moved
(enable by default with
diff.colorMoved =
default
).
Or consider
One example where Myers requires more work by a reviewer is when a code change involves white space, like the change shown earlier in this post:
Yet Git has several modes for making whitespace easier to review, like
--ignore-space-change
, --ingore-space-at-eol
, and --ignore-all-space
. This
also typically shortcuts the complex changes from extracting methods, depending
on how far the new function is relocated. In Harding’s example, I think
--ignore-space-change
would produce a similar diff (but we’ll never know
because sources for the diffs are not given).
Then there’s “incremental updates” (whatever that means in this context):
The same diff through a GitClear lens condenses the incremental update to a single line, where the new (or removed) characters are shown inline:
Git has a --word-diff
mode that does the same thing and can be configured
per-invocation depending on where you want to consider interesting boundaries.
In my experience, it trivializes Harding’s example diff, too.
Harding later tries to explain Commit Cruncher and writes:
The Myers diff algorithm works by inspecting two inputs: the repo state before commit A and the state after commit C.
This is imprecise, just like the earlier formulation
[Myers] offered what became the canonical solution for representing the difference between the state of a git repo “before” and “after” a developer’s git commit.
Git can generate diffs between blobs, trees, commits, and commit ranges. Harding is either being intentionally imprecise (why?) or doesn’t know much about Git’s diffs, the very thing his company’s product is trying to improve.
I’ve written before that GitHub’s UI has problems1, but this highlights one more: GitHub has very poor support for examining diffs.
--word-diff
). This includes
--color-moved
for showing moved lines. In practice, developers creating
commits may have a good idea about how to communicate the diff (I and others
have experimented with communicating these options in
commits).Improving these situations or moving away from GitHub as your primary diff viewer would be free alternatives to a Harding’s tool.
The StackOverflow blog shamelessly shills for a company to get you to buy a product you probably don’t need. What’s new?
PR reviews lack threading, and it has bad defaults for some kinds of merges. ↩