Workflow question: merging a single rev.

Pierre Asselin pa at panix.com
Sat Apr 25 21:14:41 CDT 2009


David Frey <dpfrey at shaw.ca> wrote:
> Hypothetical workflow question:

> Say I make a clone of the main repository to implement a feature.  Part way
> through my development, I find a bug in some low level service and fix it. 
> I keep working on my feature.  I mention to a colleague that I made the fix
> to the low level service.  He says that he has been having the same problem
> and needs the fix right away.

Others already mentioned the transplant extension.  There is also
a way to cherry-pick your bugfix manually with core hg commands.
I assume your bugfix is a single commit, or at least an uninterrupted
sequence of commits.  The workflow goes like this --I think, it's
been a while.

    (1)  hg update --clean --rev just-before-fix
    (2)  hg revert --rev starting-point
    (3)  hg update --rev just-after-fix
    repair conflicts
    (4)  hg update --rev starting-point

At this point you have a working copy whose parent is starting-point
and whose only uncommitted changes are the bugfix.  Use "hg diff"
to make sure, test, commit.

    (5)  hg commit -m 'bugfix blabla'

The trick relies on the peculiar (to a CVS transfuge) semantics of
"hg update" with uncommitted changes in the working directory.
Such updates are allowed if they don't cross branch boundaries.
Going forward along a branch, "update" does a three-way merge of
your pending changes with the delta to the target revision and
reparents your directory to the target rev.  Going backwards, it
reparents you to the target rev without changing anything to the
files.  (There is a reason for this behavior, but it is what
it is.)

Okay, so.  At step (1) you have a clean copy of where you were just
before you made the fix.  At step (2) your working copy has large
changes that undo all your feature work, but none of that is committed;
your working copy is still a child of just-before-fix.

Step (3) attempts to merge this large uncommitted backtrack with
the small change that was the bugfix.  If it works, or if you manage
to fix all the conflicts, your working copy contains starting-point
plus the bugfix, and is a child of just-after-fix.  To hg, your
working copy still has large uncommitted changes but to you it has
exactly the files you want.

Step (4) does nothing to the uncommitted changes because it is a
backward update.  At step (4) your working copy is a child of
starting-point and now the uncommitted changes should look a lot
smaller, just the bug fix.  Confirm with "hg diff", test and commit.

Things get messier if there are file renames in the mix.  You
have to manually de-add and de-remove, then rename.

Also your bugfix is still in the feature branch and may generate
spurious conflicts when you merge that branch with the fixed
mainline.  You might want to back it out of your feature branch,
even if you immediately re-merge it from the now official bugfix
changeset.

Have fun.

-- 
pa at panix dot com



More information about the Mercurial mailing list