Show More
@@ -66,7 +66,6 b' revignored = -3' | |||||
66 | revprecursor = -4 |
|
66 | revprecursor = -4 | |
67 | # plain prune (no successor) |
|
67 | # plain prune (no successor) | |
68 | revpruned = -5 |
|
68 | revpruned = -5 | |
69 | revskipped = (revignored, revprecursor, revpruned) |
|
|||
70 |
|
69 | |||
71 | cmdtable = {} |
|
70 | cmdtable = {} | |
72 | command = registrar.command(cmdtable) |
|
71 | command = registrar.command(cmdtable) | |
@@ -390,10 +389,7 b' class rebaseruntime(object):' | |||||
390 | ui.status(_('rebasing %s\n') % desc) |
|
389 | ui.status(_('rebasing %s\n') % desc) | |
391 | ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)), |
|
390 | ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)), | |
392 | _('changesets'), total) |
|
391 | _('changesets'), total) | |
393 | p1, p2, base = defineparents(repo, rev, self.dest, |
|
392 | p1, p2, base = defineparents(repo, rev, self.dest, self.state) | |
394 | self.state, |
|
|||
395 | self.destancestors, |
|
|||
396 | self.obsoletenotrebased) |
|
|||
397 | self.storestatus(tr=tr) |
|
393 | self.storestatus(tr=tr) | |
398 | storecollapsemsg(repo, self.collapsemsg) |
|
394 | storecollapsemsg(repo, self.collapsemsg) | |
399 | if len(repo[None].parents()) == 2: |
|
395 | if len(repo[None].parents()) == 2: | |
@@ -463,9 +459,7 b' class rebaseruntime(object):' | |||||
463 | repo, ui, opts = self.repo, self.ui, self.opts |
|
459 | repo, ui, opts = self.repo, self.ui, self.opts | |
464 | if self.collapsef and not self.keepopen: |
|
460 | if self.collapsef and not self.keepopen: | |
465 | p1, p2, _base = defineparents(repo, min(self.state), |
|
461 | p1, p2, _base = defineparents(repo, min(self.state), | |
466 |
self.dest, self.state |
|
462 | self.dest, self.state) | |
467 | self.destancestors, |
|
|||
468 | self.obsoletenotrebased) |
|
|||
469 | editopt = opts.get('edit') |
|
463 | editopt = opts.get('edit') | |
470 | editform = 'rebase.collapse' |
|
464 | editform = 'rebase.collapse' | |
471 | if self.collapsemsg: |
|
465 | if self.collapsemsg: | |
@@ -960,15 +954,6 b' def adjustdest(repo, rev, dest, state):' | |||||
960 | result.append(adjusted) |
|
954 | result.append(adjusted) | |
961 | return result |
|
955 | return result | |
962 |
|
956 | |||
963 | def nearestrebased(repo, rev, state): |
|
|||
964 | """return the nearest ancestors of rev in the rebase result""" |
|
|||
965 | rebased = [r for r in state if state[r] > nullmerge] |
|
|||
966 | candidates = repo.revs('max(%ld and (::%d))', rebased, rev) |
|
|||
967 | if candidates: |
|
|||
968 | return state[candidates.first()] |
|
|||
969 | else: |
|
|||
970 | return None |
|
|||
971 |
|
||||
972 | def _checkobsrebase(repo, ui, rebaseobsrevs, rebasesetrevs, rebaseobsskipped): |
|
957 | def _checkobsrebase(repo, ui, rebaseobsrevs, rebasesetrevs, rebaseobsskipped): | |
973 | """ |
|
958 | """ | |
974 | Abort if rebase will create divergence or rebase is noop because of markers |
|
959 | Abort if rebase will create divergence or rebase is noop because of markers | |
@@ -992,107 +977,173 b' def _checkobsrebase(repo, ui, rebaseobsr' | |||||
992 | "experimental.allowdivergence=True") |
|
977 | "experimental.allowdivergence=True") | |
993 | raise error.Abort(msg % (",".join(divhashes),), hint=h) |
|
978 | raise error.Abort(msg % (",".join(divhashes),), hint=h) | |
994 |
|
979 | |||
995 | def defineparents(repo, rev, dest, state, destancestors, |
|
980 | def successorrevs(repo, rev): | |
996 | obsoletenotrebased): |
|
981 | """yield revision numbers for successors of rev""" | |
997 | 'Return the new parent relationship of the revision that will be rebased' |
|
982 | unfi = repo.unfiltered() | |
998 | parents = repo[rev].parents() |
|
983 | nodemap = unfi.changelog.nodemap | |
999 | p1 = p2 = nullrev |
|
984 | for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]): | |
1000 | rp1 = None |
|
985 | if s in nodemap: | |
|
986 | yield nodemap[s] | |||
|
987 | ||||
|
988 | def defineparents(repo, rev, dest, state): | |||
|
989 | """Return new parents and optionally a merge base for rev being rebased | |||
|
990 | ||||
|
991 | The destination specified by "dest" cannot always be used directly because | |||
|
992 | previously rebase result could affect destination. For example, | |||
1001 |
|
|
993 | ||
1002 | p1n = parents[0].rev() |
|
994 | D E rebase -r C+D+E -d B | |
1003 | if p1n in destancestors: |
|
995 | |/ C will be rebased to C' | |
1004 | p1 = dest |
|
996 | B C D's new destination will be C' instead of B | |
1005 | elif p1n in state: |
|
997 | |/ E's new destination will be C' instead of B | |
1006 | if state[p1n] == nullmerge: |
|
998 | A | |
1007 | p1 = dest |
|
999 | ||
1008 | elif state[p1n] in revskipped: |
|
1000 | The new parents of a merge is slightly more complicated. See the comment | |
1009 | p1 = nearestrebased(repo, p1n, state) |
|
1001 | block below. | |
1010 | if p1 is None: |
|
1002 | """ | |
1011 | p1 = dest |
|
1003 | cl = repo.changelog | |
1012 | else: |
|
1004 | def isancestor(a, b): | |
1013 | p1 = state[p1n] |
|
1005 | # take revision numbers instead of nodes | |
1014 | else: # p1n external |
|
1006 | if a == b: | |
1015 |
|
|
1007 | return True | |
1016 | p2 = p1n |
|
1008 | elif a > b: | |
|
1009 | return False | |||
|
1010 | return cl.isancestor(cl.node(a), cl.node(b)) | |||
|
1011 | ||||
|
1012 | oldps = repo.changelog.parentrevs(rev) # old parents | |||
|
1013 | newps = [nullrev, nullrev] # new parents | |||
|
1014 | dests = adjustdest(repo, rev, dest, state) # adjusted destinations | |||
|
1015 | bases = list(oldps) # merge base candidates, initially just old parents | |||
1017 |
|
1016 | |||
1018 | if len(parents) == 2 and parents[1].rev() not in destancestors: |
|
1017 | if all(r == nullrev for r in oldps[1:]): | |
1019 | p2n = parents[1].rev() |
|
1018 | # For non-merge changeset, just move p to adjusted dest as requested. | |
1020 | # interesting second parent |
|
1019 | newps[0] = dests[0] | |
1021 | if p2n in state: |
|
1020 | else: | |
1022 | if p1 == dest: # p1n in destancestors or external |
|
1021 | # For merge changeset, if we move p to dests[i] unconditionally, both | |
1023 | p1 = state[p2n] |
|
1022 | # parents may change and the end result looks like "the merge loses a | |
1024 | if p1 == revprecursor: |
|
1023 | # parent", which is a surprise. This is a limit because "--dest" only | |
1025 | rp1 = obsoletenotrebased[p2n] |
|
1024 | # accepts one dest per src. | |
1026 | elif state[p2n] in revskipped: |
|
1025 | # | |
1027 | p2 = nearestrebased(repo, p2n, state) |
|
1026 | # Therefore, only move p with reasonable conditions (in this order): | |
1028 | if p2 is None: |
|
1027 | # 1. use dest, if dest is a descendent of (p or one of p's successors) | |
1029 | # no ancestors rebased yet, detach |
|
1028 | # 2. use p's rebased result, if p is rebased (state[p] > 0) | |
1030 | p2 = dest |
|
1029 | # | |
1031 | else: |
|
1030 | # Comparing with adjustdest, the logic here does some additional work: | |
1032 | p2 = state[p2n] |
|
1031 | # 1. decide which parents will not be moved towards dest | |
1033 | else: # p2n external |
|
1032 | # 2. if the above decision is "no", should a parent still be moved | |
1034 | if p2 != nullrev: # p1n external too => rev is a merged revision |
|
1033 | # because it was rebased? | |
1035 | raise error.Abort(_('cannot use revision %d as base, result ' |
|
1034 | # | |
1036 | 'would have 3 parents') % rev) |
|
1035 | # For example: | |
1037 | p2 = p2n |
|
1036 | # | |
1038 | repo.ui.debug(" future parents are %d and %d\n" % |
|
1037 | # C # "rebase -r C -d D" is an error since none of the parents | |
1039 | (repo[rp1 or p1].rev(), repo[p2].rev())) |
|
1038 | # /| # can be moved. "rebase -r B+C -d D" will move C's parent | |
|
1039 | # A B D # B (using rule "2."), since B will be rebased. | |||
|
1040 | # | |||
|
1041 | # The loop tries to be not rely on the fact that a Mercurial node has | |||
|
1042 | # at most 2 parents. | |||
|
1043 | for i, p in enumerate(oldps): | |||
|
1044 | np = p # new parent | |||
|
1045 | if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)): | |||
|
1046 | np = dests[i] | |||
|
1047 | elif p in state and state[p] > 0: | |||
|
1048 | np = state[p] | |||
1040 |
|
1049 | |||
1041 | if not any(p.rev() in state for p in parents): |
|
1050 | # "bases" only record "special" merge bases that cannot be | |
1042 | # Case (1) root changeset of a non-detaching rebase set. |
|
1051 | # calculated from changelog DAG (i.e. isancestor(p, np) is False). | |
1043 | # Let the merge mechanism find the base itself. |
|
1052 | # For example: | |
|
1053 | # | |||
|
1054 | # B' # rebase -s B -d D, when B was rebased to B'. dest for C | |||
|
1055 | # | C # is B', but merge base for C is B, instead of | |||
|
1056 | # D | # changelog.ancestor(C, B') == A. If changelog DAG and | |||
|
1057 | # | B # "state" edges are merged (so there will be an edge from | |||
|
1058 | # |/ # B to B'), the merge base is still ancestor(C, B') in | |||
|
1059 | # A # the merged graph. | |||
|
1060 | # | |||
|
1061 | # Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8 | |||
|
1062 | # which uses "virtual null merge" to explain this situation. | |||
|
1063 | if isancestor(p, np): | |||
|
1064 | bases[i] = nullrev | |||
|
1065 | ||||
|
1066 | # If one parent becomes an ancestor of the other, drop the ancestor | |||
|
1067 | for j, x in enumerate(newps[:i]): | |||
|
1068 | if x == nullrev: | |||
|
1069 | continue | |||
|
1070 | if isancestor(np, x): | |||
|
1071 | np = nullrev | |||
|
1072 | elif isancestor(x, np): | |||
|
1073 | newps[j] = np | |||
|
1074 | np = nullrev | |||
|
1075 | bases[j], bases[i] = bases[i], bases[j] | |||
|
1076 | ||||
|
1077 | newps[i] = np | |||
|
1078 | ||||
|
1079 | # "rebasenode" updates to new p1, and the old p1 will be used as merge | |||
|
1080 | # base. If only p2 changes, merging using unchanged p1 as merge base is | |||
|
1081 | # suboptimal. Therefore swap parents to make the merge sane. | |||
|
1082 | if newps[1] != nullrev and oldps[0] == newps[0]: | |||
|
1083 | assert len(newps) == 2 and len(oldps) == 2 | |||
|
1084 | newps.reverse() | |||
|
1085 | bases.reverse() | |||
|
1086 | ||||
|
1087 | # No parent change might be an error because we fail to make rev a | |||
|
1088 | # descendent of requested dest. This can happen, for example: | |||
|
1089 | # | |||
|
1090 | # C # rebase -r C -d D | |||
|
1091 | # /| # None of A and B will be changed to D and rebase fails. | |||
|
1092 | # A B D | |||
|
1093 | if set(newps) == set(oldps) and dest not in newps: | |||
|
1094 | # The error message is for compatibility. It's a bit misleading | |||
|
1095 | # since rebase is not supposed to add new parents. | |||
|
1096 | raise error.Abort(_('cannot use revision %d as base, ' | |||
|
1097 | 'result would have 3 parents') % rev) | |||
|
1098 | ||||
|
1099 | repo.ui.debug(" future parents are %d and %d\n" % tuple(newps)) | |||
|
1100 | ||||
|
1101 | # "rebasenode" updates to new p1, use the corresponding merge base. | |||
|
1102 | if bases[0] != nullrev: | |||
|
1103 | base = bases[0] | |||
|
1104 | else: | |||
1044 | base = None |
|
1105 | base = None | |
1045 | elif not repo[rev].p2(): |
|
1106 | ||
1046 | # Case (2) detaching the node with a single parent, use this parent |
|
1107 | # Check if the merge will contain unwanted changes. That may happen if | |
1047 | base = repo[rev].p1().rev() |
|
1108 | # there are multiple special (non-changelog ancestor) merge bases, which | |
1048 | else: |
|
1109 | # cannot be handled well by the 3-way merge algorithm. For example: | |
1049 | # Assuming there is a p1, this is the case where there also is a p2. |
|
1110 | # | |
1050 | # We are thus rebasing a merge and need to pick the right merge base. |
|
1111 | # F | |
1051 | # |
|
1112 | # /| | |
1052 | # Imagine we have: |
|
1113 | # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen | |
1053 | # - M: current rebase revision in this step |
|
1114 | # | | # as merge base, the difference between D and F will include | |
1054 | # - A: one parent of M |
|
1115 | # B C # C, so the rebased F will contain C surprisingly. If "E" was | |
1055 | # - B: other parent of M |
|
1116 | # |/ # chosen, the rebased F will contain B. | |
1056 | # - D: destination of this merge step (p1 var) |
|
1117 | # A Z | |
1057 |
|
|
1118 | # | |
1058 | # Consider the case where D is a descendant of A or B and the other is |
|
1119 | # But our merge base candidates (D and E in above case) could still be | |
1059 | # 'outside'. In this case, the right merge base is the D ancestor. |
|
1120 | # better than the default (ancestor(F, Z) == null). Therefore still | |
1060 | # |
|
1121 | # pick one (so choose p1 above). | |
1061 | # An informal proof, assuming A is 'outside' and B is the D ancestor: |
|
1122 | if sum(1 for b in bases if b != nullrev) > 1: | |
1062 | # |
|
1123 | assert base is not None | |
1063 | # If we pick B as the base, the merge involves: |
|
|||
1064 | # - changes from B to M (actual changeset payload) |
|
|||
1065 | # - changes from B to D (induced by rebase) as D is a rebased |
|
|||
1066 | # version of B) |
|
|||
1067 | # Which exactly represent the rebase operation. |
|
|||
1068 | # |
|
|||
1069 | # If we pick A as the base, the merge involves: |
|
|||
1070 | # - changes from A to M (actual changeset payload) |
|
|||
1071 | # - changes from A to D (with include changes between unrelated A and B |
|
|||
1072 | # plus changes induced by rebase) |
|
|||
1073 | # Which does not represent anything sensible and creates a lot of |
|
|||
1074 | # conflicts. A is thus not the right choice - B is. |
|
|||
1075 | # |
|
|||
1076 | # Note: The base found in this 'proof' is only correct in the specified |
|
|||
1077 | # case. This base does not make sense if is not D a descendant of A or B |
|
|||
1078 | # or if the other is not parent 'outside' (especially not if the other |
|
|||
1079 | # parent has been rebased). The current implementation does not |
|
|||
1080 | # make it feasible to consider different cases separately. In these |
|
|||
1081 | # other cases we currently just leave it to the user to correctly |
|
|||
1082 | # resolve an impossible merge using a wrong ancestor. |
|
|||
1083 | # |
|
|||
1084 | # xx, p1 could be -4, and both parents could probably be -4... |
|
|||
1085 | for p in repo[rev].parents(): |
|
|||
1086 | if state.get(p.rev()) == p1: |
|
|||
1087 | base = p.rev() |
|
|||
1088 | break |
|
|||
1089 | else: # fallback when base not found |
|
|||
1090 | base = None |
|
|||
1091 |
|
1124 | |||
1092 | # Raise because this function is called wrong (see issue 4106) |
|
1125 | # Revisions in the side (not chosen as merge base) branch that might | |
1093 | raise AssertionError('no base found to rebase on ' |
|
1126 | # contain "surprising" contents | |
1094 | '(defineparents called wrong)') |
|
1127 | siderevs = list(repo.revs('((%ld-%d) %% (%d+%d))', | |
1095 | return rp1 or p1, p2, base |
|
1128 | bases, base, base, dest)) | |
|
1129 | ||||
|
1130 | # If those revisions are covered by rebaseset, the result is good. | |||
|
1131 | # A merge in rebaseset would be considered to cover its ancestors. | |||
|
1132 | if siderevs: | |||
|
1133 | rebaseset = [r for r, d in state.items() if d > 0] | |||
|
1134 | merges = [r for r in rebaseset if cl.parentrevs(r)[1] != nullrev] | |||
|
1135 | unwantedrevs = list(repo.revs('%ld - (::%ld) - %ld', | |||
|
1136 | siderevs, merges, rebaseset)) | |||
|
1137 | ||||
|
1138 | # For revs not covered, it is worth a warning. | |||
|
1139 | if unwantedrevs: | |||
|
1140 | repo.ui.warn( | |||
|
1141 | _('warning: rebasing %d:%s may include unwanted changes ' | |||
|
1142 | 'from %s\n') | |||
|
1143 | % (rev, repo[rev], ', '.join('%d:%s' % (r, repo[r]) | |||
|
1144 | for r in unwantedrevs))) | |||
|
1145 | ||||
|
1146 | return newps[0], newps[1], base | |||
1096 |
|
1147 | |||
1097 | def isagitpatch(repo, patchname): |
|
1148 | def isagitpatch(repo, patchname): | |
1098 | 'Return true if the given patch is in git format' |
|
1149 | 'Return true if the given patch is in git format' |
@@ -31,8 +31,8 b' Source looks like "N"' | |||||
31 | AD: A':Z D':Z |
|
31 | AD: A':Z D':Z | |
32 | BD: B':Z D':B' |
|
32 | BD: B':Z D':B' | |
33 | ABD: A':Z B':Z D':B' |
|
33 | ABD: A':Z B':Z D':B' | |
34 | CD: CRASH: revlog index out of range |
|
34 | CD: ABORT: cannot use revision 3 as base, result would have 3 parents | |
35 |
ACD: A':Z C':A' |
|
35 | ACD: A':Z C':A'B D':Z | |
36 |
BCD: B |
|
36 | BCD: B':Z C':B'A D':B' | |
37 |
ABCD: A':Z |
|
37 | ABCD: A':Z B':Z C':A'B' D':B' | |
38 |
|
38 | |||
@@ -52,4 +52,4 b' Moving backwards' | |||||
52 | C: ABORT: cannot use revision 3 as base, result would have 3 parents |
|
52 | C: ABORT: cannot use revision 3 as base, result would have 3 parents | |
53 | BC: B':Z C':B'A |
|
53 | BC: B':Z C':B'A | |
54 | AC: |
|
54 | AC: | |
55 | BAC: ABORT: nothing to merge |
|
55 | BAC: B':Z C':B'A |
@@ -3,7 +3,7 b'' | |||||
3 | > usegeneraldelta=yes |
|
3 | > usegeneraldelta=yes | |
4 | > [extensions] |
|
4 | > [extensions] | |
5 | > rebase= |
|
5 | > rebase= | |
6 | > |
|
6 | > drawdag=$TESTDIR/drawdag.py | |
7 | > [alias] |
|
7 | > [alias] | |
8 | > tglog = log -G --template "{rev}: '{desc}' {branches}\n" |
|
8 | > tglog = log -G --template "{rev}: '{desc}' {branches}\n" | |
9 | > EOF |
|
9 | > EOF | |
@@ -334,3 +334,101 b' rebase of merge of ancestors' | |||||
334 | |/ |
|
334 | |/ | |
335 | o 0: 'common' |
|
335 | o 0: 'common' | |
336 |
|
336 | |||
|
337 | Due to the limitation of 3-way merge algorithm (1 merge base), rebasing a merge | |||
|
338 | may include unwanted content: | |||
|
339 | ||||
|
340 | $ hg init $TESTTMP/dual-merge-base1 | |||
|
341 | $ cd $TESTTMP/dual-merge-base1 | |||
|
342 | $ hg debugdrawdag <<'EOS' | |||
|
343 | > F | |||
|
344 | > /| | |||
|
345 | > D E | |||
|
346 | > | | | |||
|
347 | > B C | |||
|
348 | > |/ | |||
|
349 | > A Z | |||
|
350 | > |/ | |||
|
351 | > R | |||
|
352 | > EOS | |||
|
353 | $ hg rebase -r D+E+F -d Z | |||
|
354 | rebasing 5:5f2c926dfecf "D" (D) | |||
|
355 | rebasing 6:b296604d9846 "E" (E) | |||
|
356 | rebasing 7:caa9781e507d "F" (F tip) | |||
|
357 | warning: rebasing 7:caa9781e507d may include unwanted changes from 4:d6003a550c2c | |||
|
358 | saved backup bundle to $TESTTMP/dual-merge-base1/.hg/strip-backup/b296604d9846-0516f6d2-rebase.hg (glob) | |||
|
359 | $ hg log -r 4 -T '{files}\n' | |||
|
360 | C | |||
|
361 | $ hg manifest -r 'desc(F)' | |||
|
362 | C | |||
|
363 | D | |||
|
364 | E | |||
|
365 | R | |||
|
366 | Z | |||
|
367 | ||||
|
368 | The warning does not get printed if there is no unwanted change detected: | |||
|
369 | ||||
|
370 | $ hg init $TESTTMP/dual-merge-base2 | |||
|
371 | $ cd $TESTTMP/dual-merge-base2 | |||
|
372 | $ hg debugdrawdag <<'EOS' | |||
|
373 | > D | |||
|
374 | > /| | |||
|
375 | > B C | |||
|
376 | > |/ | |||
|
377 | > A Z | |||
|
378 | > |/ | |||
|
379 | > R | |||
|
380 | > EOS | |||
|
381 | $ hg rebase -r B+C+D -d Z | |||
|
382 | rebasing 3:c1e6b162678d "B" (B) | |||
|
383 | rebasing 4:d6003a550c2c "C" (C) | |||
|
384 | rebasing 5:c8f78076273e "D" (D tip) | |||
|
385 | saved backup bundle to $TESTTMP/dual-merge-base2/.hg/strip-backup/d6003a550c2c-6f1424b6-rebase.hg (glob) | |||
|
386 | $ hg manifest -r 'desc(D)' | |||
|
387 | B | |||
|
388 | C | |||
|
389 | R | |||
|
390 | Z | |||
|
391 | ||||
|
392 | The merge base could be different from old p1 (changed parent becomes new p1): | |||
|
393 | ||||
|
394 | $ hg init $TESTTMP/chosen-merge-base1 | |||
|
395 | $ cd $TESTTMP/chosen-merge-base1 | |||
|
396 | $ hg debugdrawdag <<'EOS' | |||
|
397 | > F | |||
|
398 | > /| | |||
|
399 | > D E | |||
|
400 | > | | | |||
|
401 | > B C Z | |||
|
402 | > EOS | |||
|
403 | $ hg rebase -r D+F -d Z | |||
|
404 | rebasing 3:004dc1679908 "D" (D) | |||
|
405 | rebasing 5:4be4cbf6f206 "F" (F tip) | |||
|
406 | saved backup bundle to $TESTTMP/chosen-merge-base1/.hg/strip-backup/004dc1679908-06a66a3c-rebase.hg (glob) | |||
|
407 | $ hg manifest -r 'desc(F)' | |||
|
408 | C | |||
|
409 | D | |||
|
410 | E | |||
|
411 | Z | |||
|
412 | $ hg log -r `hg log -r 'desc(F)' -T '{p1node}'` -T '{desc}\n' | |||
|
413 | D | |||
|
414 | ||||
|
415 | $ hg init $TESTTMP/chosen-merge-base2 | |||
|
416 | $ cd $TESTTMP/chosen-merge-base2 | |||
|
417 | $ hg debugdrawdag <<'EOS' | |||
|
418 | > F | |||
|
419 | > /| | |||
|
420 | > D E | |||
|
421 | > | | | |||
|
422 | > B C Z | |||
|
423 | > EOS | |||
|
424 | $ hg rebase -r E+F -d Z | |||
|
425 | rebasing 4:974e4943c210 "E" (E) | |||
|
426 | rebasing 5:4be4cbf6f206 "F" (F tip) | |||
|
427 | saved backup bundle to $TESTTMP/chosen-merge-base2/.hg/strip-backup/974e4943c210-b2874da5-rebase.hg (glob) | |||
|
428 | $ hg manifest -r 'desc(F)' | |||
|
429 | B | |||
|
430 | D | |||
|
431 | E | |||
|
432 | Z | |||
|
433 | $ hg log -r `hg log -r 'desc(F)' -T '{p1node}'` -T '{desc}\n' | |||
|
434 | E |
@@ -488,9 +488,14 b' Detach both parents' | |||||
488 | > A |
|
488 | > A | |
489 | > EOF |
|
489 | > EOF | |
490 |
|
490 | |||
491 | BROKEN: This raises an exception |
|
491 | $ hg rebase -d G -r 'B + D + F' | |
492 | $ hg rebase -d G -r 'B + D + F' 2>&1 | grep '^AssertionError' |
|
492 | rebasing 1:112478962961 "B" (B) | |
493 | AssertionError: no base found to rebase on (defineparents called wrong) |
|
493 | rebasing 2:b18e25de2cf5 "D" (D) | |
|
494 | not rebasing ignored 4:26805aba1e60 "C" (C) | |||
|
495 | not rebasing ignored 5:4b61ff5c62e2 "E" (E) | |||
|
496 | rebasing 6:f15c3adaf214 "F" (F tip) | |||
|
497 | abort: cannot use revision 6 as base, result would have 3 parents | |||
|
498 | [255] | |||
494 |
|
499 | |||
495 |
$ |
|
500 | $ cd .. | |
496 |
|
501 | |||
@@ -962,17 +967,19 b' Rebase merge where successor of other pa' | |||||
962 | > A |
|
967 | > A | |
963 | > EOF |
|
968 | > EOF | |
964 |
|
969 | |||
965 | BROKEN: Raises an exception |
|
970 | $ hg rebase -d B -s E | |
966 | $ hg rebase -d B -s E 2>&1 | grep AssertionError: |
|
971 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" | |
967 | AssertionError: no base found to rebase on (defineparents called wrong) |
|
972 | rebasing 4:66f1a38021c9 "F" (F tip) | |
968 | $ hg log -G |
|
973 | $ hg log -G | |
969 | o 4:66f1a38021c9 F |
|
974 | o 5:aae1787dacee F | |
970 | |\ |
|
975 | |\ | |
971 | | x 3:7fb047a69f22 E |
|
976 | | | x 4:66f1a38021c9 F | |
972 | | | |
|
977 | | |/| | |
973 | o | 2:b18e25de2cf5 D |
|
978 | | | x 3:7fb047a69f22 E | |
974 | |/ |
|
979 | | | | | |
975 | | o 1:112478962961 B |
|
980 | | o | 2:b18e25de2cf5 D | |
|
981 | | |/ | |||
|
982 | o / 1:112478962961 B | |||
976 | |/ |
|
983 | |/ | |
977 | o 0:426bada5c675 A |
|
984 | o 0:426bada5c675 A | |
978 |
|
985 | |||
@@ -994,19 +1001,19 b' Rebase merge where successor of one pare' | |||||
994 | $ hg rebase -d C -s D |
|
1001 | $ hg rebase -d C -s D | |
995 | note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" |
|
1002 | note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" | |
996 | rebasing 5:66f1a38021c9 "F" (F tip) |
|
1003 | rebasing 5:66f1a38021c9 "F" (F tip) | |
997 | BROKEN: not rebased on top of requested destination (C) |
|
1004 | ||
998 | $ hg log -G |
|
1005 | $ hg log -G | |
999 |
o 6: |
|
1006 | o 6:0913febf6439 F | |
1000 | |\ |
|
1007 | |\ | |
1001 |
|
|
1008 | +---x 5:66f1a38021c9 F | |
1002 |
| | |
|
1009 | | | | | |
1003 |
|
|
1010 | | o | 4:26805aba1e60 C | |
1004 | | | | |
|
1011 | | | | | |
1005 |
| |
|
1012 | o | | 3:7fb047a69f22 E | |
1006 | | | | |
|
1013 | | | | | |
1007 |
|
|
1014 | +---x 2:b18e25de2cf5 D | |
1008 |
| | |
|
1015 | | | | |
1009 |
o |
|
1016 | | o 1:112478962961 B | |
1010 | |/ |
|
1017 | |/ | |
1011 | o 0:426bada5c675 A |
|
1018 | o 0:426bada5c675 A | |
1012 |
|
1019 | |||
@@ -1025,19 +1032,21 b' Rebase merge where successor of other pa' | |||||
1025 | > A |
|
1032 | > A | |
1026 | > EOF |
|
1033 | > EOF | |
1027 |
|
1034 | |||
1028 | BROKEN: Raises an exception |
|
1035 | $ hg rebase -d C -s E | |
1029 | $ hg rebase -d C -s E 2>&1 | grep AssertionError: |
|
1036 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" | |
1030 | AssertionError: no base found to rebase on (defineparents called wrong) |
|
1037 | rebasing 5:66f1a38021c9 "F" (F tip) | |
1031 | $ hg log -G |
|
1038 | $ hg log -G | |
1032 | o 5:66f1a38021c9 F |
|
1039 | o 6:c6ab0cc6d220 F | |
1033 | |\ |
|
1040 | |\ | |
1034 | | | o 4:26805aba1e60 C |
|
1041 | +---x 5:66f1a38021c9 F | |
1035 | | | | |
|
1042 | | | | | |
1036 | | x | 3:7fb047a69f22 E |
|
1043 | | o | 4:26805aba1e60 C | |
1037 | | | | |
|
1044 | | | | | |
1038 | o | | 2:b18e25de2cf5 D |
|
1045 | | | x 3:7fb047a69f22 E | |
1039 |
| |
|
1046 | | | | | |
1040 | | o 1:112478962961 B |
|
1047 | o---+ 2:b18e25de2cf5 D | |
|
1048 | / / | |||
|
1049 | o / 1:112478962961 B | |||
1041 | |/ |
|
1050 | |/ | |
1042 | o 0:426bada5c675 A |
|
1051 | o 0:426bada5c675 A | |
1043 |
|
1052 | |||
@@ -1060,6 +1069,7 b' Rebase merge where successor of one pare' | |||||
1060 | rebasing 2:b18e25de2cf5 "D" (D) |
|
1069 | rebasing 2:b18e25de2cf5 "D" (D) | |
1061 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" |
|
1070 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" | |
1062 | rebasing 5:66f1a38021c9 "F" (F tip) |
|
1071 | rebasing 5:66f1a38021c9 "F" (F tip) | |
|
1072 | warning: rebasing 5:66f1a38021c9 may include unwanted changes from 3:7fb047a69f22 | |||
1063 |
|
|
1073 | $ hg log -G | |
1064 | o 7:9ed45af61fa0 F |
|
1074 | o 7:9ed45af61fa0 F | |
1065 | | |
|
1075 | | | |
@@ -1096,13 +1106,13 b' Rebase merge where successor of other pa' | |||||
1096 | note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" |
|
1106 | note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" | |
1097 | rebasing 3:7fb047a69f22 "E" (E) |
|
1107 | rebasing 3:7fb047a69f22 "E" (E) | |
1098 | rebasing 5:66f1a38021c9 "F" (F tip) |
|
1108 | rebasing 5:66f1a38021c9 "F" (F tip) | |
1099 | BROKEN: This should have resulted in a rebased F with one parent, just like in |
|
1109 | warning: rebasing 5:66f1a38021c9 may include unwanted changes from 2:b18e25de2cf5 | |
1100 | the test case above |
|
1110 | ||
1101 | $ hg log -G |
|
1111 | $ hg log -G | |
1102 | o 7:c1e6f26e339d F |
|
1112 | o 7:502540f44880 F | |
1103 |
| |
|
1113 | | | |
1104 |
|
|
1114 | o 6:533690786a86 E | |
1105 |
| |
|
1115 | | | |
1106 | | x 5:66f1a38021c9 F |
|
1116 | | x 5:66f1a38021c9 F | |
1107 | | |\ |
|
1117 | | |\ | |
1108 | o | | 4:26805aba1e60 C |
|
1118 | o | | 4:26805aba1e60 C |
General Comments 0
You need to be logged in to leave comments.
Login now