Our source code management tool of choice is Mercurial; which is a python based DVCS. We switched back in 2009 once we’d gotten fed up with CVS. There are still a few internal projects using CVS, but these days almost all the developers are using mercurial. People always ask why we never moved to subversion and generally my answer has always been because it’s not *significantly* better than CVS. Yes it is better, it might even be CVS done right (not that this is a good advertisement for subversion); but ultimately, I need to use it on the plane or during a proof of concept with no external network access and collaborative development has to take place.
When you have a team of people actively maintaining a code base, someone somewhere is going to break something. It’s unavoidable, skill levels, and interest levels in SCM tools vary massively. We tend to trust the people working on the codebase so more often than not everyone has push access to our repositories. That means mercurial is going to break, at some point, sometime. Just this last week, we had 2 SCM breakages in 2 separate projects, one of which I fixed, and the other was manually merged by the team of devs.
Rolling back a transaction
Ok; so the scenario is, Alice and Bob are writing code, and sharing it via a centralised repository. Carol comes along and makes a couple of changes and pushes them as well. Bob pulls the change, but realises that this change breaks something that he’s working on locally.
You can revert the last transaction by using the rollback command which allows you to rollback the last transaction; a fetch or pull treats all the changesets that were pulled as a single transaction so it’s quite easy to rollback all the changes that you’ve pulled.
If you are using the fetch extension then this will leave some files that have been merged but not checked in. You almost certainly want to do hg update –clean to get rid of all the evidence now.
Remember that you’ve only modified your local repository here, the next time you pull, you’re going to be the same position. There are changes out there, in the wild that you’re going to have to merge at some point.
Using histedit to remove changes
You could enable the histedit plugin and drop the changes you want, but this basically leaves you in the same situation as above, the changes are out there, and you’re going to have to merge them in at some point in the future.
Of course you can force everyone to clone a fresh copy once you’ve replaced the master but you’re generally better off using backout as described next.
Backing out your changes because it’s too late, it’s out there.
Ok; You’ve been happily checking your code into your local repository; your code is awesome. But oh dear during a refactoring exercise you now realise that some of your code needs to be reverted back to a previous version because what was great an hour ago, isn’t so great now. If you’ve been clever then each check-in is the minimal set that needed to be checked in rather than a monolithic check-in where the most suitable checkin message is actually many many changes1 then this shouldn’t be too hard.
This is where the backout command comes in. It won’t delete the change you’ve made, but what it will do is create a new change that reverses the change that you made (you’ve kept the history, and if you had to, you can revert back to the reverted back code). For example, I need to back out change 1704 and get rid of those now not so awesome changes.
Back in the day, there was a tendency for some of the CVS commits to have many many changes as the commit message; it’s now part of our long and chequered history. ↩︎