hgext/rebase.py
changeset 23732 c51d6c043bb1
parent 23520 de143427c499
child 23877 7cc77030c557
equal deleted inserted replaced
23731:ccbaa2ed11a4 23732:c51d6c043bb1
   643         base = None
   643         base = None
   644     elif not repo[rev].p2():
   644     elif not repo[rev].p2():
   645         # Case (2) detaching the node with a single parent, use this parent
   645         # Case (2) detaching the node with a single parent, use this parent
   646         base = repo[rev].p1().rev()
   646         base = repo[rev].p1().rev()
   647     else:
   647     else:
   648         # In case of merge, we need to pick the right parent as merge base.
   648         # Assuming there is a p1, this is the case where there also is a p2.
       
   649         # We are thus rebasing a merge and need to pick the right merge base.
   649         #
   650         #
   650         # Imagine we have:
   651         # Imagine we have:
   651         # - M: currently rebase revision in this step
   652         # - M: current rebase revision in this step
   652         # - A: one parent of M
   653         # - A: one parent of M
   653         # - B: second parent of M
   654         # - B: other parent of M
   654         # - D: destination of this merge step (p1 var)
   655         # - D: destination of this merge step (p1 var)
   655         #
   656         #
   656         # If we are rebasing on D, D is the successors of A or B. The right
   657         # Consider the case where D is a descendant of A or B and the other is
   657         # merge base is the one D succeed to. We pretend it is B for the rest
   658         # 'outside'. In this case, the right merge base is the D ancestor.
   658         # of this comment
   659         #
       
   660         # An informal proof, assuming A is 'outside' and B is the D ancestor:
   659         #
   661         #
   660         # If we pick B as the base, the merge involves:
   662         # If we pick B as the base, the merge involves:
   661         # - changes from B to M (actual changeset payload)
   663         # - changes from B to M (actual changeset payload)
   662         # - changes from B to D (induced by rebase) as D is a rebased
   664         # - changes from B to D (induced by rebase) as D is a rebased
   663         #   version of B)
   665         #   version of B)
   664         # Which exactly represent the rebase operation.
   666         # Which exactly represent the rebase operation.
   665         #
   667         #
   666         # If we pick the A as the base, the merge involves
   668         # If we pick A as the base, the merge involves:
   667         # - changes from A to M (actual changeset payload)
   669         # - changes from A to M (actual changeset payload)
   668         # - changes from A to D (with include changes between unrelated A and B
   670         # - changes from A to D (with include changes between unrelated A and B
   669         #   plus changes induced by rebase)
   671         #   plus changes induced by rebase)
   670         # Which does not represent anything sensible and creates a lot of
   672         # Which does not represent anything sensible and creates a lot of
   671         # conflicts.
   673         # conflicts. A is thus not the right choice - B is.
       
   674         #
       
   675         # Note: The base found in this 'proof' is only correct in the specified
       
   676         # case. This base does not make sense if is not D a descendant of A or B
       
   677         # or if the other is not parent 'outside' (especially not if the other
       
   678         # parent has been rebased). The current implementation does not
       
   679         # make it feasible to consider different cases separately. In these
       
   680         # other cases we currently just leave it to the user to correctly
       
   681         # resolve an impossible merge using a wrong ancestor.
   672         for p in repo[rev].parents():
   682         for p in repo[rev].parents():
   673             if state.get(p.rev()) == p1:
   683             if state.get(p.rev()) == p1:
   674                 base = p.rev()
   684                 base = p.rev()
   675                 break
   685                 break
   676         else: # fallback when base not found
   686         else: # fallback when base not found