Show More
@@ -574,9 +574,9 b' def abort(repo, originalwd, target, stat' | |||
|
574 | 574 | merge.update(repo, repo[originalwd].rev(), False, True, False) |
|
575 | 575 | rebased = filter(lambda x: x > -1 and x != target, state.values()) |
|
576 | 576 | if rebased: |
|
577 |
strippoint = |
|
|
577 | strippoints = [c.node() for c in repo.set('roots(%ld)', rebased)] | |
|
578 | 578 | # no backup of rebased cset versions needed |
|
579 |
repair.strip(repo.ui, repo, |
|
|
579 | repair.strip(repo.ui, repo, strippoints) | |
|
580 | 580 | clearstatus(repo) |
|
581 | 581 | repo.ui.warn(_('rebase aborted\n')) |
|
582 | 582 | return 0 |
@@ -599,65 +599,65 b' def buildstate(repo, dest, rebaseset, co' | |||
|
599 | 599 | roots = list(repo.set('roots(%ld)', rebaseset)) |
|
600 | 600 | if not roots: |
|
601 | 601 | raise util.Abort(_('no matching revisions')) |
|
602 | if len(roots) > 1: | |
|
603 | raise util.Abort(_("can't rebase multiple roots")) | |
|
604 | root = roots[0] | |
|
605 | ||
|
606 | commonbase = root.ancestor(dest) | |
|
607 | if commonbase == root: | |
|
608 | raise util.Abort(_('source is ancestor of destination')) | |
|
609 | if commonbase == dest: | |
|
610 | samebranch = root.branch() == dest.branch() | |
|
611 | if not collapse and samebranch and root in dest.children(): | |
|
612 | repo.ui.debug('source is a child of destination\n') | |
|
613 | return None | |
|
602 | roots.sort() | |
|
603 | state = {} | |
|
604 | detachset = set() | |
|
605 | for root in roots: | |
|
606 | commonbase = root.ancestor(dest) | |
|
607 | if commonbase == root: | |
|
608 | raise util.Abort(_('source is ancestor of destination')) | |
|
609 | if commonbase == dest: | |
|
610 | samebranch = root.branch() == dest.branch() | |
|
611 | if not collapse and samebranch and root in dest.children(): | |
|
612 | repo.ui.debug('source is a child of destination\n') | |
|
613 | return None | |
|
614 | 614 | |
|
615 |
repo.ui.debug('rebase onto %d starting from % |
|
|
616 |
state |
|
|
617 | # Rebase tries to turn <dest> into a parent of <root> while | |
|
618 | # preserving the number of parents of rebased changesets: | |
|
619 | # | |
|
620 | # - A changeset with a single parent will always be rebased as a | |
|
621 | # changeset with a single parent. | |
|
622 | # | |
|
623 | # - A merge will be rebased as merge unless its parents are both | |
|
624 | # ancestors of <dest> or are themselves in the rebased set and | |
|
625 | # pruned while rebased. | |
|
626 | # | |
|
627 | # If one parent of <root> is an ancestor of <dest>, the rebased | |
|
628 | # version of this parent will be <dest>. This is always true with | |
|
629 | # --base option. | |
|
630 | # | |
|
631 | # Otherwise, we need to *replace* the original parents with | |
|
632 | # <dest>. This "detaches" the rebased set from its former location | |
|
633 | # and rebases it onto <dest>. Changes introduced by ancestors of | |
|
634 | # <root> not common with <dest> (the detachset, marked as | |
|
635 | # nullmerge) are "removed" from the rebased changesets. | |
|
636 | # | |
|
637 | # - If <root> has a single parent, set it to <dest>. | |
|
638 | # | |
|
639 | # - If <root> is a merge, we cannot decide which parent to | |
|
640 | # replace, the rebase operation is not clearly defined. | |
|
641 | # | |
|
642 | # The table below sums up this behavior: | |
|
643 | # | |
|
644 |
# + |
|
|
645 |
|
|
|
646 |
# + |
|
|
647 |
# | parent in |
|
|
648 |
|
|
|
649 |
# + |
|
|
650 |
# | unrelated source |
|
|
651 |
# + |
|
|
652 | # | |
|
653 | # The actual abort is handled by `defineparents` | |
|
654 | if len(root.parents()) <= 1: | |
|
655 | # ancestors of <root> not ancestors of <dest> | |
|
656 |
detachset |
|
|
657 | [root.rev()]) | |
|
658 | state.update(dict.fromkeys(detachset, nullmerge)) | |
|
659 | # detachset can have root, and we definitely want to rebase that | |
|
660 |
state[r |
|
|
615 | repo.ui.debug('rebase onto %d starting from %s\n' % (dest, roots)) | |
|
616 | state.update(dict.fromkeys(rebaseset, nullrev)) | |
|
617 | # Rebase tries to turn <dest> into a parent of <root> while | |
|
618 | # preserving the number of parents of rebased changesets: | |
|
619 | # | |
|
620 | # - A changeset with a single parent will always be rebased as a | |
|
621 | # changeset with a single parent. | |
|
622 | # | |
|
623 | # - A merge will be rebased as merge unless its parents are both | |
|
624 | # ancestors of <dest> or are themselves in the rebased set and | |
|
625 | # pruned while rebased. | |
|
626 | # | |
|
627 | # If one parent of <root> is an ancestor of <dest>, the rebased | |
|
628 | # version of this parent will be <dest>. This is always true with | |
|
629 | # --base option. | |
|
630 | # | |
|
631 | # Otherwise, we need to *replace* the original parents with | |
|
632 | # <dest>. This "detaches" the rebased set from its former location | |
|
633 | # and rebases it onto <dest>. Changes introduced by ancestors of | |
|
634 | # <root> not common with <dest> (the detachset, marked as | |
|
635 | # nullmerge) are "removed" from the rebased changesets. | |
|
636 | # | |
|
637 | # - If <root> has a single parent, set it to <dest>. | |
|
638 | # | |
|
639 | # - If <root> is a merge, we cannot decide which parent to | |
|
640 | # replace, the rebase operation is not clearly defined. | |
|
641 | # | |
|
642 | # The table below sums up this behavior: | |
|
643 | # | |
|
644 | # +------------------+----------------------+-------------------------+ | |
|
645 | # | | one parent | merge | | |
|
646 | # +------------------+----------------------+-------------------------+ | |
|
647 | # | parent in | new parent is <dest> | parents in ::<dest> are | | |
|
648 | # | ::<dest> | | remapped to <dest> | | |
|
649 | # +------------------+----------------------+-------------------------+ | |
|
650 | # | unrelated source | new parent is <dest> | ambiguous, abort | | |
|
651 | # +------------------+----------------------+-------------------------+ | |
|
652 | # | |
|
653 | # The actual abort is handled by `defineparents` | |
|
654 | if len(root.parents()) <= 1: | |
|
655 | # ancestors of <root> not ancestors of <dest> | |
|
656 | detachset.update(repo.changelog.findmissingrevs([commonbase.rev()], | |
|
657 | [root.rev()])) | |
|
658 | for r in detachset: | |
|
659 | if r not in state: | |
|
660 | state[r] = nullmerge | |
|
661 | 661 | return repo['.'].rev(), dest.rev(), state |
|
662 | 662 | |
|
663 | 663 | def clearrebased(ui, repo, state, collapsedas=None): |
@@ -677,12 +677,16 b' def clearrebased(ui, repo, state, collap' | |||
|
677 | 677 | else: |
|
678 | 678 | rebased = [rev for rev in state if state[rev] != nullmerge] |
|
679 | 679 | if rebased: |
|
680 | if set(repo.changelog.descendants([min(rebased)])) - set(state): | |
|
681 | ui.warn(_("warning: new changesets detected " | |
|
682 | "on source branch, not stripping\n")) | |
|
683 | else: | |
|
680 | stripped = [] | |
|
681 | for root in repo.set('roots(%ld)', rebased): | |
|
682 | if set(repo.changelog.descendants([root.rev()])) - set(state): | |
|
683 | ui.warn(_("warning: new changesets detected " | |
|
684 | "on source branch, not stripping\n")) | |
|
685 | else: | |
|
686 | stripped.append(root.node()) | |
|
687 | if stripped: | |
|
684 | 688 | # backup the old csets by default |
|
685 |
repair.strip(ui, repo, |
|
|
689 | repair.strip(ui, repo, stripped, "all") | |
|
686 | 690 | |
|
687 | 691 | |
|
688 | 692 | def pullrebase(orig, ui, repo, *args, **opts): |
@@ -306,3 +306,26 b' Test that rewriting leaving instability ' | |||
|
306 | 306 | |
|
307 | 307 | |
|
308 | 308 | |
|
309 | Test multiple root handling | |
|
310 | ------------------------------------ | |
|
311 | ||
|
312 | $ hg rebase --dest 4 --rev '7+11+9' | |
|
313 | $ hg log -G | |
|
314 | @ 14:00891d85fcfc C | |
|
315 | | | |
|
316 | | o 13:102b4c1d889b D | |
|
317 | |/ | |
|
318 | | o 12:bfe264faf697 H | |
|
319 | |/ | |
|
320 | | o 10:7c6027df6a99 B | |
|
321 | | | | |
|
322 | | x 7:02de42196ebe H | |
|
323 | | | | |
|
324 | +---o 6:eea13746799a G | |
|
325 | | |/ | |
|
326 | | o 5:24b6387c8c8c F | |
|
327 | | | | |
|
328 | o | 4:9520eea781bc E | |
|
329 | |/ | |
|
330 | o 0:cd010b8cd998 A | |
|
331 |
@@ -542,6 +542,108 b' We would expect heads are I, F if it was' | |||
|
542 | 542 | $ hg clone -q -u . ah ah6 |
|
543 | 543 | $ cd ah6 |
|
544 | 544 | $ hg rebase -r '(4+6)::' -d 1 |
|
545 | abort: can't rebase multiple roots | |
|
546 | [255] | |
|
545 | saved backup bundle to $TESTTMP/ah6/.hg/strip-backup/3d8a618087a7-backup.hg (glob) | |
|
546 | $ hg tglog | |
|
547 | @ 8: 'I' | |
|
548 | | | |
|
549 | o 7: 'H' | |
|
550 | | | |
|
551 | o 6: 'G' | |
|
552 | | | |
|
553 | | o 5: 'F' | |
|
554 | | | | |
|
555 | | o 4: 'E' | |
|
556 | |/ | |
|
557 | | o 3: 'D' | |
|
558 | | | | |
|
559 | | o 2: 'C' | |
|
560 | | | | |
|
561 | o | 1: 'B' | |
|
562 | |/ | |
|
563 | o 0: 'A' | |
|
564 | ||
|
547 | 565 | $ cd .. |
|
566 | ||
|
567 | More complexe rebase with multiple roots | |
|
568 | each root have a different common ancestor with the destination and this is a detach | |
|
569 | ||
|
570 | (setup) | |
|
571 | ||
|
572 | $ hg clone -q -u . a a8 | |
|
573 | $ cd a8 | |
|
574 | $ echo I > I | |
|
575 | $ hg add I | |
|
576 | $ hg commit -m I | |
|
577 | $ hg up 4 | |
|
578 | 1 files updated, 0 files merged, 3 files removed, 0 files unresolved | |
|
579 | $ echo I > J | |
|
580 | $ hg add J | |
|
581 | $ hg commit -m J | |
|
582 | created new head | |
|
583 | $ echo I > K | |
|
584 | $ hg add K | |
|
585 | $ hg commit -m K | |
|
586 | $ hg tglog | |
|
587 | @ 10: 'K' | |
|
588 | | | |
|
589 | o 9: 'J' | |
|
590 | | | |
|
591 | | o 8: 'I' | |
|
592 | | | | |
|
593 | | o 7: 'H' | |
|
594 | | | | |
|
595 | +---o 6: 'G' | |
|
596 | | |/ | |
|
597 | | o 5: 'F' | |
|
598 | | | | |
|
599 | o | 4: 'E' | |
|
600 | |/ | |
|
601 | | o 3: 'D' | |
|
602 | | | | |
|
603 | | o 2: 'C' | |
|
604 | | | | |
|
605 | | o 1: 'B' | |
|
606 | |/ | |
|
607 | o 0: 'A' | |
|
608 | ||
|
609 | (actual test) | |
|
610 | ||
|
611 | $ hg rebase --dest 'desc(G)' --rev 'desc(K) + desc(I)' | |
|
612 | saved backup bundle to $TESTTMP/a8/.hg/strip-backup/23a4ace37988-backup.hg (glob) | |
|
613 | $ hg log --rev 'children(desc(G))' | |
|
614 | changeset: 9:adb617877056 | |
|
615 | parent: 6:eea13746799a | |
|
616 | user: test | |
|
617 | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
618 | summary: I | |
|
619 | ||
|
620 | changeset: 10:882431a34a0e | |
|
621 | tag: tip | |
|
622 | parent: 6:eea13746799a | |
|
623 | user: test | |
|
624 | date: Thu Jan 01 00:00:00 1970 +0000 | |
|
625 | summary: K | |
|
626 | ||
|
627 | $ hg tglog | |
|
628 | @ 10: 'K' | |
|
629 | | | |
|
630 | | o 9: 'I' | |
|
631 | |/ | |
|
632 | | o 8: 'J' | |
|
633 | | | | |
|
634 | | | o 7: 'H' | |
|
635 | | | | | |
|
636 | o---+ 6: 'G' | |
|
637 | |/ / | |
|
638 | | o 5: 'F' | |
|
639 | | | | |
|
640 | o | 4: 'E' | |
|
641 | |/ | |
|
642 | | o 3: 'D' | |
|
643 | | | | |
|
644 | | o 2: 'C' | |
|
645 | | | | |
|
646 | | o 1: 'B' | |
|
647 | |/ | |
|
648 | o 0: 'A' | |
|
649 |
General Comments 0
You need to be logged in to leave comments.
Login now