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?
17 Answers
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=vimdiffOther 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 6 Although Git has an internal implementation of diff, you can set up an external tool instead.
There are two different ways to specify an external diff tool:
- setting the
GIT_EXTERNAL_DIFFand theGIT_DIFF_OPTSenvironment variables. - configuring the external diff tool via
git config
ymattw's answer is also pretty neat, using ydiff
See also:
git diff --help
When doing a git diff, Git checks both the settings of above environment variables and its .gitconfig file.
By default, Git passes the following seven arguments to the diff program:
path old-file old-hex old-mode new-file new-hex new-modeYou typically only need the old-file and new-file parameters. Of course most diff tools only take two file names as an argument. This means that you need to write a small wrapper-script, which takes the arguments which Git provides to the script, and hands them on to the external git program of your choice.
Let's say you put your wrapper-script under ~/scripts/my_diff.sh:
#!/bin/bash
# un-comment one diff tool you'd like to use
# side-by-side diff with custom options:
# /usr/bin/sdiff -w200 -l "$2" "$5"
# using kdiff3 as the side-by-side diff:
# /usr/bin/kdiff3 "$2" "$5"
# using Meld
/usr/bin/meld "$2" "$5"
# using VIM
# /usr/bin/vim -d "$2" "$5"you then need to make that script executable:
chmod a+x ~/scripts/my_diff.shyou then need to tell Git how and where to find your custom diff wrapper script. You have three choices how to do that: (I prefer editing the .gitconfig file)
Using
GIT_EXTERNAL_DIFF,GIT_DIFF_OPTSe.g. in your .bashrc or .bash_profile file you can set:
GIT_EXTERNAL_DIFF=$HOME/scripts/my_diff.sh export GIT_EXTERNAL_DIFFUsing
git configuse "git config" to define where your wrapper script can be found:
git config --global diff.external ~/scripts/my_diff.shEditing your
~/.gitconfigfileyou can edit your
~/.gitconfigfile to add these lines:[diff] external = ~/scripts/my_diff.sh
Note:
Similarly to installing your custom diff tool, you can also install a custom merge-tool, which could be a visual merging tool to better help visualizing the merge. (see the progit.org page)
See: and
5You 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.
ydiff
Formerly called cdiff, this tool can display side by side, incremental, and colorful diff.
Instead of doing git diff, do:
ydiff -s -w0This 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 ydiffFor 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.
3You can do a side-by-side diff using sdiff as follows:
$ git difftool -y -x sdiff HEAD^ | lesswhere 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)" "${@}" | lessSave 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 0 For unix, combining just git and the built-in diff:
git show HEAD:path/to/file | diff -y - path/to/fileOf 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.
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'then simply:
git diff 2 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 webdiffThis 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.
I recently implemented a tool that does exactly this:
Here's how to use it:
npm install -g git-split-diffs
git config --global core.pager "git-split-diffs --color | less -RFX"And this is how it looks in your terminal (with the default theme):
As you can see, it also supports syntax highlighting and highlighting changed words within lines
3I use colordiff.
On Mac OS X, install it with
$ sudo port install colordiffOn Linux is possibly apt get install colordiff or something like that, depending on your distro.
Then:
$ git difftool --extcmd="colordiff -ydw" HEAD^ HEADOr create an alias
$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""Then you can use it
$ git diffy HEAD^ HEADI 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
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=colorThat 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.
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 "$@"
} 1 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
Several others already mentioned cdiff for git side-by-side diffing but no one gave a full implementation of it.
Setup cdiff:
git clone
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 terminalEdit ~/.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-difThe 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.
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 yourdiffsupports the option). - no colors in this case, just the usual
diffmarkers - can tweak the column width
--width=term-width; in Bash can get the width as$COLUMNSortput 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 scriptnameThe 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