[git] How can I get a side-by-side diff when I do "git diff"?

When I type "git diff", I'd like to see a side-by-side diff, like with "diff -y", or like to display the diff in an interactive diff tool like "kdiff3". How can this be done?

This question is related to git git-diff code-visualization

The answer is


I use colordiff.

On Mac OS X, install it with

$ sudo port install colordiff

On Linux is possibly apt get install colordiff or something like that, depending on your distro.

Then:

$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

Or create an alias

$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

Then you can use it

$ git diffy HEAD^ HEAD

I called it "diffy" because diff -y is the side-by-side diff in unix. Colordiff also adds colors, that are nicer. In the option -ydw, the y is for the side-by-side, the w is to ignore whitespaces, and the d is to produce the minimal diff (usually you get a better result as diff)


I personally really like icdiff !

If you're on Mac OS X with HomeBrew, just do brew install icdiff.

To get the file labels correctly, plus other cool features, I have in my ~/.gitconfig:

[pager]
    difftool = true
[diff]
    tool = icdiff
[difftool "icdiff"]
    cmd = icdiff --head=5000 --highlight --line-numbers -L \"$BASE\" -L \"$REMOTE\" \"$LOCAL\" \"$REMOTE\"

And I use it like: git difftool


ydiff

Formerly called cdiff, this tool can display side by side, incremental, and colorful diff.

Instead of doing git diff, do:

ydiff -s -w0

This will launch ydiff in side-by-side display mode for each of the files with differences.

Install with:

python3 -m pip install --user ydiff

-or-

brew install ydiff

For git log, you can use:

ydiff -ls -w0

-w0 auto-detects your terminal width. See the ydiff GitHub repository page for detail and demo.

Tested in Git 2.18.0, ydiff 1.1.


For unix, combining just git and the built-in diff:

git show HEAD:path/to/file | diff -y - path/to/file

Of course, you can replace HEAD with any other git reference, and you probably want to add something like -W 170 to the diff command.

This assumes that you are just comparing your directory contents with a past commit. Comparing between two commits is more complex. If your shell is bash you can use "process substitution":

diff -y -W 170 <(git show REF1:path/to/file) <(git show REF2:path/to/file)

where REF1 and REF2 are git references – tags, branches or hashes.


Several others already mentioned cdiff for git side-by-side diffing but no one gave a full implementation of it.

Setup cdiff:

git clone https://github.com/ymattw/cdiff.git
cd cdiff
ln -s `pwd`/cdiff ~/bin/cdiff
hash -r # refresh your PATH executable in bash (or 'rehash' if you use tcsh)
        # or just create a new terminal

Edit ~/.gitconfig inserting these lines:

[pager]
        diff = false
        show = false

[diff]
        tool = cdiff
        external = "cdiff -s $2 $5 #"

[difftool "cdiff"]
        cmd = cdiff -s \"$LOCAL\" \"$REMOTE\"

[alias]
        showw = show --ext-dif

The pager off is needed for cdiff to work with Diff, it is essentially a pager anyway so this is fine. Difftool will work regardless of these settings.

The show alias is needed because git show only supports external diff tools via argument.

The '#' at the end of the diff external command is important. Git's diff command appends a $@ (all available diff variables) to the diff command, but we only want the two filenames. So we call out those two explicitly with $2 and $5, and then hide the $@ behind a comment which would otherwise confuse sdiff. Resulting in an error that looks like:

fatal: <FILENAME>: no such path in the working tree
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

Git commands that now produce side-by-side diffing:

git diff <SHA1> <SHA2> 
git difftool <SHA1> <SHA2>
git showw <SHA>

Cdiff usage:

'SPACEBAR' - Advances the page of the current file.
'Q'        - Quits current file, thus advancing you to the next file.

You now have side-by-side diff via git diff and difftool. And you have the cdiff python source code for power user customization should you need it.


You can do a side-by-side diff using sdiff as follows:

$ git difftool -y -x sdiff  HEAD^ | less

where HEAD^ is an example that you should replace with whatever you want to diff against.

I found this solution here where there are a couple of other suggestions also. However, this one answer's the OP's question succinctly and clearly.

See the man git-difftool for an explanation of the arguments.


Taking the comments on board, you can create a handy git sdiff command by writing the following executable script:

#!/bin/sh
git difftool -y -x "sdiff -w $(tput cols)" "${@}" | less

Save it as /usr/bin/git-sdiff and chmod +x it. Then you'll be able to do this:

$ git sdiff HEAD^

Extra Tip

As suggested in comments you can use icdiff to do what sdiff does with colored output:

$ more /usr/bin/git-sdiff
#!/bin/sh
git difftool -y -x "icdiff --cols=$(tput cols)" "${@}" | less

If you'd like to see side-by-side diffs in a browser without involving GitHub, you might enjoy git webdiff, a drop-in replacement for git diff:

$ pip install webdiff
$ git webdiff

This offers a number of advantages over traditional GUI difftools like tkdiff in that it can give you syntax highlighting and show image diffs.

Read more about it here.


Try git difftool

Use git difftool instead of git diff. You'll never go back.

UPDATE to add an example usage:

Here is a link to another stackoverflow that talks about git difftool: How do I view 'git diff' output with my preferred diff tool/ viewer?

For newer versions of git, the difftool command supports many external diff tools out-of-the-box. For example vimdiff is auto supported and can be opened from the command line by:

cd /path/to/git/repo
git difftool --tool=vimdiff

Other supported external diff tools are listed via git difftool --tool-help here is an example output:

'git difftool --tool=<tool>' may be set to one of the following:
        araxis
        kompare
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        bc3
        codecompare
        deltawalker
        diffuse
        ecmerge
        emerge
        gvimdiff
        gvimdiff2
        kdiff3
        meld
        opendiff
        tkdiff
        xxdiff

Here's an approach. If you pipe through less, the xterm width is set to 80, which ain't so hot. But if you proceed the command with, e.g. COLS=210, you can utilize your expanded xterm.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}

This may be a somewhat limited solution, but does the job using the system's diff command without external tools:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • filter just the change lines use --suppress-common-lines (if your diff supports the option).
  • no colors in this case, just the usual diff markers
  • can tweak the column width --width=term-width; in Bash can get the width as $COLUMNS or tput cols.

This can be wrapped into a helper git-script too for more convenience, for example, usage like this:

git diffy the/file/path --from rev1 --to rev2

There are a lot of good answers on this thread. My solution for this issue was to write a script.

Name this 'git-scriptname' (and make it executable and put it in your PATH, like any script), and you can invoke it like a normal git command by running

$ git scriptname

The actual functionality is just the last line. Here's the source:

#!/usr/bin/env zsh
#
#   Show a side-by-side diff of a particular file how it currently exists between:
#       * the file system
#       * in HEAD (latest committed changes)

function usage() {
    cat <<-HERE
    USAGE

    $(basename $1) <file>

    Show a side-by-side diff of a particular file between the current versions:

        * on the file system (latest edited changes)
        * in HEAD (latest committed changes)

HERE
}

if [[ $# = 0 ]]; then
    usage $0
    exit
fi

file=$1
diff -y =(git show HEAD:$file) $file | pygmentize -g | less -R

This question showed up when I was searching for a fast way to use git builtin way to locate differences. My solution criteria:

  • Fast startup, needed builtin options
  • Can handle many formats easily, xml, different programming languages
  • Quickly identify small code changes in big textfiles

I found this answer to get color in git.

To get side by side diff instead of line diff I tweaked mb14's excellent answer on this question with the following parameters:

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]"

If you do not like the extra [- or {+ the option --word-diff=color can be used.

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]" --word-diff=color

That helped to get proper comparison with both json and xml text and java code.

In summary the --word-diff-regex options has a helpful visibility together with color settings to get a colorized side by side source code experience compared to the standard line diff, when browsing through big files with small line changes.


Open Intellij IDEA, select a single or multiple commits in the "Version Control" tool window, browse changed files, and double click them to inspect changes side by side for each file.

With the bundled command-line launcher you can bring IDEA up anywhere with a simple idea some/path

version control view diff view


export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

then simply:

git diff

You can also try git diff --word-diff. It's not exactly side-by-side, but somehow better, so you might prefer it to your actual side-by-side need.


Examples related to git

Does the target directory for a git clone have to match the repo name? Git fatal: protocol 'https' is not supported Git is not working after macOS Update (xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools) git clone: Authentication failed for <URL> destination path already exists and is not an empty directory SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443 GitLab remote: HTTP Basic: Access denied and fatal Authentication How can I switch to another branch in git? VS 2017 Git Local Commit DB.lock error on every commit How to remove an unpushed outgoing commit in Visual Studio?

Examples related to git-diff

How to show uncommitted changes in Git and some Git diffs in detail Git list of staged files Create patch or diff file from git repository and apply it to another different git repository There isn't anything to compare. Nothing to compare, branches are entirely different commit histories git: diff between file in local repo and origin Git diff between current branch and master but not including unmerged master commits How to Diff between local uncommitted changes and origin How to see the changes in a Git commit? How do you take a git diff file, and apply it to a local branch that is a copy of the same repository? git diff file against its last change

Examples related to code-visualization

How can I get a side-by-side diff when I do "git diff"?