First, I'll mention that using your sample, and Git version 2.27.0, I'm already getting the kind of match you'd like. There are other samples that are more problematic though. For the rest of this answer, I'll assume you have one of those.
You can try using one of Git's other built in diff algorithms. You can also fuss with the heuristics (as xhienne mentioned), but note that these just slide a window around on the diff after computing it: they won't change the set of diff hunks that come out. If none of these work, then, other than adding a new diff algorithm, or modifications to the existing ones, no: there isn't anything else left to do at this point, at least not in Git itself. The git difftool
method that chepner mentioned is a way to run some other command, instead of Git's built in diff.
As matt noted, each Git commit really just stores a full snapshot of every file. When you use git diff
or any other similar tooling to compare two commits, Git will figure out which files in the two commits are "the same file", yet with different content, and feed them to some diff engine. The diff engine's job is to come up with some set of actions that would modify the left-side file to produce the right-side file (I like to use left and right sides here, rather than old and new, because you can feed the files in backwards to get a "reverse patch").
The existing diff engines know nothing of code. They just match lines. The lines color: red;
match each other, and the lines }
match each other, and the blank lines match each other.
There are two diff engines inside Git today: the default or myers
diff, and the patience
diff. Both have slight modifications: minimal
takes away a shortcut that was inserted into myers
to make it go faster, and histogram
modifies patience
to include lines that patience
discards entirely.
For an overview of patience diff, see What is `git diff --patience` for? The actual algorithm works by stripping out "dummy" lines like blanks lines and close-brace lines that match up too often. The histogram modification doesn't completely strip out these lines, but gives them low weighting in terms of deciding whether to match on them. In theory, histogram should work well on these cases, but there was a bug in Git's implementation for a long time.