For the longest time, I have been suffering with problems of changes whitespace rendering SVN diffs useless.

Sometimes it’s the spaces vs tabs issue. Sometimes it’s file line endings (silly Windows-only editors and their CRLF). And sometimes it’s just people adjusting whitespace arbitrarily on lines (like adding spaces around parens or leaving spaces at the end of lines, etc…).

Regardless of the individual manifestation, it’s a silly problem, but one that causes more than its share of tears among developers everywhere.

Perhaps the easiest and smartest solution is to browbeat your co-developers into compliance. Force people to use editors that preserve line endings, force them to strip trailing whitespace and conform to a universal standard of indentation, etc… but it’s not always the nicest or most reliable solution. People will make mistakes, even if it’s only once a month… going over that diff might cost you an hour to figure out what had actually changed.

There are a few other solutions out there. They’re not new, and they’re not for everyone… but they can be phenomenally helpful at times. I’ll go over the two simplest ones.

dos2unix

Ever gotten a diff that reads like this?

ammon@binky:~/test$ svn diff one
Index: one
===================================================================
--- one (revision 2)
+++ one (working copy)
@@ -1,11 +1,11 @@
-One is the loneliest number that you'll ever do
-Two can be as bad as one
-It's the loneliest number since the number one
-
-No is the saddest experience you'll ever know
-Yes, it's the saddest experience you'll ever know
-`Cause one is the loneliest number that you'll ever do
-One is the loneliest number, worse than two
-
-It's just no good anymore since she went away
-Now I spend my time just making rhymes of yesterday
+One is the loneliest number that you'll ever do
+Two can be as bad as one
+It's the loneliest number since the number one
+
+No is the saddest experience you'll ever know
+Yes, it's the saddest experience you'll ever know
+'cause one is the loneliest number that you'll ever do
+One is the loneliest number, worse than two
+
+It's just no good anymore since she went away
+Now I spend my time just making rhymes of yesterday

This is what happens when something changes the line endings of a file. In this case, the original file was created with LF endings and was then edited slightly by an application that converted them to CRLF.

Now… if this were a 1000 line perl script in stead of an 11 line lyrics snippet… it would be soulcrushingly difficult to find the one actual change in the file.

Most unix distros have at their disposal the dos2unix / unix2dos utilities. On Red Hat, you can yum install dos2unix to get them. On Debian/Ubuntu, you can apt-get install tofrodos. I don’t have any other unices lying around at present to check on, but you can always just get the source at http://www.thefreecountry.com/tofrodos.

ammon@binky:~/test$ dos2unix one
ammon@binky:~/test$ svn diff one
Index: one
===================================================================
--- one (revision 2)
+++ one (working copy)
@@ -4,7 +4,7 @@

 No is the saddest experience you'll ever know
 Yes, it's the saddest experience you'll ever know
-`Cause one is the loneliest number that you'll ever do
+`cause one is the loneliest number that you'll ever do
 One is the loneliest number, worse than two

 It's just no good anymore since she went away

Much easier to figure out what has changed this way.

For extra credit, look into the svn:eol-style property. Set this on files as you commit them – or just use autoprops to do the dirty work for you…

diff-cmd

Of course, some times it’s not line endings. Sometimes the problem is random meaningless whitespace changes. Maybe somebody used an editor that auto-indents with spaces when the file was already indented with tabs, etc…

Subversion allows you to specify an alternate command to use to generate your diffs (in stead of relying on svn’s internal diff generation).

ammon@binky:~/test$ svn diff ----diff-cmd /usr/bin/diff -x -w one
Index: one
===================================================================
7c7
< `Cause one is the loneliest number that you'll ever do
---
> `cause one is the loneliest number that you'll ever do

But what if (for some bizarre reason) you don’t care about the case of letters?

ammon@binky:~/test$ svn diff ----diff-cmd /usr/bin/diff -x -iw one
Index: one
===================================================================

If you always want to use your custom diff utility you can set it in your runtime config to save yourself the hassle of having to type it manually each time.

For those using TortoiseSVN, you can always just specify graphical diff/merge utils to use in stead of Tortoise’s builtin ones. Personally, I’m a big fan of WinMerge, but there are several other good ones out there.

Leave a Reply