Show More
@@ -66,7 +66,6 b' revignored = -3' | |||
|
66 | 66 | revprecursor = -4 |
|
67 | 67 | # plain prune (no successor) |
|
68 | 68 | revpruned = -5 |
|
69 | revskipped = (revignored, revprecursor, revpruned) | |
|
70 | 69 | |
|
71 | 70 | cmdtable = {} |
|
72 | 71 | command = registrar.command(cmdtable) |
@@ -390,10 +389,7 b' class rebaseruntime(object):' | |||
|
390 | 389 | ui.status(_('rebasing %s\n') % desc) |
|
391 | 390 | ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)), |
|
392 | 391 | _('changesets'), total) |
|
393 | p1, p2, base = defineparents(repo, rev, self.dest, | |
|
394 | self.state, | |
|
395 | self.destancestors, | |
|
396 | self.obsoletenotrebased) | |
|
392 | p1, p2, base = defineparents(repo, rev, self.dest, self.state) | |
|
397 | 393 | self.storestatus(tr=tr) |
|
398 | 394 | storecollapsemsg(repo, self.collapsemsg) |
|
399 | 395 | if len(repo[None].parents()) == 2: |
@@ -463,9 +459,7 b' class rebaseruntime(object):' | |||
|
463 | 459 | repo, ui, opts = self.repo, self.ui, self.opts |
|
464 | 460 | if self.collapsef and not self.keepopen: |
|
465 | 461 | p1, p2, _base = defineparents(repo, min(self.state), |
|
466 |
self.dest, self.state |
|
|
467 | self.destancestors, | |
|
468 | self.obsoletenotrebased) | |
|
462 | self.dest, self.state) | |
|
469 | 463 | editopt = opts.get('edit') |
|
470 | 464 | editform = 'rebase.collapse' |
|
471 | 465 | if self.collapsemsg: |
@@ -960,15 +954,6 b' def adjustdest(repo, rev, dest, state):' | |||
|
960 | 954 | result.append(adjusted) |
|
961 | 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 | 957 | def _checkobsrebase(repo, ui, rebaseobsrevs, rebasesetrevs, rebaseobsskipped): |
|
973 | 958 | """ |
|
974 | 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 | 977 | "experimental.allowdivergence=True") |
|
993 | 978 | raise error.Abort(msg % (",".join(divhashes),), hint=h) |
|
994 | 979 | |
|
995 | def defineparents(repo, rev, dest, state, destancestors, | |
|
996 | obsoletenotrebased): | |
|
997 | 'Return the new parent relationship of the revision that will be rebased' | |
|
998 | parents = repo[rev].parents() | |
|
999 | p1 = p2 = nullrev | |
|
1000 | rp1 = None | |
|
980 | def successorrevs(repo, rev): | |
|
981 | """yield revision numbers for successors of rev""" | |
|
982 | unfi = repo.unfiltered() | |
|
983 | nodemap = unfi.changelog.nodemap | |
|
984 | for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]): | |
|
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() | |
|
1003 | if p1n in destancestors: | |
|
1004 | p1 = dest | |
|
1005 | elif p1n in state: | |
|
1006 | if state[p1n] == nullmerge: | |
|
1007 | p1 = dest | |
|
1008 | elif state[p1n] in revskipped: | |
|
1009 | p1 = nearestrebased(repo, p1n, state) | |
|
1010 | if p1 is None: | |
|
1011 | p1 = dest | |
|
1012 | else: | |
|
1013 | p1 = state[p1n] | |
|
1014 | else: # p1n external | |
|
1015 |
|
|
|
1016 | p2 = p1n | |
|
994 | D E rebase -r C+D+E -d B | |
|
995 | |/ C will be rebased to C' | |
|
996 | B C D's new destination will be C' instead of B | |
|
997 | |/ E's new destination will be C' instead of B | |
|
998 | A | |
|
999 | ||
|
1000 | The new parents of a merge is slightly more complicated. See the comment | |
|
1001 | block below. | |
|
1002 | """ | |
|
1003 | cl = repo.changelog | |
|
1004 | def isancestor(a, b): | |
|
1005 | # take revision numbers instead of nodes | |
|
1006 | if a == b: | |
|
1007 | return True | |
|
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: | |
|
1019 | p2n = parents[1].rev() | |
|
1020 | # interesting second parent | |
|
1021 | if p2n in state: | |
|
1022 | if p1 == dest: # p1n in destancestors or external | |
|
1023 | p1 = state[p2n] | |
|
1024 | if p1 == revprecursor: | |
|
1025 | rp1 = obsoletenotrebased[p2n] | |
|
1026 | elif state[p2n] in revskipped: | |
|
1027 | p2 = nearestrebased(repo, p2n, state) | |
|
1028 | if p2 is None: | |
|
1029 | # no ancestors rebased yet, detach | |
|
1030 | p2 = dest | |
|
1031 | else: | |
|
1032 | p2 = state[p2n] | |
|
1033 | else: # p2n external | |
|
1034 | if p2 != nullrev: # p1n external too => rev is a merged revision | |
|
1035 | raise error.Abort(_('cannot use revision %d as base, result ' | |
|
1036 | 'would have 3 parents') % rev) | |
|
1037 | p2 = p2n | |
|
1038 | repo.ui.debug(" future parents are %d and %d\n" % | |
|
1039 | (repo[rp1 or p1].rev(), repo[p2].rev())) | |
|
1017 | if all(r == nullrev for r in oldps[1:]): | |
|
1018 | # For non-merge changeset, just move p to adjusted dest as requested. | |
|
1019 | newps[0] = dests[0] | |
|
1020 | else: | |
|
1021 | # For merge changeset, if we move p to dests[i] unconditionally, both | |
|
1022 | # parents may change and the end result looks like "the merge loses a | |
|
1023 | # parent", which is a surprise. This is a limit because "--dest" only | |
|
1024 | # accepts one dest per src. | |
|
1025 | # | |
|
1026 | # Therefore, only move p with reasonable conditions (in this order): | |
|
1027 | # 1. use dest, if dest is a descendent of (p or one of p's successors) | |
|
1028 | # 2. use p's rebased result, if p is rebased (state[p] > 0) | |
|
1029 | # | |
|
1030 | # Comparing with adjustdest, the logic here does some additional work: | |
|
1031 | # 1. decide which parents will not be moved towards dest | |
|
1032 | # 2. if the above decision is "no", should a parent still be moved | |
|
1033 | # because it was rebased? | |
|
1034 | # | |
|
1035 | # For example: | |
|
1036 | # | |
|
1037 | # C # "rebase -r C -d D" is an error since none of the parents | |
|
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): | |
|
1042 | # Case (1) root changeset of a non-detaching rebase set. | |
|
1043 | # Let the merge mechanism find the base itself. | |
|
1050 | # "bases" only record "special" merge bases that cannot be | |
|
1051 | # calculated from changelog DAG (i.e. isancestor(p, np) is False). | |
|
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 | 1105 | base = None |
|
1045 | elif not repo[rev].p2(): | |
|
1046 | # Case (2) detaching the node with a single parent, use this parent | |
|
1047 | base = repo[rev].p1().rev() | |
|
1048 | else: | |
|
1049 | # Assuming there is a p1, this is the case where there also is a p2. | |
|
1050 | # We are thus rebasing a merge and need to pick the right merge base. | |
|
1051 | # | |
|
1052 | # Imagine we have: | |
|
1053 | # - M: current rebase revision in this step | |
|
1054 | # - A: one parent of M | |
|
1055 | # - B: other parent of M | |
|
1056 | # - D: destination of this merge step (p1 var) | |
|
1057 |
|
|
|
1058 | # Consider the case where D is a descendant of A or B and the other is | |
|
1059 | # 'outside'. In this case, the right merge base is the D ancestor. | |
|
1060 | # | |
|
1061 | # An informal proof, assuming A is 'outside' and B is the D ancestor: | |
|
1062 | # | |
|
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 | |
|
1106 | ||
|
1107 | # Check if the merge will contain unwanted changes. That may happen if | |
|
1108 | # there are multiple special (non-changelog ancestor) merge bases, which | |
|
1109 | # cannot be handled well by the 3-way merge algorithm. For example: | |
|
1110 | # | |
|
1111 | # F | |
|
1112 | # /| | |
|
1113 | # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen | |
|
1114 | # | | # as merge base, the difference between D and F will include | |
|
1115 | # B C # C, so the rebased F will contain C surprisingly. If "E" was | |
|
1116 | # |/ # chosen, the rebased F will contain B. | |
|
1117 | # A Z | |
|
1118 | # | |
|
1119 | # But our merge base candidates (D and E in above case) could still be | |
|
1120 | # better than the default (ancestor(F, Z) == null). Therefore still | |
|
1121 | # pick one (so choose p1 above). | |
|
1122 | if sum(1 for b in bases if b != nullrev) > 1: | |
|
1123 | assert base is not None | |
|
1091 | 1124 | |
|
1092 | # Raise because this function is called wrong (see issue 4106) | |
|
1093 | raise AssertionError('no base found to rebase on ' | |
|
1094 | '(defineparents called wrong)') | |
|
1095 | return rp1 or p1, p2, base | |
|
1125 | # Revisions in the side (not chosen as merge base) branch that might | |
|
1126 | # contain "surprising" contents | |
|
1127 | siderevs = list(repo.revs('((%ld-%d) %% (%d+%d))', | |
|
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 | 1148 | def isagitpatch(repo, patchname): |
|
1098 | 1149 | 'Return true if the given patch is in git format' |
@@ -31,8 +31,8 b' Source looks like "N"' | |||
|
31 | 31 | AD: A':Z D':Z |
|
32 | 32 | BD: B':Z D':B' |
|
33 | 33 | ABD: A':Z B':Z D':B' |
|
34 | CD: CRASH: revlog index out of range | |
|
35 |
ACD: A':Z C':A' |
|
|
34 | CD: ABORT: cannot use revision 3 as base, result would have 3 parents | |
|
35 | ACD: A':Z C':A'B D':Z | |
|
36 | 36 |
BCD: B |
|
37 | 37 |
ABCD: A':Z |
|
38 | 38 | |
@@ -52,4 +52,4 b' Moving backwards' | |||
|
52 | 52 | C: ABORT: cannot use revision 3 as base, result would have 3 parents |
|
53 | 53 | BC: B':Z C':B'A |
|
54 | 54 | AC: |
|
55 | BAC: ABORT: nothing to merge | |
|
55 | BAC: B':Z C':B'A |
@@ -3,7 +3,7 b'' | |||
|
3 | 3 | > usegeneraldelta=yes |
|
4 | 4 | > [extensions] |
|
5 | 5 | > rebase= |
|
6 | > | |
|
6 | > drawdag=$TESTDIR/drawdag.py | |
|
7 | 7 | > [alias] |
|
8 | 8 | > tglog = log -G --template "{rev}: '{desc}' {branches}\n" |
|
9 | 9 | > EOF |
@@ -334,3 +334,101 b' rebase of merge of ancestors' | |||
|
334 | 334 | |/ |
|
335 | 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 | 488 | > A |
|
489 | 489 | > EOF |
|
490 | 490 | |
|
491 | BROKEN: This raises an exception | |
|
492 | $ hg rebase -d G -r 'B + D + F' 2>&1 | grep '^AssertionError' | |
|
493 | AssertionError: no base found to rebase on (defineparents called wrong) | |
|
491 | $ hg rebase -d G -r 'B + D + F' | |
|
492 | rebasing 1:112478962961 "B" (B) | |
|
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 |
$ |
|
496 | 501 | |
@@ -962,17 +967,19 b' Rebase merge where successor of other pa' | |||
|
962 | 967 | > A |
|
963 | 968 | > EOF |
|
964 | 969 | |
|
965 | BROKEN: Raises an exception | |
|
966 | $ hg rebase -d B -s E 2>&1 | grep AssertionError: | |
|
967 | AssertionError: no base found to rebase on (defineparents called wrong) | |
|
970 | $ hg rebase -d B -s E | |
|
971 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" | |
|
972 | rebasing 4:66f1a38021c9 "F" (F tip) | |
|
968 | 973 | $ hg log -G |
|
969 | o 4:66f1a38021c9 F | |
|
974 | o 5:aae1787dacee F | |
|
970 | 975 | |\ |
|
971 | | x 3:7fb047a69f22 E | |
|
972 | | | | |
|
973 | o | 2:b18e25de2cf5 D | |
|
974 | |/ | |
|
975 | | o 1:112478962961 B | |
|
976 | | | x 4:66f1a38021c9 F | |
|
977 | | |/| | |
|
978 | | | x 3:7fb047a69f22 E | |
|
979 | | | | | |
|
980 | | o | 2:b18e25de2cf5 D | |
|
981 | | |/ | |
|
982 | o / 1:112478962961 B | |
|
976 | 983 | |/ |
|
977 | 984 | o 0:426bada5c675 A |
|
978 | 985 | |
@@ -994,19 +1001,19 b' Rebase merge where successor of one pare' | |||
|
994 | 1001 | $ hg rebase -d C -s D |
|
995 | 1002 | note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" |
|
996 | 1003 | rebasing 5:66f1a38021c9 "F" (F tip) |
|
997 | BROKEN: not rebased on top of requested destination (C) | |
|
1004 | ||
|
998 | 1005 | $ hg log -G |
|
999 |
o 6: |
|
|
1006 | o 6:0913febf6439 F | |
|
1000 | 1007 | |\ |
|
1001 |
|
|
|
1002 |
| | |
|
|
1003 |
|
|
|
1008 | +---x 5:66f1a38021c9 F | |
|
1009 | | | | | |
|
1010 | | o | 4:26805aba1e60 C | |
|
1004 | 1011 | | | | |
|
1005 |
| |
|
|
1012 | o | | 3:7fb047a69f22 E | |
|
1006 | 1013 | | | | |
|
1007 |
|
|
|
1008 |
| | |
|
|
1009 |
o |
|
|
1014 | +---x 2:b18e25de2cf5 D | |
|
1015 | | | | |
|
1016 | | o 1:112478962961 B | |
|
1010 | 1017 | |/ |
|
1011 | 1018 | o 0:426bada5c675 A |
|
1012 | 1019 | |
@@ -1025,19 +1032,21 b' Rebase merge where successor of other pa' | |||
|
1025 | 1032 | > A |
|
1026 | 1033 | > EOF |
|
1027 | 1034 | |
|
1028 | BROKEN: Raises an exception | |
|
1029 | $ hg rebase -d C -s E 2>&1 | grep AssertionError: | |
|
1030 | AssertionError: no base found to rebase on (defineparents called wrong) | |
|
1035 | $ hg rebase -d C -s E | |
|
1036 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" | |
|
1037 | rebasing 5:66f1a38021c9 "F" (F tip) | |
|
1031 | 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 | |
|
1039 |
| |
|
|
1040 | | o 1:112478962961 B | |
|
1045 | | | x 3:7fb047a69f22 E | |
|
1046 | | | | | |
|
1047 | o---+ 2:b18e25de2cf5 D | |
|
1048 | / / | |
|
1049 | o / 1:112478962961 B | |
|
1041 | 1050 | |/ |
|
1042 | 1051 | o 0:426bada5c675 A |
|
1043 | 1052 | |
@@ -1060,6 +1069,7 b' Rebase merge where successor of one pare' | |||
|
1060 | 1069 | rebasing 2:b18e25de2cf5 "D" (D) |
|
1061 | 1070 | note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" |
|
1062 | 1071 | rebasing 5:66f1a38021c9 "F" (F tip) |
|
1072 | warning: rebasing 5:66f1a38021c9 may include unwanted changes from 3:7fb047a69f22 | |
|
1063 | 1073 |
|
|
1064 | 1074 | o 7:9ed45af61fa0 F |
|
1065 | 1075 | | |
@@ -1096,13 +1106,13 b' Rebase merge where successor of other pa' | |||
|
1096 | 1106 | note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" |
|
1097 | 1107 | rebasing 3:7fb047a69f22 "E" (E) |
|
1098 | 1108 | rebasing 5:66f1a38021c9 "F" (F tip) |
|
1099 | BROKEN: This should have resulted in a rebased F with one parent, just like in | |
|
1100 | the test case above | |
|
1109 | warning: rebasing 5:66f1a38021c9 may include unwanted changes from 2:b18e25de2cf5 | |
|
1110 | ||
|
1101 | 1111 | $ hg log -G |
|
1102 | o 7:c1e6f26e339d F | |
|
1103 |
| |
|
|
1104 |
|
|
|
1105 |
| |
|
|
1112 | o 7:502540f44880 F | |
|
1113 | | | |
|
1114 | o 6:533690786a86 E | |
|
1115 | | | |
|
1106 | 1116 | | x 5:66f1a38021c9 F |
|
1107 | 1117 | | |\ |
|
1108 | 1118 | o | | 4:26805aba1e60 C |
General Comments 0
You need to be logged in to leave comments.
Login now