Show More
@@ -370,8 +370,8 b' def rebase(ui, repo, **opts):' | |||||
370 | if state[rev] == -1: |
|
370 | if state[rev] == -1: | |
371 | ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])), |
|
371 | ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])), | |
372 | _('changesets'), total) |
|
372 | _('changesets'), total) | |
373 | p1, p2 = defineparents(repo, rev, target, state, |
|
373 | p1, p2, base = defineparents(repo, rev, target, state, | |
374 |
|
|
374 | targetancestors) | |
375 | storestatus(repo, originalwd, target, state, collapsef, keepf, |
|
375 | storestatus(repo, originalwd, target, state, collapsef, keepf, | |
376 | keepbranchesf, external, activebookmark) |
|
376 | keepbranchesf, external, activebookmark) | |
377 | if len(repo.parents()) == 2: |
|
377 | if len(repo.parents()) == 2: | |
@@ -380,8 +380,8 b' def rebase(ui, repo, **opts):' | |||||
380 | try: |
|
380 | try: | |
381 | ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), |
|
381 | ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), | |
382 | 'rebase') |
|
382 | 'rebase') | |
383 |
stats = rebasenode(repo, rev, p1, state, |
|
383 | stats = rebasenode(repo, rev, p1, base, state, | |
384 | target) |
|
384 | collapsef, target) | |
385 | if stats and stats[3] > 0: |
|
385 | if stats and stats[3] > 0: | |
386 | raise error.InterventionRequired( |
|
386 | raise error.InterventionRequired( | |
387 | _('unresolved conflicts (see hg ' |
|
387 | _('unresolved conflicts (see hg ' | |
@@ -414,8 +414,8 b' def rebase(ui, repo, **opts):' | |||||
414 | ui.note(_('rebase merging completed\n')) |
|
414 | ui.note(_('rebase merging completed\n')) | |
415 |
|
415 | |||
416 | if collapsef and not keepopen: |
|
416 | if collapsef and not keepopen: | |
417 | p1, p2 = defineparents(repo, min(state), target, |
|
417 | p1, p2, _base = defineparents(repo, min(state), target, | |
418 |
|
|
418 | state, targetancestors) | |
419 | editopt = opts.get('edit') |
|
419 | editopt = opts.get('edit') | |
420 | editform = 'rebase.collapse' |
|
420 | editform = 'rebase.collapse' | |
421 | if collapsemsg: |
|
421 | if collapsemsg: | |
@@ -509,7 +509,8 b' def externalparent(repo, state, targetan' | |||||
509 | ', '.join(str(p) for p in sorted(parents)))) |
|
509 | ', '.join(str(p) for p in sorted(parents)))) | |
510 |
|
510 | |||
511 | def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): |
|
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 | Return node of committed revision.''' |
|
514 | Return node of committed revision.''' | |
514 | try: |
|
515 | try: | |
515 | repo.dirstate.beginparentchange() |
|
516 | repo.dirstate.beginparentchange() | |
@@ -539,8 +540,8 b' def concludenode(repo, rev, p1, p2, comm' | |||||
539 | repo.dirstate.invalidate() |
|
540 | repo.dirstate.invalidate() | |
540 | raise |
|
541 | raise | |
541 |
|
542 | |||
542 | def rebasenode(repo, rev, p1, state, collapse, target): |
|
543 | def rebasenode(repo, rev, p1, base, state, collapse, target): | |
543 | 'Rebase a single revision' |
|
544 | 'Rebase a single revision rev on top of p1 using base as merge ancestor' | |
544 | # Merge phase |
|
545 | # Merge phase | |
545 | # Update to target and merge it with local |
|
546 | # Update to target and merge it with local | |
546 | if repo['.'].rev() != p1: |
|
547 | if repo['.'].rev() != p1: | |
@@ -550,48 +551,6 b' def rebasenode(repo, rev, p1, state, col' | |||||
550 | repo.ui.debug(" already in target\n") |
|
551 | repo.ui.debug(" already in target\n") | |
551 | repo.dirstate.write() |
|
552 | repo.dirstate.write() | |
552 | repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev])) |
|
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 | if base is not None: |
|
554 | if base is not None: | |
596 | repo.ui.debug(" detach base %d:%s\n" % (base, repo[base])) |
|
555 | repo.ui.debug(" detach base %d:%s\n" % (base, repo[base])) | |
597 | # When collapsing in-place, the parent is the common ancestor, we |
|
556 | # When collapsing in-place, the parent is the common ancestor, we | |
@@ -660,7 +619,50 b' def defineparents(repo, rev, target, sta' | |||||
660 | p2 = p2n |
|
619 | p2 = p2n | |
661 | repo.ui.debug(" future parents are %d and %d\n" % |
|
620 | repo.ui.debug(" future parents are %d and %d\n" % | |
662 | (repo[p1].rev(), repo[p2].rev())) |
|
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 | def isagitpatch(repo, patchname): |
|
667 | def isagitpatch(repo, patchname): | |
666 | 'Return true if the given patch is in git format' |
|
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