Reputation: 8788
The output of git diff
is optimized for code which tends to be one statement per line whereas text can (if authors like me are too lazy to use line breaks) cause diff output which is very hard to read and more of a "Where's Wally?" search than reading diff output
whereas highlighting as done on GitLab's or GitHub's web frontend shows the difference immediately
I'm aware that I'm comparing HTML and plain text (apples and oranges), however it should be possible to improve the git diff
output by using different colors or adding marker characters around a change (JUnit uses []
around insertions which isn't great to read, but an example for what I mean) and it would be the first time that there's something I expect to be somewhere available in git that actually was not.
Upvotes: 50
Views: 14402
Reputation: 31
To expand on @Hi-Angel answer, we could use a wrapper script to find the diff-highlight
contrib script and place it in $PATH
. Then use the wrapper script in your .gitconfig
.
The script will try to find contrib/diff-highlight
. We will name the script wrapper diff-highlight
and place it in $PATH
:
#!/bin/sh
# diff-highlight locates the diff-highlight script in the git source tree and
# runs it.
# https://github.com/git/git/blob/master/contrib/diff-highlight
hilite=
for prefix in /usr/share /usr/local/share; do
# First try git-core directory
if [ -f "$prefix/git-core/contrib/diff-highlight" ]; then
hilite="/usr/share/git-core/contrib/diff-highlight"
elif [ -d "$prefix/git-core/contrib/diff-highlight" ]; then
hilite="$prefix/git-core/contrib/diff-highlight/diff-highlight"
# Then try git contrib directory
elif [ -f "$prefix/git/contrib/diff-highlight" ]; then
hilite="$prefix/git/contrib/diff-highlight"
elif [ -d "$prefix/git/contrib/diff-highlight" ]; then
hilite="$prefix/git/contrib/diff-highlight/diff-highlight"
# Try git directory
elif [ -f "$prefix/git/diff-highlight" ]; then
hilite="$prefix/git/diff-highlight"
elif [ -d "$prefix/git/diff-highlight" ]; then
hilite="$prefix/git/diff-highlight/diff-highlight"
# Then try doc directory
elif [ -f "$prefix/doc/git/contrib/diff-highlight" ]; then
hilite="$prefix/doc/git/contrib/diff-highlight"
elif [ -d "$prefix/doc/git/contrib/diff-highlight" ]; then
hilite="$prefix/doc/git/contrib/diff-highlight/diff-highlight"
fi
if [ -n "$hilite" ]; then
break
fi
done
if [ -x "$hilite" ]; then
exec "$hilite" "$@"
elif command -v perl >/dev/null 2>&1; then
perl "$hilite" "$@"
else
cat
fi
You can also find this script in my dotfiles.
Then change the git pager to use the wrapper script:
$ git config --global core.pager 'diff-highlight | less'
$ git config --global interactive.diffFilter 'diff-highlight'
Upvotes: 3
Reputation: 2165
Sometimes just changing the coloring engine of git helps so much. Try diff-so-fancy.
Upvotes: 1
Reputation: 5659
The word-diff
suggested in the other answer isn't exactly what gitlab/github do. To get same effect, you can use diff-highlight
script that is distributed with git.
First find path to diff-highlight
script. It varies between systems, and is not usually in $PATH. You can find it with your package manager, for example:
rpm -ql git | grep diff-highlight
dpkg -L git | grep diff-highlight
pacman -Ql git | grep diff-highlight
Now, execute the following two commands, which will add to your ~/.gitconfig
the necessary settings:
$ git config --global core.pager 'perl /usr/share/git/diff-highlight/diff-highlight | less'
$ git config --global interactive.difffilter 'perl /usr/share/git/diff-highlight/diff-highlight'
I'm using perl
here instead of calling the script directly because some distros, it seems, do not set executable bit on the script. IMO this is a package bug which should be reported. Anyway, this answer should work regardless.
Now log
, diff
, show
commands should show difference word-by-word. Screenshot:
Upvotes: 50
Reputation: 5659
Also worth mentioning is diffr
. It's written in Rust and uses Myers longest common subsequence algorithm. Compared to git's diff-highlight
it gives better results, see:
git's diff-highlight
:
diffr
:
Once installed, making use of it is similar to that of diff-highlight
, so for example execute these two commands to add diffr
to your global config:
$ git config --global core.pager 'diffr | less'
$ git config --global interactive.difffilter diffr
Upvotes: 38
Reputation: 9386
Delta is a modern alternative to the postprocessing tools in other answers.
It is highly configurable (with emulation modes for diff-highlight
and diff-so-fancy
) and includes many features not found in other tools: side-by-side views, syntax highlighting, and coloring of merge conflicts and git blame
output.
The Delta documentation also has an overview of related projects that mentions a few more ad-hoc tools that can produce similar output.
Upvotes: 8
Reputation: 12013
You could use the --word-diff[=<mode>]
option to make it easier to see which words have changed within a line. This is described in the man page as
Show a word diff, using the
<mode>
to delimit changed words. By default, words are delimited by whitespace; see--word-diff-regex
below. The<mode>
defaults to plain, and must be one of:
color
– Highlight changed words using only colors. Implies--color
.
plain
– Show words as[-removed-]
and{+added+}.
Makes no attempts to escape the delimiters if they appear in the input, so the output may be ambiguous.
porcelain
– Use a special line-based format intended for script consumption. Added/removed/unchanged runs are printed in the usual unified diff format, starting with a+/-/` `
character at the beginning of the line and extending to the end of the line. Newlines in the input are represented by a tilde~
on a line of its own.
none
– Disable word diff again.Note that despite the name of the first mode, color is used to highlight the changed parts in all modes if enabled.
Upvotes: 19