Wednesday, May 6, 2015

Ignoring files recursively with Subversion - svn:ignore and svn:global-ignores in Subversion 1.8

This is fun. The good old svn:ignore property and its inheritable (but not recursive!) counterpart, the svn:global-ignores property (Subversion 1.8 only), not to be mistaken for the client-specific global-ignores runtime configuration variable. Throw in some information about recursive properties vs. inheritable properties and it's a nice little mess to deal with. But I think I get it know. Let me explain it on a .NET developer's typical example: ignoring all "bin" and "obj" folders in whole solution's folder hierarchy.
  1. First, the svn:ignore property does not work recursively, so setting it just for your solution folder is not helpful at all - you need to set it for each project's folder individually. This might be hard when you have 191 projects in a solution (you don't? I do! And I don't like it to be clear). And when somebody creates a new project, they need to remember to add the svn:ignore property on the new project's folder, and they will forget; again and again.
  2. Subversion has this feature to set properties recursively, like in svn propset svn:ignore bin --recursive .. This is a brute-force approach - it will actually set the svn:ignore on each and every single folder below current folder. Similar to the solution above, this is not future-proof either - you need to apply the svn:ignore property yourself when creating new projects/folders.
  3. In Subversion 1.8, "inheritable" properties were introduced, and all existing versioned properties were made inheritable. However, since the svn:ignore property has historically been non-recursive (see point 1), another property was introduced, which works recursively - enter svn:global-ignores. Setting this property on the root folder of the solution will work for every subfolder.
There are two catches in this whole story.
  1. First, don't be fooled by the svn:ignore property being "inheritable". You might set the svn:ignore property on the solution's root folder and look at a project's folder properties and see the svn:ignore property being "inherited" from the solution folder - but this means nothing. The svn:ignore property still only works in the folder where it was set, not in subfolders.
  2. Second, if you use TortoiseSVN, be sure to separate the items in the svn:global-ignores property with newlines, even though according to Subversion 1.8 specification, any whitespace should work. It is apparently a bug in TortoiseSVN, described here: http://stackoverflow.com/questions/21708509/tortoisesvn-and-subversions-global-ignore.
More info:
  • "Properties" chapter in the official SVN Book (with the "Inherited Properties" subchapter)
  • "Ignoring Unversioned Items" chapter in that same book
  • "Ignoring Files And Directories" chapter in TortoiseSVN documentation
  •