Why backout, not revert?

Giorgos Keramidas keramida at ceid.upatras.gr
Tue Mar 25 08:55:50 CDT 2008


On Tue, 25 Mar 2008 10:37:05 +0100, Marcin Kasperski <Marcin.Kasperski at softax.com.pl> wrote:
> Are there any noticeable advantages of using backout instead of
> revert?
>
> (by using revert I mean
>      hg revert -r BeforeIStartedThisBadIdea
>      hg commit -m "Giving up the flawed concept"
> )

There may be other, unrelated changes since the 'bad' change.  If each
commit is sufficiently self-contained, you will be reverting changes
that may be useful too.

In my every day job, I regularly use Mercurial to 'stage' backouts of
changesets in a Perforce repository.  The history of a checkout may be:

    [1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]
                                  bad

To undo the `bad' changeset [6], I use backout which give me the history
graph shown below:
                                    ,---[9]
                                   /
    [1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]
                                  bad

Then I can "hg update" to changeset [9], and merge the rest of the
changes from [7] and [8].  The useful bits of work from [7] and [8] are
still available in the new 'tip':

                                    ,---[9]--------.
                                   /                \
    [1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]---[10]
                                  bad

I sometimes trim the backout changeset [9], and 'rebase' the backout on
top of the latest tip, by performing a few last steps:

    hg up -C 8
    hg revert --no-b -r 10
    hg ci -m 'Backout changeset 6 (reason)'

This creates a new head off the [8] changeset:

                                    ,---[9]--------.
                                   /                \
    [1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]---[10]
                                  bad          \
                                                `---[11]

Then you can trim the 'branch' of the backout with:

    hg clone -r 6 old-tree new-tree
    hg new-tree
    hg pull -r 11 ../old-tree

This ends up like this:

    [1]---[2]---[3]---[4]---[5]---[6]---[7]---[8]---[9']

Where the new [9'] changeset is the old-tree:11 backout of [6].  This
way I can "hg export" changeset 9' and commit it to some other SCM, like
CVS, or Perforce :)

NOTE: If you use "hg revert -r 5" to remove the changes from changeset
[6], you would also 'lose' the changes from [7] and [8].  Then changes
[10], [11] and [9'] mentioned above would have to be patched again to
include any interesting pieces of work from [7] and [8].

Both backout and revert have their use cases, but there *is* a fairly
important difference in what they do and how much of the source tree
they 'revert' to an older state.

HTH,
Giorgos



More information about the Mercurial mailing list