8

I use vimdiff as my difftool with git.

Let's say that I've changed twelve files. The problem is that sometimes I run git diff and around the fourth or fifth file I see something that I want to edit/change. Sometimes I need to make a few more changes outside of this. The problem is that I can't just :qa and go back to hacking, because there are six or seven more diffs that pop up in vimdiff. It gets really tedious to :qa all of these files without looking every time that I want to abort a git diff.

Is there any way to set up vimdiff as git's difftool such that all of the diffs open in the same vim instance, e.g. in separate tabs?

3
  • I never had an idea why tabs were introduced and how they could be used in a sensible way. This is the first use-case where tabs actually would make sense.
    – Marco
    Jul 31, 2012 at 18:35
  • I agree. The only real use case I've seen for tabs is when I want a similar group of buffers open in a different configuration of windows; i.e. one tab has a header and a source file in a split, while another tab has the source and a makefile in a vertical split. Or something. And sometimes it's nice to have a "stack of windows", i.e. you're editing four files in some splits and you want to make a quick edit to your vimrc, :tabe ~/.vimrc followed by :bd is a nice combo.
    – So8res
    Jul 31, 2012 at 21:30
  • Did it for me stackoverflow.com/q/2428051/168034
    – phunehehe
    Sep 20, 2012 at 11:08

5 Answers 5

4

You could use the vim plugins published here. Then you just need to set the difftool:

[multidiff]
  tool = vd -f

As an alternative application I would suggest meld, which will show you modified files - you can then select just the files who's diffs you want to see.

See the screenshot here for an example.

Further to Marcos useful comment, as a third (manual alternative) if you want to use vimdiff I would recommend following meld's strategy in a script (possibly python):

  • use git diff-files --name-status and git diff-index --name-status --cached HEAD to identify files that need to be examined.
  • Get cached versions of these files and place in /tmp/
  • Open all of these files - the changed files and their cached versions - at once in vimdiff - though most likely not possible in the sense that you require- see below.

However, as vimdiff itself doesn't seem to handle multiple diff tabs natively I recommend one of my other suggestions above.

3
  • This would be better suited as a comment, since it does not answer the question at all.
    – Marco
    Jul 31, 2012 at 18:43
  • Thanks for your suggestion @Marco - I hope my edits have improved my answer.
    – jmetz
    Jul 31, 2012 at 19:14
  • 1
    They did definitely. This is not what I would call elegant, but it seems to work. I'll give it two weeks of testing if this is a practical solution. Thanks for sharing, this vim “invasion” while diffing always bothered me.
    – Marco
    Jul 31, 2012 at 20:01
4

A quite simple workaround is to add this option in your ~/.gitconfig file

[difftool]
    tool = vimdiff $LOCAL $REMOTE
    prompt = true

That way before each file comparison, you are prompted and have the possibility to skip a file by answering 'no' or abort the file comparison with Ctrl+C

Example:

$ git difftool
Viewing: 'file1.js'
Launch 'vimdiff' [Y/n]: y
2 files to edit

Viewing: 'file2.js'
Launch 'vimdiff' [Y/n]: n
2

This is what I use. It requires that you use vim-fugitive

[alias] dt = "!f() { vim -p $(git diff --name-only) +\"tabdo Gdiff $@\" +tabfirst; }; f"

git dt will then open each diff pair in a separate tab. Then :tabclose to close a single pair, or :qa to exit.

source

3
  • Will this work with multiple refs, instead of comparing against the working files?
    – Spidey
    Nov 24, 2018 at 13:18
  • No since this works by openning all the working files and running Gdiff on each tab.
    – Lewis R
    Nov 28, 2018 at 9:43
  • Really liked this though. Very smart solution. Congrats.
    – Spidey
    Dec 8, 2018 at 11:26
2

There's a much simpler solution that's not posted yet.

Add the following to your ~/.gitconfig -

[difftool]
    trustExitCode = true

Now you can run :cq at any time during the process to stop diffing more files.

1

I came up with the following script to achieve the behaviour git difftoll + vimdiff provides, but using tabs:

#!/bin/bash

commit1=$1
commit2=$2

files=`git diff ${commit1} ${commit2} --name-only`

cmd="set nosplitright | set nobackup | set noswapfile"

EXE="| silent exe"

for f in $files; do
    if [ -z "$commit2" ]; then
        cmd+="$EXE ':tabnew $f'"
    else
        cmd+="$EXE ':tabnew | f <${commit2}>/${f} | setlocal buftype=nofile | 0read ! git show ${commit2}:$f'"
    fi
    cmd+="$EXE ':0 | filetype detect'"
    cmd+="$EXE ':vnew | f <${commit1}>/${f} | setlocal buftype=nofile | 0read ! git show ${commit1}:$f'"
    cmd+="$EXE ':0 | filetype detect'"
    cmd+="$EXE ':windo diffth'"
done
cmd+="$EXE 'bd 1 | tabfirst'"

vim -c "$cmd"

Call it like this: vimgd <commit1> <commit2>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .