##// END OF EJS Templates
rebase: rewrite core algorithm (issue5578) (issue5630)...
Jun Wu -
r33783:09755061 default
parent child Browse files
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]
1001
987
1002 p1n = parents[0].rev()
988 def defineparents(repo, rev, dest, state):
1003 if p1n in destancestors:
989 """Return new parents and optionally a merge base for rev being rebased
1004 p1 = dest
990
1005 elif p1n in state:
991 The destination specified by "dest" cannot always be used directly because
1006 if state[p1n] == nullmerge:
992 previously rebase result could affect destination. For example,
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 p1 = dest
1016 p2 = p1n
1017
993
1018 if len(parents) == 2 and parents[1].rev() not in destancestors:
994 D E rebase -r C+D+E -d B
1019 p2n = parents[1].rev()
995 |/ C will be rebased to C'
1020 # interesting second parent
996 B C D's new destination will be C' instead of B
1021 if p2n in state:
997 |/ E's new destination will be C' instead of B
1022 if p1 == dest: # p1n in destancestors or external
998 A
1023 p1 = state[p2n]
999
1024 if p1 == revprecursor:
1000 The new parents of a merge is slightly more complicated. See the comment
1025 rp1 = obsoletenotrebased[p2n]
1001 block below.
1026 elif state[p2n] in revskipped:
1002 """
1027 p2 = nearestrebased(repo, p2n, state)
1003 cl = repo.changelog
1028 if p2 is None:
1004 def isancestor(a, b):
1029 # no ancestors rebased yet, detach
1005 # take revision numbers instead of nodes
1030 p2 = dest
1006 if a == b:
1031 else:
1007 return True
1032 p2 = state[p2n]
1008 elif a > b:
1033 else: # p2n external
1009 return False
1034 if p2 != nullrev: # p1n external too => rev is a merged revision
1010 return cl.isancestor(cl.node(a), cl.node(b))
1035 raise error.Abort(_('cannot use revision %d as base, result '
1011
1036 'would have 3 parents') % rev)
1012 oldps = repo.changelog.parentrevs(rev) # old parents
1037 p2 = p2n
1013 newps = [nullrev, nullrev] # new parents
1038 repo.ui.debug(" future parents are %d and %d\n" %
1014 dests = adjustdest(repo, rev, dest, state) # adjusted destinations
1039 (repo[rp1 or p1].rev(), repo[p2].rev()))
1015 bases = list(oldps) # merge base candidates, initially just old parents
1040
1016
1041 if not any(p.rev() in state for p in parents):
1017 if all(r == nullrev for r in oldps[1:]):
1042 # Case (1) root changeset of a non-detaching rebase set.
1018 # For non-merge changeset, just move p to adjusted dest as requested.
1043 # Let the merge mechanism find the base itself.
1019 newps[0] = dests[0]
1044 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:
1020 else:
1049 # Assuming there is a p1, this is the case where there also is a p2.
1021 # For merge changeset, if we move p to dests[i] unconditionally, both
1050 # We are thus rebasing a merge and need to pick the right merge base.
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:
1051 #
1036 #
1052 # Imagine we have:
1037 # C # "rebase -r C -d D" is an error since none of the parents
1053 # - M: current rebase revision in this step
1038 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1054 # - A: one parent of M
1039 # A B D # B (using rule "2."), since B will be rebased.
1055 # - B: other parent of M
1056 # - D: destination of this merge step (p1 var)
1057 #
1040 #
1058 # Consider the case where D is a descendant of A or B and the other is
1041 # The loop tries to be not rely on the fact that a Mercurial node has
1059 # 'outside'. In this case, the right merge base is the D ancestor.
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]
1049
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:
1060 #
1053 #
1061 # An informal proof, assuming A is 'outside' and B is the D ancestor:
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.
1062 #
1060 #
1063 # If we pick B as the base, the merge involves:
1061 # Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8
1064 # - changes from B to M (actual changeset payload)
1062 # which uses "virtual null merge" to explain this situation.
1065 # - changes from B to D (induced by rebase) as D is a rebased
1063 if isancestor(p, np):
1066 # version of B)
1064 bases[i] = nullrev
1067 # Which exactly represent the rebase operation.
1065
1068 #
1066 # If one parent becomes an ancestor of the other, drop the ancestor
1069 # If we pick A as the base, the merge involves:
1067 for j, x in enumerate(newps[:i]):
1070 # - changes from A to M (actual changeset payload)
1068 if x == nullrev:
1071 # - changes from A to D (with include changes between unrelated A and B
1069 continue
1072 # plus changes induced by rebase)
1070 if isancestor(np, x):
1073 # Which does not represent anything sensible and creates a lot of
1071 np = nullrev
1074 # conflicts. A is thus not the right choice - B is.
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:
1075 #
1089 #
1076 # Note: The base found in this 'proof' is only correct in the specified
1090 # C # rebase -r C -d D
1077 # case. This base does not make sense if is not D a descendant of A or B
1091 # /| # None of A and B will be changed to D and rebase fails.
1078 # or if the other is not parent 'outside' (especially not if the other
1092 # A B D
1079 # parent has been rebased). The current implementation does not
1093 if set(newps) == set(oldps) and dest not in newps:
1080 # make it feasible to consider different cases separately. In these
1094 # The error message is for compatibility. It's a bit misleading
1081 # other cases we currently just leave it to the user to correctly
1095 # since rebase is not supposed to add new parents.
1082 # resolve an impossible merge using a wrong ancestor.
1096 raise error.Abort(_('cannot use revision %d as base, '
1083 #
1097 'result would have 3 parents') % rev)
1084 # xx, p1 could be -4, and both parents could probably be -4...
1098
1085 for p in repo[rev].parents():
1099 repo.ui.debug(" future parents are %d and %d\n" % tuple(newps))
1086 if state.get(p.rev()) == p1:
1100
1087 base = p.rev()
1101 # "rebasenode" updates to new p1, use the corresponding merge base.
1088 break
1102 if bases[0] != nullrev:
1089 else: # fallback when base not found
1103 base = bases[0]
1104 else:
1090 base = None
1105 base = None
1091
1106
1092 # Raise because this function is called wrong (see issue 4106)
1107 # Check if the merge will contain unwanted changes. That may happen if
1093 raise AssertionError('no base found to rebase on '
1108 # there are multiple special (non-changelog ancestor) merge bases, which
1094 '(defineparents called wrong)')
1109 # cannot be handled well by the 3-way merge algorithm. For example:
1095 return rp1 or p1, p2, base
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
1124
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 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'A' D':Z
35 ACD: A':Z C':A'B D':Z
36 BCD: B':Z C':B'A D':B'
36 BCD: B':Z C':B'A D':B'
37 ABCD: A':Z B':Z C':A'B' D':B'
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 $ cd ..
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:50e9d60b99c6 F
1006 o 6:0913febf6439 F
1000 |\
1007 |\
1001 | | x 5:66f1a38021c9 F
1008 +---x 5:66f1a38021c9 F
1002 | |/|
1009 | | |
1003 +-----o 4:26805aba1e60 C
1010 | o | 4:26805aba1e60 C
1004 | | |
1011 | | |
1005 | o | 3:7fb047a69f22 E
1012 o | | 3:7fb047a69f22 E
1006 | | |
1013 | | |
1007 | | x 2:b18e25de2cf5 D
1014 +---x 2:b18e25de2cf5 D
1008 | |/
1015 | |
1009 o | 1:112478962961 B
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 $ hg log -G
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 | o 6:533690786a86 E
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