Jérôme Belleman
Home  •  Tools  •  Posts  •  Talks  •  Travels  •  Graphics  •  About Me

Comparing Files, Directories over Space and Time

3 Sep 2017

How to compare files in batch or interactively? Here are a few nifty tips and tricks to make the most of tools such as diff, vimdiff and git difftool.

1 diff

I don't suppose the diff command needs any introduction. It compares files line by line and – well, I just accidentally introduced it again anyway. I hardly ever use it without the -u option which presents a unified view, much more useful than the disjoint view you get by default.

Interactively speaking, I like piping the output of diff -u – or even diff -ru to compare whole file hierarchies – into an editor whereby I can freely further search for specific kinds of differences: line addition, removals, missing files and binary files. Interestingly, while a standard Vim installation comes with the syntax for displaying diff outputs in colour, it will occasionally fail to detect the correct file type. I found it best to help it a little there:

diff -ru foo/ bar/ | vim +'set ft=diff' -

An inexplicable nuisance about diff comes from its -x option which excludes some files from comparison based on the file name. That is, not based on the file path. If you routinely compare large file hierarchies and know that there are some files you're not interested in comparing, it might become a problem if these files have common names which may appear in different places in your hierarchy.

2 Vimdiff

Vimdiff goes the extra mile to compare files interactively. It opens the old and new file in two separate windows side by side. What makes it interesting is that you can edit both files to help you understand what the differences entail.

Sometimes, Vimdiff – and also diff – will struggle to correctly identify blocks of changes and will incorrectly report changes which are not. I recently found that it helps to add a few common lines before blocks which I know haven't changed, e.g. use a commented out block in the source code, to help the program perform the correct mappings and show the actual differences.

Likewise, when it comes to source code, some reported differences are due to changes in the indentation. You can easily shift left and right that indentation in the old, new or both files to check that this is the only reason why a change is reported.

The :window command is particularly convenient to perform changes on the contents of both windows at the same time. I often use :windo sort, again to highlight where changes come from. Differences in e.g. Vim dictionary word lists don't matter in practice and I don't want to know about them.

Vimdiff comes with convenient motions for jumping between differences, namely ] c (next) and [ c (previous).

3 git difftool

If git diff is a commonly-used command in the git toolkit to compare files over time and commits, git difftool is perhaps less known. It's an extremely convenient utility, though, which uses the diff program of your choice where you would normally use git diff. Set it up in your ~/.gitconfig with:


[diff]
    tool = vimdiff

For security reason, git will ask you whether or not you really want to launch the third-party diff program for each file, and this will quickly get in the way if you get to compare commits involving many files. You can disable the check with:

[difftool]
    prompt = false

Again, if you work with many different files, it can be difficult to stop git spawning your diff program for each file when you've had enough. You can instruct git difftool to trust its exit code and stop if the git program returns a non-zero exit status:

[difftool]
    trustExitCode = true

If you use Vimdiff, use the :cquit (:cq for short) command instead of :q to quit with an error code and this will stop the entire git difftool operation: no more files will be opened for comparison.

4 References