Source Code Repository: The Commit Paradox

I shot myself in the foot today, figuratively speaking of course, while struggling with this little subtle dilemma surrounding the rules of code commitment (aka check-in):

  1. To make effective use of a version control system, you should commit your changes often, even if it means committing partially completed features.
  2. As a responsible developer, you should not allow your commit to break the nightly build and regression tests.

I had a piece of enhancement work this morning that I had just finished coding for, but hadn't adequately been tested so I didn't want to commit them to the repository just yet (trying to follow rule #2: don't break the build).

Just then, I realized that there's code duplication in a couple of places. So I decided to do some refactoring. An hour later, a credit of my stunning optimization skills, the code had been nicely refactored. The problem was: the feature enhancement no longer worked! Oops! I must have cut out some vital piece of logic somewhere. The original spaghetti code (that used to work) is now gone--eaten by the refactoring monster.

So in failing to follow rule #1, that set me back by about half a day.

But how can you follow two seemingly paradoxical rules such as ones above? On the one hand, you'd want to commit your changes as often as possible, and not wait until you've fully implemented the feature before committing. On the other hand, you wouldn't want your partial commits to break the automated build and regression tests.

Well, you might say that I should have made a back up of my changes before I start refactoring. Ah hah, but what's the point of a revision control system if you have to keep backups of your changes on the side?

I think the correct solution to this "paradox" would have been to use branching: create a new developmental branch for your enhancement work, even if it was a relatively small enhancement. This would have given me my own sandbox to play with and make partial commits to my heart's content, without breaking the nightly build (because the build would have continued to work on the MAIN branch). And then when I'm satisfied with my implementation, I'd merge the latest changes back into the MAIN branch.


Gavin said...

It sounds like your unit test coverage may be a little light. Truism: don't refactor without a safety net...