Mercurial > hg
comparison hgext/rebase.py @ 28189:fac3a24be50e
rebase: choose default destination the same way as 'hg merge' (BC)
This changeset finally make 'hg rebase' choose its default destination using the
same logic as 'hg merge'. The previous default was "tipmost changeset on the
current branch", the new default is "the other head if there is only one". This
change has multiple consequences:
- Multiple tests which were not rebasing anything (rebasing from tipmost head)
are now rebasing on the other "lower" branch. This is the expected new
behavior.
- A test is now explicitly aborting when there is too many heads on the branch.
This is the expected behavior.
- We gained a better detection of the "nothing to rebase" case while performing
'hg pull --rebase' so the message have been updated. Making clearer than an
update was performed and why. This is beneficial side-effect.
- Rebasing from an active bookmark will behave the same as 'hg merge' from a
bookmark.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Sun, 14 Feb 2016 13:25:59 +0000 |
parents | 6411140aeda9 |
children | dc6032a1d888 |
comparison
equal
deleted
inserted
replaced
28188:6411140aeda9 | 28189:fac3a24be50e |
---|---|
67 def extrafn(ctx, extra): | 67 def extrafn(ctx, extra): |
68 for c in copiers: | 68 for c in copiers: |
69 c(ctx, extra) | 69 c(ctx, extra) |
70 return extrafn | 70 return extrafn |
71 | 71 |
72 def _destrebase(repo): | 72 def _destrebase(repo, sourceset): |
73 # Destination defaults to the latest revision in the | 73 """small wrapper around destmerge to pass the right extra args |
74 # current branch | 74 |
75 branch = repo[None].branch() | 75 Please wrap destutil.destmerge instead.""" |
76 return repo[branch].rev() | 76 return destutil.destmerge(repo, action='rebase', sourceset=sourceset, |
77 onheadcheck=False) | |
77 | 78 |
78 revsetpredicate = revset.extpredicate() | 79 revsetpredicate = revset.extpredicate() |
79 | 80 |
80 @revsetpredicate('_destrebase') | 81 @revsetpredicate('_destrebase') |
81 def _revsetdestrebase(repo, subset, x): | 82 def _revsetdestrebase(repo, subset, x): |
82 # ``_rebasedefaultdest()`` | 83 # ``_rebasedefaultdest()`` |
83 | 84 |
84 # default destination for rebase. | 85 # default destination for rebase. |
85 # # XXX: Currently private because I expect the signature to change. | 86 # # XXX: Currently private because I expect the signature to change. |
86 # # XXX: - taking rev as arguments, | |
87 # # XXX: - bailing out in case of ambiguity vs returning all data. | 87 # # XXX: - bailing out in case of ambiguity vs returning all data. |
88 # # XXX: - probably merging with the merge destination. | |
89 # i18n: "_rebasedefaultdest" is a keyword | 88 # i18n: "_rebasedefaultdest" is a keyword |
90 revset.getargs(x, 0, 0, _("_rebasedefaultdest takes no arguments")) | 89 sourceset = None |
91 return subset & revset.baseset([_destrebase(repo)]) | 90 if x is not None: |
91 sourceset = revset.getset(repo, revset.fullreposet(repo), x) | |
92 return subset & revset.baseset([_destrebase(repo, sourceset)]) | |
92 | 93 |
93 @command('rebase', | 94 @command('rebase', |
94 [('s', 'source', '', | 95 [('s', 'source', '', |
95 _('rebase the specified changeset and descendants'), _('REV')), | 96 _('rebase the specified changeset and descendants'), _('REV')), |
96 ('b', 'base', '', | 97 ('b', 'base', '', |
125 development tree. | 126 development tree. |
126 | 127 |
127 Published commits cannot be rebased (see :hg:`help phases`). | 128 Published commits cannot be rebased (see :hg:`help phases`). |
128 To copy commits, see :hg:`help graft`. | 129 To copy commits, see :hg:`help graft`. |
129 | 130 |
130 If you don't specify a destination changeset (``-d/--dest``), | 131 If you don't specify a destination changeset (``-d/--dest``), rebase |
131 rebase uses the current branch tip as the destination. (The | 132 will use the same logic as :hg:`merge` to pick a destination. if |
132 destination changeset is not modified by rebasing, but new | 133 the current branch contains exactly one other head, the other head |
133 changesets are added as its descendants.) | 134 is merged with by default. Otherwise, an explicit revision with |
135 which to merge with must be provided. (destination changeset is not | |
136 modified by rebasing, but new changesets are added as its | |
137 descendants.) | |
134 | 138 |
135 Here are the ways to select changesets: | 139 Here are the ways to select changesets: |
136 | 140 |
137 1. Explicitly select them using ``--rev``. | 141 1. Explicitly select them using ``--rev``. |
138 | 142 |
542 cmdutil.checkunfinished(repo) | 546 cmdutil.checkunfinished(repo) |
543 cmdutil.bailifchanged(repo) | 547 cmdutil.bailifchanged(repo) |
544 | 548 |
545 if destf: | 549 if destf: |
546 dest = scmutil.revsingle(repo, destf) | 550 dest = scmutil.revsingle(repo, destf) |
547 else: | |
548 dest = repo[_destrebase(repo)] | |
549 destf = str(dest) | |
550 | 551 |
551 if revf: | 552 if revf: |
552 rebaseset = scmutil.revrange(repo, revf) | 553 rebaseset = scmutil.revrange(repo, revf) |
553 if not rebaseset: | 554 if not rebaseset: |
554 ui.status(_('empty "rev" revision set - nothing to rebase\n')) | 555 ui.status(_('empty "rev" revision set - nothing to rebase\n')) |
564 base = scmutil.revrange(repo, [basef or '.']) | 565 base = scmutil.revrange(repo, [basef or '.']) |
565 if not base: | 566 if not base: |
566 ui.status(_('empty "base" revision set - ' | 567 ui.status(_('empty "base" revision set - ' |
567 "can't compute rebase set\n")) | 568 "can't compute rebase set\n")) |
568 return None, None | 569 return None, None |
570 if not destf: | |
571 dest = repo[_destrebase(repo, base)] | |
572 destf = str(dest) | |
573 | |
569 commonanc = repo.revs('ancestor(%ld, %d)', base, dest).first() | 574 commonanc = repo.revs('ancestor(%ld, %d)', base, dest).first() |
570 if commonanc is not None: | 575 if commonanc is not None: |
571 rebaseset = repo.revs('(%d::(%ld) - %d)::', | 576 rebaseset = repo.revs('(%d::(%ld) - %d)::', |
572 commonanc, base, commonanc) | 577 commonanc, base, commonanc) |
573 else: | 578 else: |
597 'ancestor of destination %s\n') % dest) | 602 'ancestor of destination %s\n') % dest) |
598 else: # can it happen? | 603 else: # can it happen? |
599 ui.status(_('nothing to rebase from %s to %s\n') % | 604 ui.status(_('nothing to rebase from %s to %s\n') % |
600 ('+'.join(str(repo[r]) for r in base), dest)) | 605 ('+'.join(str(repo[r]) for r in base), dest)) |
601 return None, None | 606 return None, None |
607 | |
608 if not destf: | |
609 dest = repo[_destrebase(repo, rebaseset)] | |
610 destf = str(dest) | |
611 | |
602 return dest, rebaseset | 612 return dest, rebaseset |
603 | 613 |
604 def externalparent(repo, state, targetancestors): | 614 def externalparent(repo, state, targetancestors): |
605 """Return the revision that should be used as the second parent | 615 """Return the revision that should be used as the second parent |
606 when the revisions in state is collapsed on top of targetancestors. | 616 when the revisions in state is collapsed on top of targetancestors. |
1196 del opts['rev'] | 1206 del opts['rev'] |
1197 # positional argument from pull conflicts with rebase's own | 1207 # positional argument from pull conflicts with rebase's own |
1198 # --source. | 1208 # --source. |
1199 if 'source' in opts: | 1209 if 'source' in opts: |
1200 del opts['source'] | 1210 del opts['source'] |
1201 if rebase(ui, repo, **opts) == _nothingtorebase(): | 1211 try: |
1212 rebase(ui, repo, **opts) | |
1213 except error.NoMergeDestAbort: | |
1214 # we can maybe update instead | |
1202 rev, _a, _b = destutil.destupdate(repo) | 1215 rev, _a, _b = destutil.destupdate(repo) |
1203 if rev != repo['.'].rev(): # we could update | 1216 if rev == repo['.'].rev(): |
1217 ui.status(_('nothing to rebase\n')) | |
1218 else: | |
1219 ui.status(_('nothing to rebase - updating instead\n')) | |
1204 # not passing argument to get the bare update behavior | 1220 # not passing argument to get the bare update behavior |
1205 # with warning and trumpets | 1221 # with warning and trumpets |
1206 commands.update(ui, repo) | 1222 commands.update(ui, repo) |
1207 finally: | 1223 finally: |
1208 release(lock, wlock) | 1224 release(lock, wlock) |