rebase: filter out descendants of divergence-causing commits earlier
`hg rebase` treats obsolete commits differently depending what has
happened to the commit:
1) Obsolete commit without non-obsolete successors: Skipped, and a
note is printed ("it has no successor").
2) Obsolete commit with a successor in the destination (ancestor of
it): Skipped, and a note is printed ("already in destination").
3) Obsolete commit with a successor in the rebase set: The commit and
its descendants are skipped, and a note is printed ("not rebasing
<commit> and its descendants as this would cause divergence"), unless
`allowdivergence` config set.
4) Obsolete commit with a successor elsewhere: Error ("this rebase
will cause divergences"), unless `allowdivergence` config set.
Before this patch, we did all those checks up front, except for (3),
which was checked later. The later check consisted of two parts: 1)
filtering out of descendants, and 2) conditionally printing message if
the `allowdivergence` config was not set. This patch makes it so we do
the filtering early.
A consequence of filtering out divergence-causing commits earlier is
that we rebase commits in slightly different order, which has some
impact on tests.
Differential Revision: https://phab.mercurial-scm.org/D10249
--- a/hgext/rebase.py Fri Mar 19 10:34:16 2021 -0700
+++ b/hgext/rebase.py Fri Mar 19 22:52:59 2021 -0700
@@ -361,6 +361,19 @@
skippedset = set(self.obsolete_with_successor_in_destination)
skippedset.update(self.obsolete_with_successor_in_rebase_set)
_checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
+ allowdivergence = self.ui.configbool(
+ b'experimental', b'evolution.allowdivergence'
+ )
+ if allowdivergence:
+ self.obsolete_with_successor_in_rebase_set = set()
+ else:
+ for rev in self.repo.revs(
+ b'descendants(%ld) and not %ld',
+ self.obsolete_with_successor_in_rebase_set,
+ self.obsolete_with_successor_in_rebase_set,
+ ):
+ self.state.pop(rev, None)
+ self.destmap.pop(rev, None)
def _prepareabortorcontinue(
self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False
@@ -493,19 +506,10 @@
def progress(ctx):
p.increment(item=(b"%d:%s" % (ctx.rev(), ctx)))
- allowdivergence = self.ui.configbool(
- b'experimental', b'evolution.allowdivergence'
- )
for subset in sortsource(self.destmap):
sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
- if not allowdivergence:
- sortedrevs -= self.repo.revs(
- b'descendants(%ld) and not %ld',
- self.obsolete_with_successor_in_rebase_set,
- self.obsolete_with_successor_in_rebase_set,
- )
for rev in sortedrevs:
- self._rebasenode(tr, rev, allowdivergence, progress)
+ self._rebasenode(tr, rev, progress)
p.complete()
ui.note(_(b'rebase merging completed\n'))
@@ -567,16 +571,13 @@
return newnode
- def _rebasenode(self, tr, rev, allowdivergence, progressfn):
+ def _rebasenode(self, tr, rev, progressfn):
repo, ui, opts = self.repo, self.ui, self.opts
ctx = repo[rev]
desc = _ctxdesc(ctx)
if self.state[rev] == rev:
ui.status(_(b'already rebased %s\n') % desc)
- elif (
- not allowdivergence
- and rev in self.obsolete_with_successor_in_rebase_set
- ):
+ elif rev in self.obsolete_with_successor_in_rebase_set:
msg = (
_(
b'note: not rebasing %s and its descendants as '
--- a/tests/test-rebase-obsolete3.t Fri Mar 19 10:34:16 2021 -0700
+++ b/tests/test-rebase-obsolete3.t Fri Mar 19 22:52:59 2021 -0700
@@ -72,9 +72,9 @@
$ hg rebase -b 'e' -d 'x'
rebasing 1:488e1b7e7341 b "b"
rebasing 3:a82ac2b38757 c "c"
+ note: not rebasing 4:76be324c128b d "d" and its descendants as this would cause divergence
rebasing 5:027ad6c5830d d' "d'"
rebasing 6:d60ebfa0f1cb e "e"
- note: not rebasing 4:76be324c128b d "d" and its descendants as this would cause divergence
$ hg log -G -r 'a'::
o 11:eb6d63fc4ed5 e
|
@@ -207,16 +207,16 @@
$ hg rebase -b 'f' -d 'x'
rebasing 1:488e1b7e7341 b "b"
rebasing 3:a82ac2b38757 c "c"
- rebasing 5:63324dc512ea e' "e'"
- rebasing 7:3ffec603ab53 f "f"
rebasing 4:76be324c128b d "d"
note: not rebasing 6:e36fae928aec e "e" and its descendants as this would cause divergence
+ rebasing 5:63324dc512ea e' "e'"
+ rebasing 7:3ffec603ab53 f "f"
$ hg log -G -r 'a':
- o 13:a1707a5b7c2c d
+ o 13:ef6251596616 f
|
- | o 12:ef6251596616 f
- | |
- | o 11:b6f172e64af9 e'
+ o 12:b6f172e64af9 e'
+ |
+ | o 11:a1707a5b7c2c d
|/
o 10:d008e6b4d3fd c
|
@@ -224,13 +224,13 @@
|
| * 8:2876ce66c6eb g
| |
- | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
+ | | x 7:3ffec603ab53 f (rewritten using rebase as 13:ef6251596616)
| | |
| x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
| | |
- | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
+ | | x 5:63324dc512ea e' (rewritten using rebase as 12:b6f172e64af9)
| | |
- | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
+ | x | 4:76be324c128b d (rewritten using rebase as 11:a1707a5b7c2c)
| |/
| x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
| |