Thursday, August 4, 2011

Git and Subversion, or There and Back Again.

Around the end of our first month at Boss Alien, we had been using Git for all of our code revision control (including coder art assets and the Unity project contents). While setting things up was fairly painless and managing local commits was fairly painless, we had various issues and problems while trying to use Git to do merges when people pushed and pulled from the Origin (mainline on our primary Git server).
We had attempted to use a few different OSX GUIs for Git, and the only one that we tried that worked to our initial satisfaction was Tower. Unfortunately there was a bug in Tower that made merges give incorrect results. (This bug has since been resolved with a test case that I sent them). Because we couldn't find another decent GUI, we ended up doing things using a commandline, and that really is not the best way to have people using Git. Merge issues continued to crop up whenever we tried to reconcile parallel changes. After an awful lot of messing around in Git configuration files we managed to get a bearable workflow using P4Merge, but it was still a pain in the arse compared to using a GUI.

This caused us to switch to Subversion, as well as the hope that, because Subversion uses a single server model rather than a distributed version model, we would be able to use the File Locking mechanism in Subversion to help us mitigate the issues with "merging" binary assets. Really, you can't merge binary. This leaves you with three choices - pick yours, pick theirs, don't mess with the file in the first place. With a DRCS there is no way to enforce "don't mess with this". With something like Perforce or Accurev, there are mechanisms to allow you to say "I have this file locked, you can't mess with it".
The main binary assets like models and textures will occasionally cause this problem, but it's rare - you're much more likely to have a single contributor modifying these files and conflicts simply don't arise in that change flow. However, some of the key files in a Unity project (scenes, prefabs and a few others) are currently binary files. Apparently this will change in a future revision of Unity, but working with them right now means that either you can't (easily) collaborate within a scene, or you need to very carefully structure your scenes and prefabs so that other people can modify subsets of assets without breaking the subset you're currently working on.
For projects the size of the ones we're working on, this is annoying. It will undoubtedly cause lost work, but it's probably not going to bring the project down. Any larger, though, and you'll most likely end up in a situation where you just can't work because you're contending with other people changing the same binary files.
Once Unity moves to a text (mergeable) representation of these files, the problem will be drastically reduced (although there will still be undoubtedly painful merges, as we saw using Renderware on the Potter games).
So, to get back to the point - we wanted to have Subversion put a lock on a scene file, for example - to say, effectively "Tim's changing this, so you can't". Not elegant, but in theory it should work. Unfortunately, in practice it doesn't work - in Unity, you can quite happily write over the file without any warning, meaning you end up in the same place at the end of the day - you have a local change and a remote change, and one of you just lost their work.
Subversion brings with it another (in this case, pretty much insurmountable) problem when you're working with Unity. the structure of the Subversion repository is held in hidden directories (.svn directories) inside each directory in your repository folder. This is annoying when trying to copy folders around in your project workspace, as you need to be very careful that you don't move or copy the hidden .svn directories. If you do, then the subversion client will give you all sorts of horrible problems, like thinking a directory exists when it doesn't, not allowing you to add a directory it thinks it already has, that sort of thing. This caused us a good few hours of pain, definitely more pain than resolving Git merge issues.
That's something we can work around when using Finder or windows Explorer. It's simply not something we can work around when moving items in the Unity project browser. When you move directories around inside Unity, it also moves the .SVN directories with it, and you've just broken your local working copy. Unpicking these issues is, pretty much always, more effort than simply redoing the work. Today, I've had three cases where I couldn't redo the work, because I'd lost local files after doing updates in Subversion and I had no way of persuading Subversion to put files back or retrieve them from history without totally deleting my local working copy and starting again. This is simply not a viable workflow.

So, primarily for this reason, we're moving back to Git today - it's not perfect and I'm sure we'll see issues with it, but at least you can work inside Unity without breaking the source control with seemingly innocuous activities.

1 comment:

  1. I wonder if it's possible for someone to write a simple "lock" unity editor plugin? The locking (which is a team communication helper) is kind of separate from the SCM being used. Just need a server with a shared namespace to 'lock' files in?

    Undoubtedly unity needs to provide more hooks for this stuff though.