When I have a diff, how can I colorize it so that it looks good?
I want it for the command line, so please no GUI solutions.
When I have a diff, how can I colorize it so that it looks good?
I want it for the command line, so please no GUI solutions.
Man pages for diff
suggest no solution for colorization from within itself. Please consider using colordiff
. It's a wrapper around diff
that produces the same output as diff, except that it augments the output using colored syntax highlighting to increase readability:
diff old new | colordiff
or just:
colordiff old new
Installation:
sudo apt-get install colordiff
brew install colordiff
or port install colordiff
less -R
, which displays the escape sequences for colors correctly. –
Guyot -y
option to enable) ☹ The vimdiff
suggestion below probably a better way –
Nicely colordiff
works well for svn diff | colordiff
(i.e. in situations where you only have the diff, not the two files being diffed). –
Eberly -y
) support. –
Pullulate -y
does not have any colorization. –
Infundibulum Use Vim:
diff /path/to/a /path/to/b | vim -R -
Or better still, VimDiff (or vim -d
, which is shorter to type) will show differences between two, three or four files side-by-side.
vim -d /path/to/[ab]
vimdiff file1 file2 file3 file4
ctrl-c
and ctrl-x
have other uses in Vim. ctrl-q
is captured by many terminals. See Writing and quitting to find the way that best suits your needs. –
Achitophel vimdiff
won't handle directory diff
s. Alternatively, you can save diff to a file, and open it with vim
. That way you will have vim
colorize it using built-in syntax highlighting facilities. –
Carine vim -d =(ls -l ~/src/m) =(ls -l ~/src/n)
–
Achitophel zsh
? I don't recognize =(...)
construct. Second, I had diff -ur a b
in mind. –
Carine =(...)
is replaced with the name of a file containing its output. –
Achitophel diff -ur ~/src/{m,n} | vim -
is a nice alternative. Thanks. –
Achitophel <(...)
instead. –
Vaccination <(...)
form is present in zsh as well. –
Dow vimd
+ tab
(autocomplete). –
Chihli -R
is vim's readonly mode so you can also use the equivalent view
command which is just vim's readonly command, i.e., diff file1 file 2 | view -
. Adding it here for those that may prefer one over the other. Cool solution, OP! –
Shred Actually there seems to be yet another option (which I only noticed recently, when running into the problem described above):
git diff --no-index <file1> <file2>
# output to console instead of opening a pager
git --no-pager diff --no-index <file1> <file2>
If you have Git around (which you already might be using anyway), then you will be able to use it for comparison, even if the files themselves are not under version control. If not enabled for you by default, then enabling color support here seems to be considerably easier than some of the previously mentioned workarounds.
git diff <(xxd file1) <(xxd filed)
doesn't work. –
Tera git help diff
. So if your git diff is coming up empty, try cd
out of where you are. –
Cigar git config color.diff auto
–
Clunk git diff --no-index
to compare two files. –
Myelitis diff
, I much prefer the way git diff
handles files that are only in one side of a recursive diff, but I hadn't realized I could use it outside of a Git repository. Thank you! –
Tamanaha git diff
I would take a look at this answer. –
Rommel git diff --word-diff --patience
–
Madelinemadella git diff
is the ---
and +++
at the top clarifying the direction of the changes. –
Classics git diff --color <file1> <file2>
–
Laudable ~/.bashrc
+= alias cdiff='git diff --no-index'
–
Vorfeld diff --color
and colordiff
are not available at a site! –
Arawak diff --color
option (added to GNU diffutils 3.4 in 2016-08-08)
This is the default diff
implementation on most distributions, which will soon be getting it.
Ubuntu 18.04 (Bionic Beaver) has diffutils
3.6 and therefore has it.
On 3.5 it looks like this:
Tested with:
diff --color -u \
<(seq 6 | sed 's/$/ a/') \
<(seq 8 | grep -Ev '^(2|3)$' | sed 's/$/ a/')
Apparently added in commit c0fa19fe92da71404f809aafb5f51cfd99b1bee2 (Mar 2015).
Word-level diff
Like diff-highlight
. It is not possible it seems, but there is a feature request: https://lists.gnu.org/archive/html/diffutils-devel/2017-01/msg00001.html
Related questions:
ydiff
does it though. See below.
ydiff
side-by-side word level diff
https://github.com/ymattw/ydiff
Is this nirvana?
python3 -m pip install --user ydiff
diff -u a b | ydiff -s
Outcome:
If the lines are too narrow (default 80 columns), fit to the screen with:
diff -u a b | ydiff -w 0 -s
Contents of the test files:
a
1
2
3
4
5 the original line the original line the original line the original line
6
7
8
9
10
11
12
13
14
15 the original line the original line the original line the original line
16
17
18
19
20
b
1
2
3
4
5 the original line the original line the original line the original line
6
7
8
9
10
11
12
13
14
15 the original line the original line the original line the original line
16
17
18
19
20
ydiff
Git integration
ydiff
integrates with Git without any configuration required.
From inside a Git repository, instead of git diff
, you can do just:
ydiff -s
and instead of git log
:
ydiff -ls
See also: How can I get a side-by-side diff when I do "git diff"?
Tested on Ubuntu 16.04 (Xenial Xerus), Git 2.18.0, and ydiff 1.1.
There is no word-highlighting, yet
- any updates? This is what I came to this question for (I want grep --color
-like diff output). –
Academy git diff --color
works too. Useful when working over ssh. –
Purpurin diff --color=always | less -R
–
Impendent And for those occasions when a yum install colordiff
or an apt-get install colordiff
is not an option due to some insane constraint beyond your immediate control, or you're just feeling crazy, you can reinvent the wheel with a line of sed:
sed 's/^-/\x1b[41m-/;s/^+/\x1b[42m+/;s/^@/\x1b[34m@/;s/$/\x1b[0m/'
Throw that in a shell script and pipe unified diff output through it.
It makes hunk markers blue and highlights new/old filenames and added/removed lines in green and red background, respectively.1 And it will make trailing space2 changes more readily apparent than colordiff can.
1 Incidentally, the reason for highlighting the filenames the same as the modified lines is that to correctly differentiate between the filenames and the modified lines requires properly parsing the diff format, which is not something to tackle with a regex. Highlighting them the same works "well enough" visually and makes the problem trivial. That said, there are some interesting subtleties.
2 But not trailing tabs. Apparently tabs don't get their background set, at least in my xterm. It does make tab vs. space changes stand out a bit though.
sed "s/^-/`echo -e \"\x1b\"`[41m-/;s/^+/`echo -e \"\x1b\"`[42m+/;s/^@/`echo -e \"\x1b\"`[34m@/;s/$/`echo -e \"\x1b\"`[0m/"
(though I expect there is a better way). –
Judkins sed -e '1,2s/^/\x1b[97m/;3,$s/^-/\x1b[31m-/;3,$s/^+/\x1b[32m+/;3,$s/^@/\x1b[36m@/;s/$/\x1b[0m/'
for an output closer to diff --color
. –
Telencephalon diff -u old new | sed "s/^-/$(tput setaf 1)&/; s/^+/$(tput setaf 2)&/; s/^@/$(tput setaf 6)&/; s/$/$(tput sgr0)/"
. See https://mcmap.net/q/64141/-how-to-colorize-diff-on-the-command-line for more details. –
Bradley Coloured, word-level diff
ouput
Here's what you can do with the the below script and diff-highlight:
#!/bin/sh -eu
# Use diff-highlight to show word-level differences
diff -U3 --minimal "$@" |
sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;34m@/;s/$/\x1b[0m/' |
diff-highlight
(Credit to @retracile's answer for the sed
highlighting)
vim
, use a plugin, eg diffchar. –
Oracular diff-highlight
does not do a word-level output. It just detects a common prefix and a common suffix on a changed line. For instance, if several words are changed, it will highlight everything from the first changed word to the last changed word. Moreover, this is effective only when only one line is changed between unchanged lines. In GNU Emacs, diff-mode does much better. –
Cullie You can change the Subversion configuration to use colordiff:
~/.subversion/config.diff
### Set diff-cmd to the absolute path of your 'diff' program.
### This will override the compile-time default, which is to use
### Subversion's internal diff implementation.
-# diff-cmd = diff_program (diff, gdiff, etc.)
+diff-cmd = colordiff
I use grc
(Generic Colouriser), which allows you to colour the output of a number of commands including diff
.
It is a Python script which can be wrapped around any command. So instead of invoking diff file1 file2
, you would invoke grc diff file1 file2
to see colourised output. I have aliased diff
to grc diff
to make it easier.
fork()
calls, although likely to work with WSL. –
Provencal Since wdiff
accepts arguments specifying the string at the beginning and end of both insertions and deletions, you can use ANSI color sequences as those strings:
wdiff -n -w $'\033[30;41m' -x $'\033[0m' -y $'\033[30;42m' -z $'\033[0m' file1 file2
For example, this is the output of comparing two CSV files:
Example from 2.2 Actual examples of wdiff usage.
colordiff
now (1.0.16) understands wdiff
, so you can also just pipe: wdiff -n f1 f2 | colordiff
. wdiff
should be merged into diffutils... –
Valois Here is another solution that invokes sed
to insert the appropriate ANSI escape sequences for colors to show the +
, -
, and @
lines in red, green, and cyan, respectively.
diff -u old new | sed "s/^-/$(tput setaf 1)&/; s/^+/$(tput setaf 2)&/; s/^@/$(tput setaf 6)&/; s/$/$(tput sgr0)/"
Unlike the other solutions to this question, this solution does not spell out the ANSI escape sequences explicitly. Instead, it invokes the tput setaf
and tput sgr0
commands to generate the ANSI escape sequences to set an appropriate color and reset terminal attributes, respectively.
To see the available colors for each argument to tput setaf
, use this command:
for i in {0..255}; do tput setaf $i; printf %4d $i; done; tput sgr0; echo
Here is how the output looks:
Here is the evidence that the tput setaf
and tput sgr0
commands generate the appropriate ANSI escape sequences:
$ tput setaf 1 | xxd -g1
00000000: 1b 5b 33 31 6d .[31m
$ tput setaf 2 | xxd -g1
00000000: 1b 5b 33 32 6d .[32m
$ tput setaf 6 | xxd -g1
00000000: 1b 5b 33 36 6d .[36m
$ tput sgr0 | xxd -g1
00000000: 1b 28 42 1b 5b 6d .(B.[m
tput: unkown terminfo capability in 'srg0'
means your os is old and tput does not recognize srg0 , i was able to use tput setaf 7
in last sed command to get color back to white –
Perchloride No one has mentioned delta so far. It supports syntax colored diff view with syntax highlighting.
.diff
files –
Roshan delta -s file1 file2
# -s is "side by side" –
Rale brew install git-delta
–
Lailaibach I would suggest you to give diff-so-fancy a try. I use it during my work and it sure seems great as of now. It comes packed with many options and it's really easy to configure your diffs the way you want.
You can install it by:
sudo npm install -g diff-so-fancy
or on Mac:
brew install diff-so-fancy
Afterwards, you can highlight your diffs like this:
diff -u file1 file2 | diff-so-fancy
ccdiff
seems to work well as a diff program, but unfortunately, it cannot color an existing diff (such as a patch). –
Cullie With the bat command:
diff file1 file2 | bat -l diff
On recent versions of Git on Ubuntu, you can enable diff-highlighting with:
sudo ln -s /usr/share/doc/git/contrib/diff-highlight/diff-highlight /usr/local/bin
sudo chmod a+x /usr/share/doc/git/contrib/diff-highlight/diff-highlight
And then adding this to your .gitconfig
file:
[pager]
log = diff-highlight | less
show = diff-highlight | less
diff = diff-highlight | less
It's possible the script is located somewhere else in other distributions. You can use locate diff-highlight
to find out where.
My favorite choice is vdiff <file1> <file2>
function (I forgot from where I got it).
It will open two windows in Vim side-by-side, to see clearly see the difference between the two files.
vdiff () {
if [ "${#}" -ne 2 ] ; then
echo "vdiff requires two arguments"
echo " comparing dirs: vdiff dir_a dir_b"
echo " comparing files: vdiff file_a file_b"
return 1
fi
local left="${1}"
local right="${2}"
if [ -d "${left}" ] && [ -d "${right}" ]; then
vim +"DirDiff ${left} ${right}"
else
vim -d "${left}" "${right}"
fi
}
Put this script in your (.alias) or (.zshrc), and then call it using vdiff <file1> <file2>.
The results are:
© 2022 - 2024 — McMap. All rights reserved.