What happens when you type git diff? As with all interesting questions, the answer is “it depends…”
Here’s one thing you want git to do:

Vimdiff!
Step 1: add this to your .gitconfig
[diff]
external = git_diff_wrapper
[pager]
diff =
Step 2: create a file named git_diff_wrapper, put it somewhere in your $PATH
#!/bin/sh
vimdiff "$2" "$5"
I still have access to the default git diff behavior with the --no-ext-diff flag. Here’s a function I put in my bash configuration files:
function git_diff() {
git diff --no-ext-diff -w "$@" | vim -R -
}
- --no-ext-diff : to prevent using vimdiff
- -w : to ignore whitespace
- -R : to start vim in read-only mode
- - : to make vim act as a pager
When it comes to vimdiff, you can get started with this tutorial.
Wonderful, thanks! My team currently uses a “legacy” CVS (and we use “cvsvimdiff” – http://vim.sourceforge.net/scripts/script.php?script_id=1209 ) – but this will find from you will be a significant part of my plan to move to git.
Thanks!
Matt
[...] Git Diff with Vimdiff What happens when you type git diff? As with all interesting questions, the answer is “it [...] [...]
Thanks for -R in vim :). I’ve been using almost the same function in my bash here, but without -R you have to always remember to type :q! instead of :q. Now it’s gone, thank you one more time :).
[...] 24, 2009 by Jonathan Palardy I’ve talked casually about using Vim as a pager before. However, I’m still surprised to see how many people use Vim regularly and don’t know [...]
Thanks for this entry, I found it useful.
Not being ready to go full speed into using vimdiff (i’m just new to it), I put the following in ‘gitvimdiff’. The result is that I can use vimdiff to look at git-diff by running ‘gitvimdiff ‘, but a normal invocation of ‘git-diff’ behaves as I’m used to.h
#!/bin/sh
if [ -n "${GIT_EXTERNAL_DIFF}" ]; then
[ "${GIT_EXTERNAL_DIFF}" = "${0}" ] ||
{ echo “GIT_EXTERNAL_DIFF set to unexpected value” 1>&2; exit 1; }
exec vimdiff “$2″ “$5″
else
GIT_EXTERNAL_DIFF=”${0}” exec git –no-pager diff “$@”
fi
Thanks!
I will add that this script works if .gitconfig is NOT modified like above.
The above script is a small masterpiece, it does not mess with standard config so all tools expecting usual “git diff” still work fine.
Have been trying to do something like this for ages. Thanks a lot!
rockin thanks, this works great
I can’t seem to get this to work for the life of me! I just get a warning from vim that the output is not to a terminal. The following is my conifg:
[user]
name = Arthur Axel ‘fREW’ Schmidt
email = ellided@gmail.com
[color]
status = auto
branch = auto
ui = auto
[alias]
ci = commit
co = checkout
[diff]
external = git_diff_wrapper
[pager]
external =
Any ideas what I could be doing wrong?
I just compared with my config.
for the pager section, here’s what I have:
[pager]
diff =
it seems to be “diff” not “external”
let me know how that goes.
Thanks for the help. Works like a charm!
I have a question though: when one has more than 2 files in diff, vimdiff is launched twice. And this gets annoying if you have, say 100 files in diff. Any idea what to do then?
Yeah, this is a common problem. And it’s not Vim specific either.
I usually check how many files are affected with “git status”. Also, vimdiff git diff is _not_ my default choice: I use the “git_diff” alias mentioned at the end of the post.
If you still make that mistake … you can try to kill the git diff process.
Hi! Thanks for the reply. Unfortunately, I am too much in habit of using git diff. Script from Scott works fine then…
I really like this idea. I would have never come up with this on my own so I appreciate the work you put into it. I do, however, have some problems with the implementation. I would strongly suggest you not hork the standard behavior of git diff. I think you should create your git_diff_wrapper script. Don’t worry about putting a git_diff function in bash. Add the following to your ~/.gitconfig:
[alias]
vimdiff = “!GIT_PAGER=” GIT_EXTERNAL_DIFF=git_diff_wrapper git diff”
That’s it. Now you have:
git diff # normal behavior
git vimdiff # enhanced behavior
I also tried it but failed with the same error as Pete. The problem is in the extra quote, so I removed the quote in front of “!” , now I don’t get errors but don’t get any valueable results either. git vimdiff simply does not yeild anything.
Andrey – it didn’t work for me either, until I did one of the two following things:
1: Set the environment variable GIT_PAGER=”"
2: Add an extra quote into the vimdiff alias in .gitconfig above:
vimdiff = “!GIT_PAGER=” GIT_EXTERNAL_DIFF=”git_diff_wrapper git diff”
I tried your method but
Expansion of alias ‘vimdiff’ failed; ‘“!GIT_PAGER=”’ is not a git command
is there anything wrong?
Much easier to use is vimdiff for git-difftool.
git config –global alias.vimdiff “difftool -y -t vimdiff”
Now just type
git vimdiff
Just note that this works per file instead of diff on the whole working directory.
re: git config –global alias.vimdiff “difftool -y -t vimdiff”
That is very handy! Is there anyway I can tell it to open in readonly mode?
Add a -R at the end, as such:
git config –global alias.vimdiff “difftool -y -t vimdiff -R”
[...] Git Diff with Vimdiff (tags: totag) [...]
Very nice article.Thanks to the writer for sharing these stuffs that I believe will be helpful for me next time.
Jonathan,
Thank you. This article was very useful. There is one thing I’m wondering about. Because my main need for vimdiff in viewing git diffs is actually for reviewing code written by others, I’m wondering if there’s a way to do something similar with “git log -p”.
In general when I’m doing a “git diff” I’m just looking at code I’ve written over the last hour or so, but when it’s someone else’s code, that’s when viewing a regular diff patch is a little confusing.
Thank you.
John
Haha. Duh.
$ git diff HEAD~1
or more generally
$ git diff ..
Cheers.
I think your article is very useful for me. Thanks
I think this was only a problem with older versions of Git. Now I can do
git config –global diff.tool vimdiff
once, and then use `git difftool` whenever I want to carefully view the diff.
You’re right, that works out nicely.
[...] 下記のURLの設定方法をそのまま利用させてもらった。 http://technotales.wordpress.com/2009/05/17/git-diff-with-vimdiff/ [...]
Dont forget to change the permissions on your git_diff_wrapper!
chmod +x git_diff_wrapper
[...] Git Diff with Vimdiff « Jonathan’s Techno-tales [...]