Hg: How to do a rebase like git's rebase

jpswain picture jpswain · Apr 20, 2010 · Viewed 76.5k times · Source

In Git I can do this:

1. Start working on new feature:
$ git co -b newfeature-123  # (a local feature development branch)
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream master:
$ git pull
(master updated with ff-commits)

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. Rebase off master so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ git rebase master

master A---B---C---D---E---F
                            \
newfeature-123               M---N---O


I want to know how to do the same thing in Mercurial, and I've scoured the web for an answer, but the best I could find was: git rebase - can hg do that

That link provides 2 examples:
1. I'll admit that this: (replacing the revisions from the example with those from my own example)

hg up -C F  
hg branch -f newfeature-123  
hg transplant -a -b newfeature-123 

is not too bad, except that it leaves behind the pre-rebase M-N-O as an unmerged head and creates 3 new commits M',N',O' that represent them branching off the updated mainline.

Basically the problem is that I end up with this:

master A---B---C---D---E---F
                \           \
newfeature-123   \           M'---N'---O'
                  \
newfeature-123     M---N---O

this is not good because it leaves behind local, unwanted commits that should be dropped.

  1. The other option from the same link is
hg qimport -r M:O
hg qpop -a
hg up F
hg branch newfeature-123
hg qpush -a
hg qdel -r qbase:qtip

and this does result in the desired graph:

master A---B---C---D---E---F
                            \
newfeature-123               M---N---O

but these commands (all 6 of them!) seem so much more complicated than

$ git rebase master

I want to know if this is the only equivalent in Hg or if there is some other way available that is simple like Git.

Answer

Ry4an Brase picture Ry4an Brase · Apr 20, 2010

VonC has the answer you're looking for, the Rebase Extension. It is, however, worth spending a second or two thinking about why neither mq nor rebase are enabled by default in mercurial: because mercurial is all about indelible changesets. When I work in the manner you're describing, which is nearly daily, here's the pattern I take:

1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream mainline:
$ hg pull

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. merge master into my clone so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F

master A---B---C---D---E---F
                \           \
newfeature-123   M---N---O---P

and that's really all that's necessary. I end up with a newfeature-123 clone I can easily push back to the mainline when I'm happy with it. Most importantly, however, I never changed history. Someone can look at my csets and see what they were originally coded against and how I reacted to changes in the mainline throughout my work. Not everyone thinks that has value, but I'm a firm believer that it's the job of source control to show us not what we wished had happened, but what actually happened -- every deadend and every refactor should leave an indelible trace, and rebasing and other history editing techniques hide that.

Now go pick VonC's answer while I put my soapbox away. :)