Rebase
While the word "rebase" is a bit confusing, it fundamentally just means moving
commits from one part of the repository to another. In Sapling, this is
done with the sl rebase
command.
Rebasing requires two pieces of information:
- Which commits will be moved, via one of the flags
-r
(revisions),-s
(source), or-b
(base). - The destination commit to move the commits to, via the
-d
(destination) flag.
Examples
To illustrate the different types of rebases, assume we start with the following
commit graph. Note that we are currently on Commit C, as indicated by the @
symbol.
$ sl
╷
╷
╷ │ Commit F
╷ │
╷
╷ │ Commit E
╷ │
╷ │
╷ │ │ Commit D
╷ │ │
╷ │
╷ ├─╯ Commit C
╷ │
╷
╷ │ Commit B
╷ │
╷
╭─╯ Commit A
│
╷
~
-b / --base
The most common use for rebase is to move your in-progress commits onto a newer
version of main. The -b
flag is ideal for this situation, as it will take the
entire subtree of your commits and move them onto the destination.
Below we use -b .
to rebase the current commit, .
, and its entire related
subtree onto main. In this case, the subtree is Commit A and all of its
descendants.
Note that sl rebase -b . -d XXX
is the same as sl rebase -d XXX
, as -b .
is the default behavior.
# Move entire current subtree onto main.
$ sl rebase -b . -d main
│ Commit F
│
│ Commit E
│
│
│ │ Commit D
│ │
│
├─╯ Commit C
│
│ Commit B
│
╭─╯ Commit A
│
╷
╷
~
-s / --source
If you don't want to rebase the entire subtree with -b
, you can use -s
to
rebase a given commit and all of its descendants.
Below we use -s .
to rebase the current commit, .
, and its descendant
Commit D
onto main
. All other commits are left behind.
# Move current commit and its descendants onto main.
$ sl rebase -s . -d main
│ Commit D
│
╭─╯ Commit C
│
╷
╷
╷ │ Commit F
╷ │
╷
╷ │ Commit E
╷ │
╷
╷ │ Commit B
╷ │
╷
╭─╯ Commit A
│
╷
~
-r / --revisions
If we only want to move a specific commit or commits, we use -r
to move
exactly the commits we specified.
Below we move the commit we're on by specifying .
as the argument to -r
. We
move it onto main
by specifying main
as the argument to -d
.
# Move just the current commit to be based on main
$ sl rebase -r . -d main
rebasing 6f782187aa42 "Commit C"
6f782187aa42 -> 8abef7d37f3a "Commit C"
$ sl
╭─╯ Commit C
│
╷
╷
╷ │ Commit F
╷ │
╷
╷ │ Commit E
╷ │
╷ │
╷ │ │ Commit D
╷ │ │
╷ │
╷ ├─╯ Commit C
╷ │
╷
╷ │ Commit B
╷ │
╷
╭─╯ Commit A
│
╷
~
Note how 6f782187a
is identified with an x
in the commit graph to denote that it
has been rewritten to the newer version 8abef7d37f3a
. However, it is still visible
because commit D did not get rebased.
Other
The rebase command can move multiple stacks and subtrees in a single invocation. The tree structure will be retained across the rebase. For example, one can use the draft()
revset to rebase all of your local commits onto a newer base commit.
$ sl
╷
╷
╷ │ Commit C
╷ │
╷ │
╷ ├─╯ Commit B
╷ │
╷
╭─╯ Commit A
│
╷
╷
╷ │ Commit Two
╷ │
╷
╭─╯ Commit One
│
╷
~
# Rebase all my commits onto new main.
$ sl rebase -r 'draft()' -d main
$ sl
│ Commit C
│
│
├─╯ Commit B
│
╭─╯ Commit A
│
│
│ │ Commit Two
│ │
│
├─╯ Commit One
│
╷
╷
~