views:

142

answers:

2

I understand the restrictions of rollback and the care required in its use (for example, http://www.selenic.com/mercurial/hg.1.html#rollback), but I just wondered why there is only 1 level of rollback.

My guess it's a design decision and that the hassle of storing multiple previous transactional states to handle multiple levels of rollback is more trouble than its worth.

+1  A: 

The trick is: hg rollback is not just about resetting some commits, it reset every data and meta-data associated with the repository.
It actually has no equivalent in Git, and is quite a dangerous mechanism.
It can be mis-used as a way to rewrite the history by resetting it, and that can "reset" more than you wanted.
To allow this on more than one level back would be too dangerous.

When it comes only to resetting/rewriting changeset (which are, by design, immutable), extensions like MQ are better suited.

VonC
I agree - definitely something to avoid - I use MQ so it's never something I've had call to use. Just seems an odd limitation - if you're going to allow it at all why not allow more than one level of rollback.
Nick Pierpoint
+3  A: 

There's only one level of rollback because rollback was never really intended as a feature. Rollback exists, and has it's odd name, because it grew out of mercurial's commit/push/pull transaction system.

If a network push is coming in and it gets 99% done and then the connection is lost the repository shouldn't be left in an inconsistent state. To make sure that an incomplete change can be discarded a "before anything happened" pointer is created before any writes are done and if the change is aborted everything is reset to that state -- rolled back.

The rollback command is really just "failing" the previous operation after it had successfully completed. It's just something that "came free" after necessary transactional security was designed in.

When using something like a controlling hook one can define checks/tests that must be passed in order for a push or commit to complete successfully. In order to not-complete successfully it must be possible to undo that in progress commit, but that doesn't require multiple levels either.

As VonC correctly notes rollback can be pretty dangerous. Many a person rollsback changes they've already pushed and then gets very confused when other those changes come back on subsequent pulls. The hg backout command is almost always a better idea.

Note also that you can simulate a rollback to any point in time easily by doing this:

hg clone -r last_revision_I_want repo_with_things_I_do_not_want new_repo_with_only_good_stuff
Ry4an