4

Typically, in HG my workflow is to exclusively use:

hg pull --rebase

If I wanted to run this in two commands, how would I do it?

hg pull
hg rebase <probably with some options?>
sixtyfootersdude
  • 25,859
  • 43
  • 145
  • 213
  • I suspect it's similar to git: http://stackoverflow.com/questions/18930527/difference-between-git-pull-and-git-pull-rebase – jonrsharpe Feb 10 '16 at 22:27

2 Answers2

9

What hg pull --rebase does is to indeed first do a hg pull and then hg rebase with default arguments on top of that (you can look at the code in rebase.py in the Mercurial distribution in function pullrebase()), but only if any new revisions were pulled in. If no rebasing is necessary, hg pull --rebase will update to the new branch tip instead. So, hg pull && hg rebase is approximately correct, but doesn't quite capture some corner cases (no new revisions, no rebase necessary).

By default, hg rebase will use the parent of the working directory as the base revision of the rebase and the most recent revision of the current branch (i.e. usually what you just pulled in) as the destination. In short, it's equivalent to hg rebase -b . -d 'last(branch(.))'.

What does "base revision" mean in this context? It means that Mercurial will go and look for the least common ancestor of the base revision and the destination. Then it will rebase everything up to, but not including that least common ancestor on top of the destination. I.e., specifying the base revision allows you to pick pretty much any revision on the branch [1] that you want to rebase and let Mercurial figure out which revisions belong to that branch.

Note that because the rebase is based on the parent of the current working directory, this means that if your current checkout is not what you have been working on, then hg pull --rebase may surprise you by actually trying to rebase a different branch (it will usually fail, because those revisions are generally part of the public phase, but it's something you need to be aware of if you're working with so-called non-publishing repositories and don't use named branches).

[1] Branch in this context refers to an anonymous or topological branch, not a named branch. See hg help glossary for further details.

Reimer Behrends
  • 8,600
  • 15
  • 19
1

If you want to rebase by hand (bad idea in common), you have to

  • Read hg help rebase before
  • Understand usable for you options of rebase (at least -s and -d)
  • Use these options

Let's see at toy-repos:

Repo A

A>hg log -T "{rev} {desc}\n"
1 A2
0 A1

with 2 changesets A1 and A2 was cloned to repos B and C (B for pull --rebase A, C for clean pull A)

and two additional changesets was added to A and B+C after clone in order to test your use-case (diverged history)

A>hg log -T "{rev} {desc}\n"
3 A2++
2 A2+
1 A2
0 A1

B>hg log -T "{rev} {desc}\n"
3 B2
2 B1
1 A2
0 A1

C state is identical to B

B>hg pull --rebase 
...
B>hg log -T "{rev} {desc}\n" -G
@  5 B2
|
o  4 B1
|
o  3 A2++
|
o  2 A2+
|
o  1 A2
|
o  0 A1

I.e. result of rebased pull is "linear history with local changes on top of remote changes", compared to just pull from C

C>hg log -T "{rev} {desc}\n" -G
@  5 A2++
|
o  4 A2+
|
| o  3 B2
| |
| o  2 B1
|/
o  1 A2
|
o  0 A1

or, in GUI

B-repo C-repo

and in order to get B from C, you have to rebase 2 (-s 2) to new parent 5 (-d 5), but short hg rebase -b 2 will work also and will have the same effect

Lazy Badger
  • 94,711
  • 9
  • 78
  • 110