Friday, February 08, 2008

Evil Clones - The SCM nightmare that can stop you in your tracks

It can happen to anyone. First the feeling of disbelief, then the cold sweat; you try pinching yourself, hoping it's some bad dream and you'll wake up and they'll be gone . . .

There, that's my catchy first line of my first novel written, now just the other 150 pages to invent. But unfortunately it really can happen to you - if you are working with ClearCase you may have come across evil twins. But I want to talk about a different nightmare that can occur if you are using SVN or CVS.

Here's the scenario. You and a team member are both working on a file (let's call it MyClass1) checked out of SVN.

Your colleague, as part of her edits, renames MyClass1 to CloneClass1 and commits the working copy.

SVN uses copy/delete commands for a rename:
First MyClass1 is copied (so that the history is maintained) to CloneClass1.
Then MyClass1 is deleted from the repository.
The screenshot of the SVN repository (left) shows the new resulting file with CloneClass1.

CVS is not quite so clever is uses add/delete: It adds CloneClass1 and deletes MyClass1 - so none of the history of MyClass1 is copied to the new CloneClass1.

But back to the SVN example. You have edited the checked out MyClass1 and are oblivious to your team member's edits. Not a problem, you might think as an update from the repository would absorb the changes or at the very least show you a conflict over the rename. Unfortunately not!

Here is where the nightmare that I'm calling Evil Clones appears.

The repository rightly updates your working copy with CloneClass1. But wait, your class MyClass1 is not only still in your App Navigator, but is no longer under version control!

If you think about it, this is correct -
  • SVN has replaced MyClass1 with CloneClass1. It has no recollection of the object MyClass1 so there is no merge of MyClass1 and CloneClass1.
  • You wouldn't want to lose the additional changes you have made to MyClass1 in your working copy - and it is not under version control - well, it's not, because it doesn't exist in the SVN repository
  • You can easily recognize that MyClass1 has been replaced by CloneClass1 so it's a simple job to move your changes to CloneClass1 - or is it. . .
This is expected behavior from Subversion and it seems that they recognize it as a bug . The example above is very simple. But what when you have 00s of different files in your working copy?

I'd be interested in how you work around this shortcoming in SVN. Here are some of my thoughts:
  • Don't rename, if you think you must, think again!
  • If you must, then refactoring or plain renaming of files (this is not specifically a Java problem, could be XML metadata, diagram or any other file type) should always be taken seriously in team development. In our JDeveloper development teams it's usual for the developer thinking about renames to email colleagues, check for dependencies and most definitely comment both the code, the check-in and the build notes to minimize the possible problems.
  • How renaming is handled in your team should be part of your defined development process. It should take account of your source code system, your build system and provide workarounds as necessary
  • If you are using JDeveloper and find that one of your objects appears to 'lose' its versioning status after an update - think rename!
  • Always ensure that you fully comment a rename on commit so that other users can use the log to find out where and why their object was deleted from the repository
In a forthcoming post I want to look more closely at how you detect and work to correct a rename problem. Specifically I want to use JDEV's offline database objects to do this. In the Java world developers may be more aware of the power of refactoring. But, as I said above, this is not a problem restricted to Java. I want to highlight the effect on XML and database objects.

No comments: