Show More
@@ -370,8 +370,8 b' def rebase(ui, repo, **opts):' | |||
|
370 | 370 | if state[rev] == -1: |
|
371 | 371 | ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])), |
|
372 | 372 | _('changesets'), total) |
|
373 | p1, p2 = defineparents(repo, rev, target, state, | |
|
374 |
|
|
|
373 | p1, p2, base = defineparents(repo, rev, target, state, | |
|
374 | targetancestors) | |
|
375 | 375 | storestatus(repo, originalwd, target, state, collapsef, keepf, |
|
376 | 376 | keepbranchesf, external, activebookmark) |
|
377 | 377 | if len(repo.parents()) == 2: |
@@ -380,8 +380,8 b' def rebase(ui, repo, **opts):' | |||
|
380 | 380 | try: |
|
381 | 381 | ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), |
|
382 | 382 | 'rebase') |
|
383 |
stats = rebasenode(repo, rev, p1, state, |
|
|
384 | target) | |
|
383 | stats = rebasenode(repo, rev, p1, base, state, | |
|
384 | collapsef, target) | |
|
385 | 385 | if stats and stats[3] > 0: |
|
386 | 386 | raise error.InterventionRequired( |
|
387 | 387 | _('unresolved conflicts (see hg ' |
@@ -414,8 +414,8 b' def rebase(ui, repo, **opts):' | |||
|
414 | 414 | ui.note(_('rebase merging completed\n')) |
|
415 | 415 | |
|
416 | 416 | if collapsef and not keepopen: |
|
417 | p1, p2 = defineparents(repo, min(state), target, | |
|
418 |
|
|
|
417 | p1, p2, _base = defineparents(repo, min(state), target, | |
|
418 | state, targetancestors) | |
|
419 | 419 | editopt = opts.get('edit') |
|
420 | 420 | editform = 'rebase.collapse' |
|
421 | 421 | if collapsemsg: |
@@ -509,7 +509,8 b' def externalparent(repo, state, targetan' | |||
|
509 | 509 | ', '.join(str(p) for p in sorted(parents)))) |
|
510 | 510 | |
|
511 | 511 | def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): |
|
512 |
'''Commit the changes |
|
|
512 | '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev | |
|
513 | but also store useful information in extra. | |
|
513 | 514 | Return node of committed revision.''' |
|
514 | 515 | try: |
|
515 | 516 | repo.dirstate.beginparentchange() |
@@ -539,8 +540,8 b' def concludenode(repo, rev, p1, p2, comm' | |||
|
539 | 540 | repo.dirstate.invalidate() |
|
540 | 541 | raise |
|
541 | 542 | |
|
542 | def rebasenode(repo, rev, p1, state, collapse, target): | |
|
543 | 'Rebase a single revision' | |
|
543 | def rebasenode(repo, rev, p1, base, state, collapse, target): | |
|
544 | 'Rebase a single revision rev on top of p1 using base as merge ancestor' | |
|
544 | 545 | # Merge phase |
|
545 | 546 | # Update to target and merge it with local |
|
546 | 547 | if repo['.'].rev() != p1: |
@@ -550,48 +551,6 b' def rebasenode(repo, rev, p1, state, col' | |||
|
550 | 551 | repo.ui.debug(" already in target\n") |
|
551 | 552 | repo.dirstate.write() |
|
552 | 553 | repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev])) |
|
553 | if rev == min(state): | |
|
554 | # Case (1) initial changeset of a non-detaching rebase. | |
|
555 | # Let the merge mechanism find the base itself. | |
|
556 | base = None | |
|
557 | elif not repo[rev].p2(): | |
|
558 | # Case (2) detaching the node with a single parent, use this parent | |
|
559 | base = repo[rev].p1().rev() | |
|
560 | else: | |
|
561 | # In case of merge, we need to pick the right parent as merge base. | |
|
562 | # | |
|
563 | # Imagine we have: | |
|
564 | # - M: currently rebase revision in this step | |
|
565 | # - A: one parent of M | |
|
566 | # - B: second parent of M | |
|
567 | # - D: destination of this merge step (p1 var) | |
|
568 | # | |
|
569 | # If we are rebasing on D, D is the successors of A or B. The right | |
|
570 | # merge base is the one D succeed to. We pretend it is B for the rest | |
|
571 | # of this comment | |
|
572 | # | |
|
573 | # If we pick B as the base, the merge involves: | |
|
574 | # - changes from B to M (actual changeset payload) | |
|
575 | # - changes from B to D (induced by rebase) as D is a rebased | |
|
576 | # version of B) | |
|
577 | # Which exactly represent the rebase operation. | |
|
578 | # | |
|
579 | # If we pick the A as the base, the merge involves | |
|
580 | # - changes from A to M (actual changeset payload) | |
|
581 | # - changes from A to D (with include changes between unrelated A and B | |
|
582 | # plus changes induced by rebase) | |
|
583 | # Which does not represent anything sensible and creates a lot of | |
|
584 | # conflicts. | |
|
585 | for p in repo[rev].parents(): | |
|
586 | if state.get(p.rev()) == p1: | |
|
587 | base = p.rev() | |
|
588 | break | |
|
589 | else: # fallback when base not found | |
|
590 | base = None | |
|
591 | ||
|
592 | # Raise because this function is called wrong (see issue 4106) | |
|
593 | raise AssertionError('no base found to rebase on ' | |
|
594 | '(rebasenode called wrong)') | |
|
595 | 554 | if base is not None: |
|
596 | 555 | repo.ui.debug(" detach base %d:%s\n" % (base, repo[base])) |
|
597 | 556 | # When collapsing in-place, the parent is the common ancestor, we |
@@ -660,7 +619,50 b' def defineparents(repo, rev, target, sta' | |||
|
660 | 619 | p2 = p2n |
|
661 | 620 | repo.ui.debug(" future parents are %d and %d\n" % |
|
662 | 621 | (repo[p1].rev(), repo[p2].rev())) |
|
663 | return p1, p2 | |
|
622 | ||
|
623 | if rev == min(state): | |
|
624 | # Case (1) initial changeset of a non-detaching rebase. | |
|
625 | # Let the merge mechanism find the base itself. | |
|
626 | base = None | |
|
627 | elif not repo[rev].p2(): | |
|
628 | # Case (2) detaching the node with a single parent, use this parent | |
|
629 | base = repo[rev].p1().rev() | |
|
630 | else: | |
|
631 | # In case of merge, we need to pick the right parent as merge base. | |
|
632 | # | |
|
633 | # Imagine we have: | |
|
634 | # - M: currently rebase revision in this step | |
|
635 | # - A: one parent of M | |
|
636 | # - B: second parent of M | |
|
637 | # - D: destination of this merge step (p1 var) | |
|
638 | # | |
|
639 | # If we are rebasing on D, D is the successors of A or B. The right | |
|
640 | # merge base is the one D succeed to. We pretend it is B for the rest | |
|
641 | # of this comment | |
|
642 | # | |
|
643 | # If we pick B as the base, the merge involves: | |
|
644 | # - changes from B to M (actual changeset payload) | |
|
645 | # - changes from B to D (induced by rebase) as D is a rebased | |
|
646 | # version of B) | |
|
647 | # Which exactly represent the rebase operation. | |
|
648 | # | |
|
649 | # If we pick the A as the base, the merge involves | |
|
650 | # - changes from A to M (actual changeset payload) | |
|
651 | # - changes from A to D (with include changes between unrelated A and B | |
|
652 | # plus changes induced by rebase) | |
|
653 | # Which does not represent anything sensible and creates a lot of | |
|
654 | # conflicts. | |
|
655 | for p in repo[rev].parents(): | |
|
656 | if state.get(p.rev()) == p1: | |
|
657 | base = p.rev() | |
|
658 | break | |
|
659 | else: # fallback when base not found | |
|
660 | base = None | |
|
661 | ||
|
662 | # Raise because this function is called wrong (see issue 4106) | |
|
663 | raise AssertionError('no base found to rebase on ' | |
|
664 | '(defineparents called wrong)') | |
|
665 | return p1, p2, base | |
|
664 | 666 | |
|
665 | 667 | def isagitpatch(repo, patchname): |
|
666 | 668 | 'Return true if the given patch is in git format' |
General Comments 0
You need to be logged in to leave comments.
Login now