##// END OF EJS Templates
rebase: allow rebase even if some revisions need no rebase (BC) (issue5422)...
Martin von Zweigbergk -
r32272:78496ac3 default
parent child Browse files
Show More
@@ -0,0 +1,95 b''
1 Tests rebasing with part of the rebase set already in the
2 destination (issue5422)
3
4 $ cat >> $HGRCPATH <<EOF
5 > [extensions]
6 > rebase=
7 > drawdag=$TESTDIR/drawdag.py
8 >
9 > [experimental]
10 > evolution=createmarkers,allowunstable
11 >
12 > [alias]
13 > tglog = log -G --template "{rev}: {desc}"
14 > EOF
15
16 $ rebasewithdag() {
17 > N=`$PYTHON -c "print($N+1)"`
18 > hg init repo$N && cd repo$N
19 > hg debugdrawdag
20 > hg rebase "$@" > _rebasetmp
21 > r=$?
22 > grep -v 'saved backup bundle' _rebasetmp
23 > [ $r -eq 0 ] && hg tglog
24 > cd ..
25 > return $r
26 > }
27
28 Rebase two commits, of which one is already in the right place
29
30 $ rebasewithdag -r C+D -d B <<EOF
31 > C
32 > |
33 > B D
34 > |/
35 > A
36 > EOF
37 rebasing 2:b18e25de2cf5 "D" (D)
38 already rebased 3:26805aba1e60 "C" (C tip)
39 o 4: D
40 |
41 | o 3: C
42 |/
43 | x 2: D
44 | |
45 o | 1: B
46 |/
47 o 0: A
48
49 Can collapse commits even if one is already in the right place
50
51 $ rebasewithdag --collapse -r C+D -d B <<EOF
52 > C
53 > |
54 > B D
55 > |/
56 > A
57 > EOF
58 rebasing 2:b18e25de2cf5 "D" (D)
59 rebasing 3:26805aba1e60 "C" (C tip)
60 o 4: Collapsed revision
61 | * D
62 | * C
63 | x 3: C
64 |/
65 | x 2: D
66 | |
67 o | 1: B
68 |/
69 o 0: A
70
71 Rebase with "holes". The commits after the hole should end up on the parent of
72 the hole (B below), not on top of the destination (A).
73
74 $ rebasewithdag -r B+D -d A <<EOF
75 > D
76 > |
77 > C
78 > |
79 > B
80 > |
81 > A
82 > EOF
83 already rebased 1:112478962961 "B" (B)
84 not rebasing ignored 2:26805aba1e60 "C" (C)
85 rebasing 3:f585351a92f8 "D" (D tip)
86 o 4: D
87 |
88 | x 3: D
89 | |
90 | o 2: C
91 |/
92 o 1: B
93 |
94 o 0: A
95
@@ -384,7 +384,9 b' class rebaseruntime(object):'
384 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
384 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
385 if names:
385 if names:
386 desc += ' (%s)' % ' '.join(names)
386 desc += ' (%s)' % ' '.join(names)
387 if self.state[rev] == revtodo:
387 if self.state[rev] == rev:
388 ui.status(_('already rebased %s\n') % desc)
389 elif self.state[rev] == revtodo:
388 pos += 1
390 pos += 1
389 ui.status(_('rebasing %s\n') % desc)
391 ui.status(_('rebasing %s\n') % desc)
390 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
392 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
@@ -508,7 +510,7 b' class rebaseruntime(object):'
508 # Nodeids are needed to reset bookmarks
510 # Nodeids are needed to reset bookmarks
509 nstate = {}
511 nstate = {}
510 for k, v in self.state.iteritems():
512 for k, v in self.state.iteritems():
511 if v > nullmerge:
513 if v > nullmerge and v != k:
512 nstate[repo[k].node()] = repo[v].node()
514 nstate[repo[k].node()] = repo[v].node()
513 elif v == revprecursor:
515 elif v == revprecursor:
514 succ = self.obsoletenotrebased[k]
516 succ = self.obsoletenotrebased[k]
@@ -1248,6 +1250,7 b' def buildstate(repo, dest, rebaseset, co'
1248 roots.sort()
1250 roots.sort()
1249 state = dict.fromkeys(rebaseset, revtodo)
1251 state = dict.fromkeys(rebaseset, revtodo)
1250 detachset = set()
1252 detachset = set()
1253 emptyrebase = True
1251 for root in roots:
1254 for root in roots:
1252 commonbase = root.ancestor(dest)
1255 commonbase = root.ancestor(dest)
1253 if commonbase == root:
1256 if commonbase == root:
@@ -1260,9 +1263,13 b' def buildstate(repo, dest, rebaseset, co'
1260 else:
1263 else:
1261 samebranch = root.branch() == dest.branch()
1264 samebranch = root.branch() == dest.branch()
1262 if not collapse and samebranch and root in dest.children():
1265 if not collapse and samebranch and root in dest.children():
1266 # mark the revision as done by setting its new revision
1267 # equal to its old (current) revisions
1268 state[root.rev()] = root.rev()
1263 repo.ui.debug('source is a child of destination\n')
1269 repo.ui.debug('source is a child of destination\n')
1264 return None
1270 continue
1265
1271
1272 emptyrebase = False
1266 repo.ui.debug('rebase onto %s starting from %s\n' % (dest, root))
1273 repo.ui.debug('rebase onto %s starting from %s\n' % (dest, root))
1267 # Rebase tries to turn <dest> into a parent of <root> while
1274 # Rebase tries to turn <dest> into a parent of <root> while
1268 # preserving the number of parents of rebased changesets:
1275 # preserving the number of parents of rebased changesets:
@@ -1305,6 +1312,13 b' def buildstate(repo, dest, rebaseset, co'
1305 # ancestors of <root> not ancestors of <dest>
1312 # ancestors of <root> not ancestors of <dest>
1306 detachset.update(repo.changelog.findmissingrevs([commonbase.rev()],
1313 detachset.update(repo.changelog.findmissingrevs([commonbase.rev()],
1307 [root.rev()]))
1314 [root.rev()]))
1315 if emptyrebase:
1316 return None
1317 for rev in sorted(state):
1318 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
1319 # if all parents of this revision are done, then so is this revision
1320 if parents and all((state.get(p) == p for p in parents)):
1321 state[rev] = rev
1308 for r in detachset:
1322 for r in detachset:
1309 if r not in state:
1323 if r not in state:
1310 state[r] = nullmerge
1324 state[r] = nullmerge
@@ -1332,7 +1346,7 b' def clearrebased(ui, repo, state, skippe'
1332 if obsolete.isenabled(repo, obsolete.createmarkersopt):
1346 if obsolete.isenabled(repo, obsolete.createmarkersopt):
1333 markers = []
1347 markers = []
1334 for rev, newrev in sorted(state.items()):
1348 for rev, newrev in sorted(state.items()):
1335 if newrev >= 0:
1349 if newrev >= 0 and newrev != rev:
1336 if rev in skipped:
1350 if rev in skipped:
1337 succs = ()
1351 succs = ()
1338 elif collapsedas is not None:
1352 elif collapsedas is not None:
@@ -1343,7 +1357,8 b' def clearrebased(ui, repo, state, skippe'
1343 if markers:
1357 if markers:
1344 obsolete.createmarkers(repo, markers)
1358 obsolete.createmarkers(repo, markers)
1345 else:
1359 else:
1346 rebased = [rev for rev in state if state[rev] > nullmerge]
1360 rebased = [rev for rev in state
1361 if state[rev] > nullmerge and state[rev] != rev]
1347 if rebased:
1362 if rebased:
1348 stripped = []
1363 stripped = []
1349 for root in repo.set('roots(%ld)', rebased):
1364 for root in repo.set('roots(%ld)', rebased):
@@ -298,18 +298,6 b' Slightly more complex merge case (mentio'
298 |
298 |
299 o 0: M0
299 o 0: M0
300
300
301 Mixed rebasable and non-rebasable bases (unresolved, issue5422):
302
303 $ rebasewithdag -b C+D -d B <<'EOS'
304 > D
305 > /
306 > B C
307 > |/
308 > A
309 > EOS
310 nothing to rebase
311 [1]
312
313 Disconnected graph:
301 Disconnected graph:
314
302
315 $ rebasewithdag -b B -d Z <<'EOS'
303 $ rebasewithdag -b B -d Z <<'EOS'
General Comments 0
You need to be logged in to leave comments. Login now