Excluding directories from version control

The relief and joy I feel after placing a project under version control is usually tempered by the frustration that almost immediately, almost invariably follows the first time I run svn status and see system-generated files in the tmp or cache directories turning up.

[I had this happen recently with a site I was building using CakePHP. Cake has a directory named “tmp” that contains all the system-generated and system-accessed files, each within its own subdirectory: cache, logs, sessions, tests. This directory is located inside the “app” directory, which is where everything specific to the site goes, a.k.a everything one would want to place under version control. I will use this example for the rest of this post.]

I don’t need to preserve the directory contents (a.k.a. “the easy one”)

If the directory doesn’t contain any subdirectories or files you need to preserve use Subversion to remove the directory’s contents:

svn delete tmp/*

If you get an error about local modifications just add --force to the end of the command and run it again.

Next, tell Subversion to ignore the contents of that directory:

svn propset svn:ignore '*' tmp/

And finally, commit the changes to the repos:

svn commit --message="emptied system directory and set prop to 'ignore'"

That’s it!

I need to preserve the contents of the directory (a.k.a. “The less-easy one”)

Maybe the directory contains a subdirectory structure or perhaps user-uploaded content (eg. images) — either way you don’t want the directory contents under version control but you can’t just delete it all. So, before we do anything else, we export the individual directory (and all of its contents) from the repos.

In my example, I exported the entire “tmp” directory into a new directory, creatively named “tmp2”.

Now that everything’s backed up we can clean out, ignore, and commit like we did above. Then, we move the contents of our backup directory (“tmp2” in my example) back where it belongs:

mv tmp2/* tmp/

Notice we’re not using Subversion to make this move because none of it is under version control. Lastly, we remove our backup directory:

rmdir tmp2

I always use rmdir here, instead of rm as we could, specifically because if there’s anything left in the directory I want to know (specifically because there shouldn’t be).

Finally we run svn status — silence equals success.

[You will probably still need to change ownership of the excluded directory back to the system and adjust the permissions before things start running normally again.]