How can I visualize per-character differences in a unified diff file?
Say I get a patch created with git format-patch
. The file is basically a unified diff with some metadata. If I open the file in Vim, I can see which lines have been modified, but I cannot see which characters in the changed lines differ. Does anyone know a way (in Vim, or some other free software that runs on Ubuntu) to visualize per-character differences?
A counter example where per-character diff is visualized is when executing vimdiff a b
.
update Fri Nov 12 22:36:23 UTC 2010
diffpatch is helpful for the scenario where you're working with a single file.
update Thu Jun 16 17:56:10 UTC 2016
Check out diff-highlight in git 2.9. This script does exactly what I was originally seeking.
Solution 1:
In git, you can merge without committing. Merge your patch first, then do:
git diff --word-diff-regex=.
Note the dot after the equals sign.
Solution 2:
Here are some versions with less noisy output than git diff --word-diff-regex=<re>
and that require less typing than, but are equivalent to, git diff --color-words --word-diff-regex=<re>
.
Simple (does highlight space changes):
git diff --color-words
Simple (highlights individual character changes; does not highlight space changes):
git diff --color-words=.
More complex (does highlight space changes):
git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
In general:
git diff --color-words=<re>
where <re>
is a regexp defining "words" for the purpose of identifying changes.
These are less noisy in that they color the changed "words", whereas using just --word-diff-regex=<re>
surrounds matched "words" with colored -/+
markers.
Solution 3:
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"
The above regex (from Thomas Rast) does a decent job of separating diff fragments at the punctuation/character level (while not being as noisy as --word-diff-regex=.
).
I posted a screenshot of the resulting output here.
Update:
This article has some great suggestions. Specifically, the contrib/
tree of the git repo has a diff-highlight
perl script that shows fine-grained highlights.
Quick start to use it:
$ curl https://git.kernel.org/cgit/git/git.git/plain/contrib/diff-highlight/diff-highlight > diff-highlight
$ chmod u+x diff-highlight
$ git diff --color=always HEAD~10 | diff-highlight | less -R
Solution 4:
Given your references to Vim in the question, I'm not sure if this is the answer you want :) but Emacs can do this. Open the file containing the diff, make sure that you're in diff-mode
(if the file is named foo.diff
or foo.patch
this happens automatically; otherwise type M-x diff-mode
RET), go to the hunk you are interested in and hit C-c C-b for refine-hunk
. Or step through the file one hunk at a time with M-n; that will do the refining automatically.
Solution 5:
If you have nothing against installing NodeJS, there's a package called "diff-so-fancy" (https://github.com/so-fancy/diff-so-fancy), which is very easy to install and works perfectly:
npm install -g diff-so-fancy
git diff --color | diff-so-fancy | less -R
Edit: Just found out it's actually a wrapper for the official diff-highlight... At least it's easier to install for perlophobes like me and the GitHub page is nicely documented :)