diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -189,6 +189,13 @@ self.activebookmark = None self.destmap = {} self.skipped = set() + self.parentmap = {} + for pm in opts.get(b'parentmap', []): + if pm.count(':') != 1: + raise error.Abort(_(b"--parentmap takes a pair of revisions" + b"separated by colon")) + oldp, newp = pm.split(":") + self.parentmap[int(oldp)] = int(newp) self.collapsef = opts.get(b'collapse', False) self.collapsemsg = cmdutil.logmessage(ui, opts) @@ -614,6 +621,7 @@ self.state, self.skipped, self.obsoletenotrebased, + self.parentmap, ) if not self.inmemory and len(repo[None].parents()) == 2: repo.ui.debug(b'resuming interrupted rebase\n') @@ -692,6 +700,7 @@ self.state, self.skipped, self.obsoletenotrebased, + self.parentmap, ) editopt = opts.get(b'edit') editform = b'rebase.collapse' @@ -870,6 +879,9 @@ _(b'read collapse commit message from file'), _(b'FILE'), ), + (b'p', b'parentmap', [], + _(b'map old parent to new parent (ADVANCED)'), + _(b'REV:REV')), (b'k', b'keep', False, _(b'keep original changesets')), (b'', b'keepbranches', False, _(b'keep original branch names')), (b'D', b'detach', False, _(b'(DEPRECATED)')), @@ -1649,7 +1661,7 @@ yield nodemap[s] -def defineparents(repo, rev, destmap, state, skipped, obsskipped): +def defineparents(repo, rev, destmap, state, skipped, obsskipped, parentmap): """Return new parents and optionally a merge base for rev being rebased The destination specified by "dest" cannot always be used directly because @@ -1707,6 +1719,8 @@ np = dests[i] elif p in state and state[p] > 0: np = state[p] + elif p in parentmap: + np = parentmap[p] # "bases" only record "special" merge bases that cannot be # calculated from changelog DAG (i.e. isancestor(p, np) is False). diff --git a/tests/test-rebase-scenario-global.t b/tests/test-rebase-scenario-global.t --- a/tests/test-rebase-scenario-global.t +++ b/tests/test-rebase-scenario-global.t @@ -982,3 +982,81 @@ $ [ -f .hg/rebasestate ] && echo 'WRONG: rebasestate should not exist' [1] + +Testing rebase of a merge unto a different parent + + $ cd $TESTTNO + $ hg init reparent + $ cd reparent + $ hg debugbuilddag '+2*2 /2 *4' + $ hg log -G + o changeset: 4:e7bd5218ca15 + | tag: tip + | parent: 0:1ea73414a91b + | user: debugbuilddag + | date: Thu Jan 01 00:00:04 1970 +0000 + | summary: r4 + | + | o changeset: 3:2b6d669947cd + | |\ parent: 2:fa942426a6fd + | | | parent: 1:66f7d451a68b + | | | user: debugbuilddag + | | | date: Thu Jan 01 00:00:03 1970 +0000 + | | | summary: r3 + | | | + +---o changeset: 2:fa942426a6fd + | | parent: 0:1ea73414a91b + | | user: debugbuilddag + | | date: Thu Jan 01 00:00:02 1970 +0000 + | | summary: r2 + | | + | o changeset: 1:66f7d451a68b + |/ user: debugbuilddag + | date: Thu Jan 01 00:00:01 1970 +0000 + | summary: r1 + | + o changeset: 0:1ea73414a91b + user: debugbuilddag + date: Thu Jan 01 00:00:00 1970 +0000 + summary: r0 + + $ hg rebase -r 3 -d 4 + rebasing 3:2b6d669947cd "r3" + abort: cannot rebase 3:2b6d669947cd without moving at least one of its parents + [255] + $ hg rebase --abort + rebase aborted + $ hg rebase --parentmap 1:4 -r 3 -d 4 + rebasing 3:2b6d669947cd "r3" + saved backup bundle to $TESTTMP/reparent/.hg/strip-backup/2b6d669947cd-f1a6a874-rebase.hg + $ hg log -G + o changeset: 4:53e482d07281 + |\ tag: tip + | | parent: 3:e7bd5218ca15 + | | parent: 2:fa942426a6fd + | | user: debugbuilddag + | | date: Thu Jan 01 00:00:03 1970 +0000 + | | summary: r3 + | | + | o changeset: 3:e7bd5218ca15 + | | parent: 0:1ea73414a91b + | | user: debugbuilddag + | | date: Thu Jan 01 00:00:04 1970 +0000 + | | summary: r4 + | | + o | changeset: 2:fa942426a6fd + |/ parent: 0:1ea73414a91b + | user: debugbuilddag + | date: Thu Jan 01 00:00:02 1970 +0000 + | summary: r2 + | + | o changeset: 1:66f7d451a68b + |/ user: debugbuilddag + | date: Thu Jan 01 00:00:01 1970 +0000 + | summary: r1 + | + o changeset: 0:1ea73414a91b + user: debugbuilddag + date: Thu Jan 01 00:00:00 1970 +0000 + summary: r0 +