This page is primarily intended for developers of Mercurial.
This page is no longer relevant but is kept for historical purposes.
Development plan for the rebase extension.
Rebasing allows linear sequence of revisions to be moved from one parent revision to another, using merge tools to resolve conflicts. This can be done already using the MqExtension, but the process is not straightforward and hard to reuse from other commands like conversion tools.
Rebasing would look like:
$ hg rebase branchroot targetparent
branchroot may be a single revision or the parent of a linear sequence of revisions unrelated to targetparent. Every revision in the source branch is merged with targetparent or the previously rebased revision. When the work is done, the source branch is (optionally ?) stripped, so only the rebased version remains. If a merge requires manual intervention, the rebasing process can be restarted afterwards with:
$ hg rebase --continue
If the operation seems impossible to succeed, it can be aborted and the original state restored with:
$ hg rebase --abort
Mercurial's design is based on the idea of immutable history. As such, revisions cannot be moved around easily. It makes stripping the source branch in place impossible since every revision is the parent of a rebased one. The idea is to duplicate the rebased revisions at the same location (without their parenthood with the original branch), then strip both the original branch and the intermediate rebased product. To summarize:
The initial situation looks like:
@ 3:b73cdcf0c323 appendc | o 2:64245ff5f687 appendb | | o 1:762335e0d9f7 add b file |/ o 0:f51f962e6e9f initial
We want to rebase 2 and 3 on top of 1. First, merge 2 and 3 on top of 1:
@ 5:8e910015e5c2 rebased appendc |\ | o 4:dd78ef8da718 rebased appendb | |\ | | | o | | 3:b73cdcf0c323 appendc |/ / o | 2:64245ff5f687 appendb | | | o 1:762335e0d9f7 add b file |/ o 0:f51f962e6e9f initial
Then 4 and 5 are duplicated on top of 1, removing the ancestry link with 2 and 3:
@ 9:9bc3ab20a7ce copy of rebased appendc | o 8:b601c4539702 copy of rebased appendb | | o 7:8e910015e5c2 rebased appendc | |\ | | o 6:dd78ef8da718 rebased appendb | | |\ +-----| | | | | | | | o | 3:b73cdcf0c323 appendc | |/ | o 2:64245ff5f687 appendb | | o | 1:762335e0d9f7 add b file |/ o 0:f51f962e6e9f initial
Finally, all descendants of 2 (64245ff5f687) included are stripped:
o 3:9bc3ab20a7ce appendc | o 2:b601c4539702 appendb | @ 1:762335e0d9f7 add b file | o 0:f51f962e6e9f initial
This sequence may not be optimal but has the interesting property of being easy to terminate or cancel. When done with the rebasing, it's enough to strip starting at the original branch root revision, intermediate rebased ones will come along. To abort or to terminate while preserving the original branch, strip parentroot descendants.
The hard part is to ensure a sane state with regard to interruptibility and user unexpected aptitude to panic and commit new stuff, rollback or do strange things in-between.
3. Random Notes
- It would be great to preserve all revision completely, including extra data. Export/import format do not support that, which is a problem when duplicating the intermediate revisions.
- Is it possible to merge from a non-head revision ? It cannot be done at UI level but there is no reason to forbid it in low-level code.
- Can merge revisions be rebased? Is it meaningful?
4. See Also
MqMerge - how to rebase Mercurial patch queue.