Simulating a Rebase in Mercurial 26 Jul, 2008
I ran into this while doing some work with Pygments this morning — I continued working in a local repo without consciously realizing that a merge node had been created from my work yesterday. If I had just pulled that merge node before committing this morning, everything would be pretty. But it wasn’t, and I wanted to avoid merging the merge which would then cause another merge upstream. Forgive the ascii art.
* $PUSH1
|\
| *
| \
| * $PUSH1
MERGE1 *--/ \
| \
|\ * $CUR2, I don't want this.
| \
| * $PUSH2, I want this, so I can...
MERGE2 *-/
Here’s how:
Background
I pushed $PUSH1, which got merged with $TRUNK, creating $MERGE1.
Some local changes (on top of $PUSH1) later, I am ready to push again (I have
$CUR2 and want to end up with $PUSH2 on top of $MERGE1).
First, enable the transplant extension.
[extensions] transplant=
Go ahead and pull so you have multiple heads in your local repo (don’t push to
your personal remote, any of ($MERGE1:$CUR2] or you’ll have to go
through an extra set of steps first, below).
Rebasing in HG
# we start with two heads, $MERGE and $CUR2, and no uncommitted changes hg update -C $MERGE hg transplant --branch $CUR2 # at this point, your $MERGE head is updated to what we'll call $MERGE2 cd .. # this is the easiest way to remove $CUR2's head hg clone -r $MERGE2 repo new_repo mv repo old_repo mv new_repo repo cd repo hg push
Extra steps if you pushed
If you did push something on $CUR2’s line, you’ll need to fix that first.
ssh remote hg clone -r$MERGE1 remote new_remote cp remote/.hg/hgrc new_remote/.hg/ # set permissions like they were before mv remote old_remote mv new_remote remote