##// 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]
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 p1 = dest
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'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