Highlight changed lines and changed bytes in each changed line
Asked Answered
G

14

120

Open Source project Trac has an excellent diff highlighter — it highlights changed lines and changed bytes in each changed line! See here or here for examples.

Is there way to use the same color highlight (i.e. changed lines and changed bytes too) in bash terminal, git, or vim for diff output (patch-file)?

Gregson answered 16/3, 2011 at 13:29 Comment(6)
What is it that you want to highlight? Do you want a diff tool that higlights the byte changes? (that would be very helpful). You say vim, to my recollection vim does a lot of color manipulation already when you are using programming language templates (and other). How would you change that? There are quite a few techniques available to change color on a terminal window that is defined VT100 (and there are dozens of other definitions that will also support color escape sequences). More specifics please. Or read en.wikipedia.org/wiki/VT100 and related links. Maybe that can help.Commiserate
I know you are only interested in open source tools, and only in terminal. But just as a reference point you may want to look at slickedit's diffzilla. of the few diff tools I used it has always seem to best represent character differences (though it definitly had issues when the diffs where complex (combination of formatting and code changes, which is always a bad idea)Dymphia
Looks like a dup of #3232259Overmaster
Note: GitHub now offers such a diff tool in its Web GUI: https://mcmap.net/q/66960/-does-github-have-a-view-that-shows-diffs-between-file-versionsFructose
I have posted 'yet another' pure git, diff-highlight based solution with tutorials to easily 1) find the relevant diff-highlight file, 2) make it executable 3) set necessary params in .gitconfig. Please have a look. Instructions are for Ubuntu 18.04 but should work broadly on linux systems.Nieman
See also unix.stackexchange.com/questions/19317/… and unix.stackexchange.com/questions/44266/… and #49279077 and https://mcmap.net/q/66958/-git-pretty-format-colorsRoger
B
79

The diff-highlight Perl contrib script produces output so similar to that of the Trac screenshots that it is likely that Trac is using it:

screenshot of diff-highlight in use

Install with:

wget https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight && chmod +x diff-highlight

Move the file diff-highlight to the ~/bin/ directory (or wherever your $PATH is), and then add the following to your ~/.gitconfig:

[pager]
    diff = diff-highlight | less
    log = diff-highlight | less
    show = diff-highlight | less

Single copy paste install suggested by @cirosantilli:

cd ~/bin
curl -O https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight
chmod +x diff-highlight
git config --global pager.log 'diff-highlight | less'
git config --global pager.show 'diff-highlight | less'
git config --global pager.diff 'diff-highlight | less'
git config --global interactive.diffFilter diff-highlight
Benghazi answered 1/3, 2013 at 2:6 Comment(10)
This. This is excellent. Thank you. It seems to be a little bit conservative in some places though, missing some lines that obviously have a majority of text in common. Do you have a bug tracker for it?Ophicleide
Ah, this is part of core git now: github.com/git/git/tree/master/contrib/diff-highlightOphicleide
@s1n4: please add your explanation here also. Its the best answer.Parotid
Github's raw urls appear to have changed, so the curl command above needs to be updated to point to the current url or use the -L tag to follow the redirect header.Appointed
It's now been turned into a module, and I think the easiest version to download from is the one immediately before that change at raw.githubusercontent.com/git/git/…Fluviomarine
Not only is this part of core git, it's distributed with git and probably already on your system. I added details on how to enable it in my answer below. ↓Dessert
Here's the direct link to @CoryKlein's answer.Transpacific
This misses the diffs you see via git add -p. Please also add: git config --global interactive.diffFilter diff-highlightSattler
Most distros have diff-so-fancy in their repo, which uses diff-highlight.Sextans
One may need to run make in /usr/share/doc/git/contrib/diff-highlight to get /usr/share/doc/git/contrib/diff-highlight/diff-highlight (see this commit)Month
B
60

While using git diff or git log and possibly others, use option --word-diff=color (there are also other modes for word diffs BTW)

Botsford answered 20/3, 2011 at 20:1 Comment(6)
--word-diff=color is really better (especially with git config color.diff.old "red reverse" and git config color.diff.new "green reverse"), but it is not what I want :(Gregson
So only thing you are missing is marking in colour/somehow both changed lines and bytes on same time?Botsford
I want to highlight changed lines and changed bytes in each changed line, like in Trac. Not just changed bytes, it is not the same.Gregson
You can also use this with git add --patch: #10874382Ophicleide
The advantage of diff-highlight is that it works well for both word diffs and line diffs.Parotid
If you enable diff-highlight it automatically highlights byte differences in all git patch diffs. Details in my answer below. ↓Dessert
U
32

diff-so-fancy is a diff-highlighter designed for human eyeballs.

It removes the leading +/- which are annoying for cut/paste and makes clear sections between files.

Coloured git (left) vs diff-so-fancy (right - note the character-level highlights):

diff-so-fancy output

If you want thediff-so-fancy (right side) output but not constrained to files in a git repository, add the following function to your .bashrc to use it on any files:

dsf() { git diff --no-index --color "$@" | diff-so-fancy; }

Eg:

dsf original changed-file

Character level highlighting and standard diff format

If you don't like the non-standard formatting of diff-so-fancy, but still want character-level git highlighting, use diff-highlight which will take git's output and produce the really pretty standard diff-format output:

diff-highlight screenshot

To use it by default from git, add to your .gitconfig:

[color "diff-highlight"]
  oldNormal = red bold
  oldHighlight = red bold 52
  newNormal = green bold
  newHighlight = green bold 22

[pager]
  diff = diff-highlight | less -FRXsu --tabs=4

The [pager] section tells git to pipe its already colourised output to diff-highlight which colourises at the character level, and then pages the output in less (if required), rather than just using the default less.

Umberto answered 15/9, 2016 at 6:16 Comment(3)
This is very interesting, could you explain a bit about these gitconfig options?Feign
Updated, also adding function dsf().Umberto
Most distros have this package in their repo: github.com/so-fancy/diff-so-fancy#install.Sextans
D
17

A utility for byte-based diffs has been distributed with official Git since v1.7.81. You just have to locate where it is installed on your machine and enable it.

Find where Git is installed

  • MacOS with Git installed via Homebrew: It's /usr/local/opt/git (later versions: /opt/homebrew/Cellar/git/VERSION)
  • Windows with Git for Windows: Run cd / && pwd -W to find the install directory.
  • Linux: Nerd. If you don't already know where Git is installed, then ll $(which git) or locate git should help.

Link diff-highlight to your bin directory so that your PATH can find it

GIT_HOME='/usr/local/opt/git/'  # Use the value from the first step.
ln -s "${GIT_HOME}/share/git-core/contrib/diff-highlight/diff-highlight" \
      '/usr/local/bin/diff-highlight'

Enable it in your Git config

git config --global interactive.diffFilter diff-highlight # Use on interactive prompts
git config --global pager.diff "diff-highlight | less"    # Use on git diff
git config --global pager.log  "diff-highlight | less"    # Use on git log
git config --global pager.show "diff-highlight | less"    # Use on git show

1 Here is the v1.7.8 version, but lots of changes have been made since then.

Dessert answered 17/1, 2019 at 16:59 Comment(4)
It would be good to specify in which version it started to be distributed with git. Also l'm guessing that distros will put it in PATH by default, so the symlink step won't be needed? And which git requires it to be in the PATH in the first place so it won't work if it's not :-)Parotid
It would be good! Feel free to add that information. And although Git does bundle diff-highlight, it does not actually install it, so the symlink step is indeed necessary (at least on macOS). If you find that it isn't necessary for your platform, again feel free to update the answer. Meanwhile, which git usually does work, because Git does install the git binary somewhere on the path.Dessert
Note that in debian unstable I needed to "compile" this file, because I just had a .perl. The compilation is trivial: just run sudo make in the diff-highlight directory.Barcroft
This seems to imply Git for Windows will install the contrib content, but it does not. diff-highlight is not installed by the Git for Windows installer nor is there any option to do so.Angiology
V
16

The behaviour you want is now available in git itself (as was pointed out in a comment by naught101). To enable it you need to set your pager to

perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

where /usr/share/doc/git/contrib/diff-highlight/diff-highlight is the location of the highlighter script on Ubuntu 13.10 (I have no idea why it's in a doc folder). If it isn't there on your system try using locate diff-highlight to find it. Note that the highlighting script is not executable (at least on my machine), hence the requirement for perl.

To always use the highlighter for the various diff-like commands just add the following to your ~/.gitconfig file:

[pager]
    log = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    show = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    diff = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

I added this as a new answer naught101's comment is buried and because the set up is not quite as trivial as it should be and at least on the version of Ubuntu that I have the instructions in the README don't work.

Vindicate answered 15/9, 2014 at 15:46 Comment(3)
I've just noticed that this doesn't enable the highlighting for the diffs within git add -p (interactive mode). I don't know how that can be fixed though, simply adding add to the list causes it to hang.Vindicate
This should work now in git 2.9.0: git config interactive.diffFilter diff-highlightEelpout
^ This! Unfortunately, diff-highlight wasn't on my path so I had to locate it first. Details in my answer below.Dessert
U
15

I use --color-words option and it works fine for me :

$ git diff --color-words | less -RS
Unbosom answered 11/5, 2011 at 10:49 Comment(3)
No, this only shows the difference in words. What the OP (and I) want is a normal line-by-line diff, with the word differences highlighted (so, say different lines are coloured text, and the word-differences within those lines are normal coloured text, with coloured highlighting or something). See the example links now in the question.Ophicleide
pastebin.com/1JrhYHRt Actually I use vimdiff as difftool and vimdiff with molokai colorscheme to get a nice highlighting as you describe in your question. 1- git config --global diff.tool vimdiff 2- in vim ":colo molokai" * Molokai @ github.com/tomasr/molokai * Possible auto colorscheme with ~/.vimrc: if &diff set background=dark colorscheme molokai endifUnbosom
This plus aha is amazing, I use it to diff file e.g. git diff --color-words file_1.rs file_2.rs | aha --black > diff.htmlLeuko
E
7

as @dshepherd says:

The behaviour you want is now available in git itself

But diff-highlight is located in DOC and is not available from shell.
To install diff-highlight into your ~/bin directory follow next steps (This will save your typing):

$ locate diff-highlight
$ cd /usr/share/doc/git/contrib/diff-highlight  #or path you locate
$ sudo make
$ mv diff-highlight ~/bin

Then configure your .gitconfig as official doc says:

[pager]
    log  = diff-highlight | less
    show = diff-highlight | less
    diff = diff-highlight | less

UPD
Also you can try next on latest git without any installation:

git diff --color-words=.

More complex:

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Entity answered 26/1, 2018 at 14:50 Comment(0)
M
5

In an answer to a similar, but slightly different question, I suggest using Delta, which is a modern diff postprocessing tool that specifically supports the special desire for highlighting both words and lines at the same time.

Delta 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 highlight both words and lines.

Delta diff formatting example

Maybe answered 2/6, 2022 at 20:5 Comment(0)
G
2

Emacs has the ediff-patch-buffer function which should fulfill your needs.

Open the un-patched file in emacs type ESC-x, ediff-patch-buffer.

Follow the prompts and you should see a highlighted comparison of the patched and original versions of your file.

As per your comment the following will will give you a bash solution requiring only dwdiff:

#!/bin/bash
paste -d'\n' <(dwdiff -2 -L -c <(cat $2) <(patch $2 -i $1 -o -)) <(dwdiff -1 -L -c <(cat $2) <(patch $2 -i $1 -o -))| uniq
Getter answered 20/3, 2011 at 23:29 Comment(6)
sorry, I do not want to use emacs, only bash, git or vimGregson
That's understandable. The only other thing i can think of is to use colordiff with the stdout from patch: colordiff -u <(patch original_file -i patch_file -o -) <(cat original_file) but this is only going to highlight changed lines not bites...Getter
I gave your problem a bit more thought and have appended a second solution which requires only dwdiff.Getter
please read carefully my question, I do not want to compare filesGregson
sorry for the confusion, so your just after a way to highlight the changed bytes on the changed lines of a diff file? if so try dwdiff -c --diff-input diff_fileGetter
I tried it before writing previous comment. unfortunately it does not highlight changed lines, only changed bytes :(Gregson
P
1

Diffy

GitLab is using Diffy https://github.com/samg/diffy (Ruby) to achieve output similar to GitHub and diff-highlight:

enter image description here

Diffy makes the diff itself using the same algorithm ad Git, and supports different types of outputs, including the HTML output that GitLab uses:

gem install diffy
echo '
  require "diffy"    
  puts Diffy::Diff.new("a b c\n", "a B c\n").to_s(:html)
' | ruby

Output:

<div class="diff">
  <ul>
    <li class="del"><del>a <strong>b</strong> c</del></li>
    <li class="ins"><ins>a <strong>B</strong> c</ins></li>
  </ul>
</div>

Note how strong was added to the changed bytes.

Parotid answered 19/7, 2014 at 7:50 Comment(0)
N
1

Note: this is a duplicate of what is found here: How to improve git's diff highlighting? . Posting my answer here too though, as it may be helpful to some people who find directly this thread :)

As said in some previous answers, this is possible with only git stuff. I post this as the instructions may be a bit easier to follow depending on your system, but this is similar to several other answers.

One solution that is purely relying on git and its contribs. This requires no additional files than what comes with git. All explanations are for Ubuntu (tested on 18.04LTS), should work similarly on other linux systems:

  • Locate the diff-highlight contrib git snippet:
find -L /usr -name diff-highlight -type f

on my system the only valid answer is:

/usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Make the corresponding perl script executable. In my case I needed to do:
sudo chmod +x /usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Update your ~/.gitconfig to get the result you want, by adding (note these are TABS, not 4 spaces):
[color "diff-highlight"]
    oldNormal = red
    oldHighlight = red 52
    newNormal = green
    newHighlight = green 22
  • Enjoy the result (note: this is only for the diff coloring + highlight, I have other things at play here too for the prompt of course :) ).

diff-highligh

Nieman answered 1/4, 2020 at 12:29 Comment(0)
W
0

My vim plugin vim-gitgutter does this when you preview a diff. You can see a simple example in the screenshot in the readme.

The code that calculates the intra-line differences is here.

Walliw answered 2/5, 2023 at 14:30 Comment(0)
F
0

Some of the tools may already mentioned but I will try to summarise and add some extra tips here:

Bash/Terminal

You can use the colordiff or diff-so-fancy

Install

Pick depending on your system

sudo apt-get install colordiff
# or
sudo yum install colordiff

Usage

colordiff firstFile secondFile
# or for word coloring
colordiff -y firstFile secondFile

Git

In case your diff not already highlight the output this can configured with:

git config --global color.ui auto
git config --global color.diff.wordDiff true

Vim

Vim has a build-in highlighting that can be enabled via editing the ~/.vimrc and adding the following lines:

syntax enable
filetype plugin indent on

For highlighting the exact bytes it is required an extra plugin there are multiple plugins available for this purpose ie diffchar.vim or vim-gitgutter

Forget answered 18/3 at 12:56 Comment(0)
A
-1

Yes, Vim does this including the highlighting of text changed within a line.
See :h diff and :h 08.7 for more details on how to diff files.

Vim uses a fairly simple algorithm for it's highlighting. It searches the line for the first changed character, and then the last changed character, and simply highlights all characters between them.
This means you can't have multiple highlights per line - many design decisions in Vim prioritise efficiency.

Agonic answered 16/3, 2011 at 13:58 Comment(4)
unfortunately, it does not highlight changed bytes on diff output (set filetype=diff)Gregson
I think I understand your question now - You want to syntax highlight the textual output of the diff command so that it highlights any changes made inside of a line. Editing this text in Vim highlights line differences, but not the changes made within a line.Agonic
Could you use Vim's :patchfile command to load the original file and then compare it to the patched version?Agonic
unfortunately no, I want to use recursive diff output for multiple filesGregson

© 2022 - 2024 — McMap. All rights reserved.