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?>
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?>
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.
If you want to rebase by hand (bad idea in common), you have to
hg help rebase
before-s
and -d
)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
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