##// END OF EJS Templates
rebase: do not add second parent to rebased changeset (drop detach option) (BC)...
Pierre-Yves David -
r17005:50f43451 default
parent child Browse files
Show More
@@ -1,677 +1,702 b''
1 1 # rebase.py - rebasing feature for mercurial
2 2 #
3 3 # Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''command to move sets of revisions to a different ancestor
9 9
10 10 This extension lets you rebase changesets in an existing Mercurial
11 11 repository.
12 12
13 13 For more information:
14 14 http://mercurial.selenic.com/wiki/RebaseExtension
15 15 '''
16 16
17 17 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
18 18 from mercurial import extensions, patch, scmutil, phases
19 19 from mercurial.commands import templateopts
20 20 from mercurial.node import nullrev
21 21 from mercurial.lock import release
22 22 from mercurial.i18n import _
23 23 import os, errno
24 24
25 25 nullmerge = -2
26 26
27 27 cmdtable = {}
28 28 command = cmdutil.command(cmdtable)
29 29 testedwith = 'internal'
30 30
31 31 @command('rebase',
32 32 [('s', 'source', '',
33 33 _('rebase from the specified changeset'), _('REV')),
34 34 ('b', 'base', '',
35 35 _('rebase from the base of the specified changeset '
36 36 '(up to greatest common ancestor of base and dest)'),
37 37 _('REV')),
38 38 ('r', 'rev', [],
39 39 _('rebase these revisions'),
40 40 _('REV')),
41 41 ('d', 'dest', '',
42 42 _('rebase onto the specified changeset'), _('REV')),
43 43 ('', 'collapse', False, _('collapse the rebased changesets')),
44 44 ('m', 'message', '',
45 45 _('use text as collapse commit message'), _('TEXT')),
46 46 ('e', 'edit', False, _('invoke editor on commit messages')),
47 47 ('l', 'logfile', '',
48 48 _('read collapse commit message from file'), _('FILE')),
49 49 ('', 'keep', False, _('keep original changesets')),
50 50 ('', 'keepbranches', False, _('keep original branch names')),
51 ('D', 'detach', False, _('force detaching of source from its original '
52 'branch')),
51 ('D', 'detach', False, _('(DEPRECATED)')),
53 52 ('t', 'tool', '', _('specify merge tool')),
54 53 ('c', 'continue', False, _('continue an interrupted rebase')),
55 54 ('a', 'abort', False, _('abort an interrupted rebase'))] +
56 55 templateopts,
57 56 _('hg rebase [-s REV | -b REV] [-d REV] [options]\n'
58 57 'hg rebase {-a|-c}'))
59 58 def rebase(ui, repo, **opts):
60 59 """move changeset (and descendants) to a different branch
61 60
62 61 Rebase uses repeated merging to graft changesets from one part of
63 62 history (the source) onto another (the destination). This can be
64 63 useful for linearizing *local* changes relative to a master
65 64 development tree.
66 65
67 66 You should not rebase changesets that have already been shared
68 67 with others. Doing so will force everybody else to perform the
69 68 same rebase or they will end up with duplicated changesets after
70 69 pulling in your rebased changesets.
71 70
72 71 If you don't specify a destination changeset (``-d/--dest``),
73 72 rebase uses the tipmost head of the current named branch as the
74 73 destination. (The destination changeset is not modified by
75 74 rebasing, but new changesets are added as its descendants.)
76 75
77 76 You can specify which changesets to rebase in two ways: as a
78 77 "source" changeset or as a "base" changeset. Both are shorthand
79 78 for a topologically related set of changesets (the "source
80 79 branch"). If you specify source (``-s/--source``), rebase will
81 80 rebase that changeset and all of its descendants onto dest. If you
82 81 specify base (``-b/--base``), rebase will select ancestors of base
83 82 back to but not including the common ancestor with dest. Thus,
84 83 ``-b`` is less precise but more convenient than ``-s``: you can
85 84 specify any changeset in the source branch, and rebase will select
86 85 the whole branch. If you specify neither ``-s`` nor ``-b``, rebase
87 86 uses the parent of the working directory as the base.
88 87
89 88 By default, rebase recreates the changesets in the source branch
90 89 as descendants of dest and then destroys the originals. Use
91 90 ``--keep`` to preserve the original source changesets. Some
92 91 changesets in the source branch (e.g. merges from the destination
93 92 branch) may be dropped if they no longer contribute any change.
94 93
95 94 One result of the rules for selecting the destination changeset
96 95 and source branch is that, unlike ``merge``, rebase will do
97 96 nothing if you are at the latest (tipmost) head of a named branch
98 97 with two heads. You need to explicitly specify source and/or
99 98 destination (or ``update`` to the other head, if it's the head of
100 99 the intended source branch).
101 100
102 101 If a rebase is interrupted to manually resolve a merge, it can be
103 102 continued with --continue/-c or aborted with --abort/-a.
104 103
105 104 Returns 0 on success, 1 if nothing to rebase.
106 105 """
107 106 originalwd = target = None
108 107 external = nullrev
109 108 state = {}
110 109 skipped = set()
111 110 targetancestors = set()
112 111
113 112 editor = None
114 113 if opts.get('edit'):
115 114 editor = cmdutil.commitforceeditor
116 115
117 116 lock = wlock = None
118 117 try:
119 118 wlock = repo.wlock()
120 119 lock = repo.lock()
121 120
122 121 # Validate input and define rebasing points
123 122 destf = opts.get('dest', None)
124 123 srcf = opts.get('source', None)
125 124 basef = opts.get('base', None)
126 125 revf = opts.get('rev', [])
127 126 contf = opts.get('continue')
128 127 abortf = opts.get('abort')
129 128 collapsef = opts.get('collapse', False)
130 129 collapsemsg = cmdutil.logmessage(ui, opts)
131 130 extrafn = opts.get('extrafn') # internal, used by e.g. hgsubversion
132 131 keepf = opts.get('keep', False)
133 132 keepbranchesf = opts.get('keepbranches', False)
134 detachf = opts.get('detach', False)
135 133 # keepopen is not meant for use on the command line, but by
136 134 # other extensions
137 135 keepopen = opts.get('keepopen', False)
138 136
139 137 if collapsemsg and not collapsef:
140 138 raise util.Abort(
141 139 _('message can only be specified with collapse'))
142 140
143 141 if contf or abortf:
144 142 if contf and abortf:
145 143 raise util.Abort(_('cannot use both abort and continue'))
146 144 if collapsef:
147 145 raise util.Abort(
148 146 _('cannot use collapse with continue or abort'))
149 if detachf:
150 raise util.Abort(_('cannot use detach with continue or abort'))
151 147 if srcf or basef or destf:
152 148 raise util.Abort(
153 149 _('abort and continue do not allow specifying revisions'))
154 150 if opts.get('tool', False):
155 151 ui.warn(_('tool option will be ignored\n'))
156 152
157 153 (originalwd, target, state, skipped, collapsef, keepf,
158 154 keepbranchesf, external) = restorestatus(repo)
159 155 if abortf:
160 156 return abort(repo, originalwd, target, state)
161 157 else:
162 158 if srcf and basef:
163 159 raise util.Abort(_('cannot specify both a '
164 160 'source and a base'))
165 161 if revf and basef:
166 162 raise util.Abort(_('cannot specify both a '
167 163 'revision and a base'))
168 164 if revf and srcf:
169 165 raise util.Abort(_('cannot specify both a '
170 166 'revision and a source'))
171 if detachf:
172 if not (srcf or revf):
173 raise util.Abort(
174 _('detach requires a revision to be specified'))
175 if basef:
176 raise util.Abort(_('cannot specify a base with detach'))
177 167
178 168 cmdutil.bailifchanged(repo)
179 169
180 170 if not destf:
181 171 # Destination defaults to the latest revision in the
182 172 # current branch
183 173 branch = repo[None].branch()
184 174 dest = repo[branch]
185 175 else:
186 176 dest = scmutil.revsingle(repo, destf)
187 177
188 178 if revf:
189 179 rebaseset = repo.revs('%lr', revf)
190 180 elif srcf:
191 181 src = scmutil.revrange(repo, [srcf])
192 182 rebaseset = repo.revs('(%ld)::', src)
193 183 else:
194 184 base = scmutil.revrange(repo, [basef or '.'])
195 185 rebaseset = repo.revs(
196 186 '(children(ancestor(%ld, %d)) and ::(%ld))::',
197 187 base, dest, base)
198 188
199 189 if rebaseset:
200 190 root = min(rebaseset)
201 191 else:
202 192 root = None
203 193
204 194 if not rebaseset:
205 195 repo.ui.debug('base is ancestor of destination\n')
206 196 result = None
207 197 elif not keepf and list(repo.revs('first(children(%ld) - %ld)',
208 198 rebaseset, rebaseset)):
209 199 raise util.Abort(
210 200 _("can't remove original changesets with"
211 201 " unrebased descendants"),
212 202 hint=_('use --keep to keep original changesets'))
213 203 elif not keepf and not repo[root].mutable():
214 204 raise util.Abort(_("can't rebase immutable changeset %s")
215 205 % repo[root],
216 206 hint=_('see hg help phases for details'))
217 207 else:
218 result = buildstate(repo, dest, rebaseset, detachf, collapsef)
208 result = buildstate(repo, dest, rebaseset, collapsef)
219 209
220 210 if not result:
221 211 # Empty state built, nothing to rebase
222 212 ui.status(_('nothing to rebase\n'))
223 213 return 1
224 214 else:
225 215 originalwd, target, state = result
226 216 if collapsef:
227 217 targetancestors = set(repo.changelog.ancestors([target]))
228 218 targetancestors.add(target)
229 219 external = checkexternal(repo, state, targetancestors)
230 220
231 221 if keepbranchesf:
232 222 assert not extrafn, 'cannot use both keepbranches and extrafn'
233 223 def extrafn(ctx, extra):
234 224 extra['branch'] = ctx.branch()
235 225 if collapsef:
236 226 branches = set()
237 227 for rev in state:
238 228 branches.add(repo[rev].branch())
239 229 if len(branches) > 1:
240 230 raise util.Abort(_('cannot collapse multiple named '
241 231 'branches'))
242 232
243 233
244 234 # Rebase
245 235 if not targetancestors:
246 236 targetancestors = set(repo.changelog.ancestors([target]))
247 237 targetancestors.add(target)
248 238
249 239 # Keep track of the current bookmarks in order to reset them later
250 240 currentbookmarks = repo._bookmarks.copy()
251 241
252 242 sortedstate = sorted(state)
253 243 total = len(sortedstate)
254 244 pos = 0
255 245 for rev in sortedstate:
256 246 pos += 1
257 247 if state[rev] == -1:
258 248 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])),
259 249 _('changesets'), total)
260 250 storestatus(repo, originalwd, target, state, collapsef, keepf,
261 251 keepbranchesf, external)
262 252 p1, p2 = defineparents(repo, rev, target, state,
263 253 targetancestors)
264 254 if len(repo.parents()) == 2:
265 255 repo.ui.debug('resuming interrupted rebase\n')
266 256 else:
267 257 try:
268 258 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
269 259 stats = rebasenode(repo, rev, p1, state, collapsef)
270 260 if stats and stats[3] > 0:
271 261 raise util.Abort(_('unresolved conflicts (see hg '
272 262 'resolve, then hg rebase --continue)'))
273 263 finally:
274 264 ui.setconfig('ui', 'forcemerge', '')
275 265 cmdutil.duplicatecopies(repo, rev, target)
276 266 if not collapsef:
277 267 newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn,
278 268 editor=editor)
279 269 else:
280 270 # Skip commit if we are collapsing
281 271 repo.setparents(repo[p1].node())
282 272 newrev = None
283 273 # Update the state
284 274 if newrev is not None:
285 275 state[rev] = repo[newrev].rev()
286 276 else:
287 277 if not collapsef:
288 278 ui.note(_('no changes, revision %d skipped\n') % rev)
289 279 ui.debug('next revision set to %s\n' % p1)
290 280 skipped.add(rev)
291 281 state[rev] = p1
292 282
293 283 ui.progress(_('rebasing'), None)
294 284 ui.note(_('rebase merging completed\n'))
295 285
296 286 if collapsef and not keepopen:
297 287 p1, p2 = defineparents(repo, min(state), target,
298 288 state, targetancestors)
299 289 if collapsemsg:
300 290 commitmsg = collapsemsg
301 291 else:
302 292 commitmsg = 'Collapsed revision'
303 293 for rebased in state:
304 294 if rebased not in skipped and state[rebased] != nullmerge:
305 295 commitmsg += '\n* %s' % repo[rebased].description()
306 296 commitmsg = ui.edit(commitmsg, repo.ui.username())
307 297 newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
308 298 extrafn=extrafn, editor=editor)
309 299
310 300 if 'qtip' in repo.tags():
311 301 updatemq(repo, state, skipped, **opts)
312 302
313 303 if currentbookmarks:
314 304 # Nodeids are needed to reset bookmarks
315 305 nstate = {}
316 306 for k, v in state.iteritems():
317 307 if v != nullmerge:
318 308 nstate[repo[k].node()] = repo[v].node()
319 309
320 310 if not keepf:
321 311 # Remove no more useful revisions
322 312 rebased = [rev for rev in state if state[rev] != nullmerge]
323 313 if rebased:
324 314 if set(repo.changelog.descendants([min(rebased)])) - set(state):
325 315 ui.warn(_("warning: new changesets detected "
326 316 "on source branch, not stripping\n"))
327 317 else:
328 318 # backup the old csets by default
329 319 repair.strip(ui, repo, repo[min(rebased)].node(), "all")
330 320
331 321 if currentbookmarks:
332 322 updatebookmarks(repo, nstate, currentbookmarks, **opts)
333 323
334 324 clearstatus(repo)
335 325 ui.note(_("rebase completed\n"))
336 326 if os.path.exists(repo.sjoin('undo')):
337 327 util.unlinkpath(repo.sjoin('undo'))
338 328 if skipped:
339 329 ui.note(_("%d revisions have been skipped\n") % len(skipped))
340 330 finally:
341 331 release(lock, wlock)
342 332
343 333 def checkexternal(repo, state, targetancestors):
344 334 """Check whether one or more external revisions need to be taken in
345 335 consideration. In the latter case, abort.
346 336 """
347 337 external = nullrev
348 338 source = min(state)
349 339 for rev in state:
350 340 if rev == source:
351 341 continue
352 342 # Check externals and fail if there are more than one
353 343 for p in repo[rev].parents():
354 344 if (p.rev() not in state
355 345 and p.rev() not in targetancestors):
356 346 if external != nullrev:
357 347 raise util.Abort(_('unable to collapse, there is more '
358 348 'than one external parent'))
359 349 external = p.rev()
360 350 return external
361 351
362 352 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None):
363 353 'Commit the changes and store useful information in extra'
364 354 try:
365 355 repo.setparents(repo[p1].node(), repo[p2].node())
366 356 ctx = repo[rev]
367 357 if commitmsg is None:
368 358 commitmsg = ctx.description()
369 359 extra = {'rebase_source': ctx.hex()}
370 360 if extrafn:
371 361 extrafn(ctx, extra)
372 362 # Commit might fail if unresolved files exist
373 363 newrev = repo.commit(text=commitmsg, user=ctx.user(),
374 364 date=ctx.date(), extra=extra, editor=editor)
375 365 repo.dirstate.setbranch(repo[newrev].branch())
376 366 targetphase = max(ctx.phase(), phases.draft)
377 367 # retractboundary doesn't overwrite upper phase inherited from parent
378 368 newnode = repo[newrev].node()
379 369 if newnode:
380 370 phases.retractboundary(repo, targetphase, [newnode])
381 371 return newrev
382 372 except util.Abort:
383 373 # Invalidate the previous setparents
384 374 repo.dirstate.invalidate()
385 375 raise
386 376
387 377 def rebasenode(repo, rev, p1, state, collapse):
388 378 'Rebase a single revision'
389 379 # Merge phase
390 380 # Update to target and merge it with local
391 381 if repo['.'].rev() != repo[p1].rev():
392 382 repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
393 383 merge.update(repo, p1, False, True, False)
394 384 else:
395 385 repo.ui.debug(" already in target\n")
396 386 repo.dirstate.write()
397 387 repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
398 388 base = None
399 389 if repo[rev].rev() != repo[min(state)].rev():
400 390 base = repo[rev].p1().node()
401 391 # When collapsing in-place, the parent is the common ancestor, we
402 392 # have to allow merging with it.
403 393 return merge.update(repo, rev, True, True, False, base, collapse)
404 394
405 395 def defineparents(repo, rev, target, state, targetancestors):
406 396 'Return the new parent relationship of the revision that will be rebased'
407 397 parents = repo[rev].parents()
408 398 p1 = p2 = nullrev
409 399
410 400 P1n = parents[0].rev()
411 401 if P1n in targetancestors:
412 402 p1 = target
413 403 elif P1n in state:
414 404 if state[P1n] == nullmerge:
415 405 p1 = target
416 406 else:
417 407 p1 = state[P1n]
418 408 else: # P1n external
419 409 p1 = target
420 410 p2 = P1n
421 411
422 412 if len(parents) == 2 and parents[1].rev() not in targetancestors:
423 413 P2n = parents[1].rev()
424 414 # interesting second parent
425 415 if P2n in state:
426 416 if p1 == target: # P1n in targetancestors or external
427 417 p1 = state[P2n]
428 418 else:
429 419 p2 = state[P2n]
430 420 else: # P2n external
431 421 if p2 != nullrev: # P1n external too => rev is a merged revision
432 422 raise util.Abort(_('cannot use revision %d as base, result '
433 423 'would have 3 parents') % rev)
434 424 p2 = P2n
435 425 repo.ui.debug(" future parents are %d and %d\n" %
436 426 (repo[p1].rev(), repo[p2].rev()))
437 427 return p1, p2
438 428
439 429 def isagitpatch(repo, patchname):
440 430 'Return true if the given patch is in git format'
441 431 mqpatch = os.path.join(repo.mq.path, patchname)
442 432 for line in patch.linereader(file(mqpatch, 'rb')):
443 433 if line.startswith('diff --git'):
444 434 return True
445 435 return False
446 436
447 437 def updatemq(repo, state, skipped, **opts):
448 438 'Update rebased mq patches - finalize and then import them'
449 439 mqrebase = {}
450 440 mq = repo.mq
451 441 original_series = mq.fullseries[:]
452 442 skippedpatches = set()
453 443
454 444 for p in mq.applied:
455 445 rev = repo[p.node].rev()
456 446 if rev in state:
457 447 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
458 448 (rev, p.name))
459 449 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
460 450 else:
461 451 # Applied but not rebased, not sure this should happen
462 452 skippedpatches.add(p.name)
463 453
464 454 if mqrebase:
465 455 mq.finish(repo, mqrebase.keys())
466 456
467 457 # We must start import from the newest revision
468 458 for rev in sorted(mqrebase, reverse=True):
469 459 if rev not in skipped:
470 460 name, isgit = mqrebase[rev]
471 461 repo.ui.debug('import mq patch %d (%s)\n' % (state[rev], name))
472 462 mq.qimport(repo, (), patchname=name, git=isgit,
473 463 rev=[str(state[rev])])
474 464 else:
475 465 # Rebased and skipped
476 466 skippedpatches.add(mqrebase[rev][0])
477 467
478 468 # Patches were either applied and rebased and imported in
479 469 # order, applied and removed or unapplied. Discard the removed
480 470 # ones while preserving the original series order and guards.
481 471 newseries = [s for s in original_series
482 472 if mq.guard_re.split(s, 1)[0] not in skippedpatches]
483 473 mq.fullseries[:] = newseries
484 474 mq.seriesdirty = True
485 475 mq.savedirty()
486 476
487 477 def updatebookmarks(repo, nstate, originalbookmarks, **opts):
488 478 'Move bookmarks to their correct changesets'
489 479 current = repo._bookmarkcurrent
490 480 for k, v in originalbookmarks.iteritems():
491 481 if v in nstate:
492 482 if nstate[v] != nullmerge:
493 483 # reset the pointer if the bookmark was moved incorrectly
494 484 if k != current:
495 485 repo._bookmarks[k] = nstate[v]
496 486
497 487 bookmarks.write(repo)
498 488
499 489 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
500 490 external):
501 491 'Store the current status to allow recovery'
502 492 f = repo.opener("rebasestate", "w")
503 493 f.write(repo[originalwd].hex() + '\n')
504 494 f.write(repo[target].hex() + '\n')
505 495 f.write(repo[external].hex() + '\n')
506 496 f.write('%d\n' % int(collapse))
507 497 f.write('%d\n' % int(keep))
508 498 f.write('%d\n' % int(keepbranches))
509 499 for d, v in state.iteritems():
510 500 oldrev = repo[d].hex()
511 501 if v != nullmerge:
512 502 newrev = repo[v].hex()
513 503 else:
514 504 newrev = v
515 505 f.write("%s:%s\n" % (oldrev, newrev))
516 506 f.close()
517 507 repo.ui.debug('rebase status stored\n')
518 508
519 509 def clearstatus(repo):
520 510 'Remove the status files'
521 511 if os.path.exists(repo.join("rebasestate")):
522 512 util.unlinkpath(repo.join("rebasestate"))
523 513
524 514 def restorestatus(repo):
525 515 'Restore a previously stored status'
526 516 try:
527 517 target = None
528 518 collapse = False
529 519 external = nullrev
530 520 state = {}
531 521 f = repo.opener("rebasestate")
532 522 for i, l in enumerate(f.read().splitlines()):
533 523 if i == 0:
534 524 originalwd = repo[l].rev()
535 525 elif i == 1:
536 526 target = repo[l].rev()
537 527 elif i == 2:
538 528 external = repo[l].rev()
539 529 elif i == 3:
540 530 collapse = bool(int(l))
541 531 elif i == 4:
542 532 keep = bool(int(l))
543 533 elif i == 5:
544 534 keepbranches = bool(int(l))
545 535 else:
546 536 oldrev, newrev = l.split(':')
547 537 if newrev != str(nullmerge):
548 538 state[repo[oldrev].rev()] = repo[newrev].rev()
549 539 else:
550 540 state[repo[oldrev].rev()] = int(newrev)
551 541 skipped = set()
552 542 # recompute the set of skipped revs
553 543 if not collapse:
554 544 seen = set([target])
555 545 for old, new in sorted(state.items()):
556 546 if new != nullrev and new in seen:
557 547 skipped.add(old)
558 548 seen.add(new)
559 549 repo.ui.debug('computed skipped revs: %s\n' % skipped)
560 550 repo.ui.debug('rebase status resumed\n')
561 551 return (originalwd, target, state, skipped,
562 552 collapse, keep, keepbranches, external)
563 553 except IOError, err:
564 554 if err.errno != errno.ENOENT:
565 555 raise
566 556 raise util.Abort(_('no rebase in progress'))
567 557
568 558 def abort(repo, originalwd, target, state):
569 559 'Restore the repository to its original state'
570 560 dstates = [s for s in state.values() if s != nullrev]
571 561 if [d for d in dstates if not repo[d].mutable()]:
572 562 repo.ui.warn(_("warning: immutable rebased changeset detected, "
573 563 "can't abort\n"))
574 564 return -1
575 565
576 566 descendants = set()
577 567 if dstates:
578 568 descendants = set(repo.changelog.descendants(dstates))
579 569 if descendants - set(dstates):
580 570 repo.ui.warn(_("warning: new changesets detected on target branch, "
581 571 "can't abort\n"))
582 572 return -1
583 573 else:
584 574 # Strip from the first rebased revision
585 575 merge.update(repo, repo[originalwd].rev(), False, True, False)
586 576 rebased = filter(lambda x: x > -1 and x != target, state.values())
587 577 if rebased:
588 578 strippoint = min(rebased)
589 579 # no backup of rebased cset versions needed
590 580 repair.strip(repo.ui, repo, repo[strippoint].node())
591 581 clearstatus(repo)
592 582 repo.ui.warn(_('rebase aborted\n'))
593 583 return 0
594 584
595 def buildstate(repo, dest, rebaseset, detach, collapse):
585 def buildstate(repo, dest, rebaseset, collapse):
596 586 '''Define which revisions are going to be rebased and where
597 587
598 588 repo: repo
599 589 dest: context
600 590 rebaseset: set of rev
601 detach: boolean'''
591 '''
602 592
603 593 # This check isn't strictly necessary, since mq detects commits over an
604 594 # applied patch. But it prevents messing up the working directory when
605 595 # a partially completed rebase is blocked by mq.
606 596 if 'qtip' in repo.tags() and (dest.node() in
607 597 [s.node for s in repo.mq.applied]):
608 598 raise util.Abort(_('cannot rebase onto an applied mq patch'))
609 599
610 detachset = set()
611 600 roots = list(repo.set('roots(%ld)', rebaseset))
612 601 if not roots:
613 602 raise util.Abort(_('no matching revisions'))
614 603 if len(roots) > 1:
615 604 raise util.Abort(_("can't rebase multiple roots"))
616 605 root = roots[0]
617 606
618 607 commonbase = root.ancestor(dest)
619 608 if commonbase == root:
620 609 raise util.Abort(_('source is ancestor of destination'))
621 610 if commonbase == dest:
622 611 samebranch = root.branch() == dest.branch()
623 612 if not collapse and samebranch and root in dest.children():
624 613 repo.ui.debug('source is a child of destination\n')
625 614 return None
626 # rebase on ancestor, force detach
627 detach = True
628 if detach:
629 detachset = repo.revs('::%d - ::%d - %d', root, commonbase, root)
630 615
631 616 repo.ui.debug('rebase onto %d starting from %d\n' % (dest, root))
632 617 state = dict.fromkeys(rebaseset, nullrev)
633 state.update(dict.fromkeys(detachset, nullmerge))
618 # Rebase tries to turn <dest> into a parent of <root> while
619 # preserving the number of parents of rebased changesets:
620 #
621 # - A changeset with a single parent will always be rebased as a
622 # changeset with a single parent.
623 #
624 # - A merge will be rebased as merge unless its parents are both
625 # ancestors of <dest> or are themselves in the rebased set and
626 # pruned while rebased.
627 #
628 # If one parent of <root> is an ancestor of <dest>, the rebased
629 # version of this parent will be <dest>. This is always true with
630 # --base option.
631 #
632 # Otherwise, we need to *replace* the original parents with
633 # <dest>. This "detaches" the rebased set from its former location
634 # and rebases it onto <dest>. Changes introduced by ancestors of
635 # <root> not common with <dest> (the detachset, marked as
636 # nullmerge) are "removed" from the rebased changesets.
637 #
638 # - If <root> has a single parent, set it to <dest>.
639 #
640 # - If <root> is a merge, we cannot decide which parent to
641 # replace, the rebase operation is not clearly defined.
642 #
643 # The table below sums up this behavior:
644 #
645 # +--------------------+----------------------+-------------------------+
646 # | | one parent | merge |
647 # +--------------------+----------------------+-------------------------+
648 # | parent in ::<dest> | new parent is <dest> | parents in ::<dest> are |
649 # | | | remapped to <dest> |
650 # +--------------------+----------------------+-------------------------+
651 # | unrelated source | new parent is <dest> | ambiguous, abort |
652 # +--------------------+----------------------+-------------------------+
653 #
654 # The actual abort is handled by `defineparents`
655 if len(root.parents()) <= 1:
656 # (strict) ancestors of <root> not ancestors of <dest>
657 detachset = repo.revs('::%d - ::%d - %d', root, commonbase, root)
658 state.update(dict.fromkeys(detachset, nullmerge))
634 659 return repo['.'].rev(), dest.rev(), state
635 660
636 661 def pullrebase(orig, ui, repo, *args, **opts):
637 662 'Call rebase after pull if the latter has been invoked with --rebase'
638 663 if opts.get('rebase'):
639 664 if opts.get('update'):
640 665 del opts['update']
641 666 ui.debug('--update and --rebase are not compatible, ignoring '
642 667 'the update flag\n')
643 668
644 669 movemarkfrom = repo['.'].node()
645 670 cmdutil.bailifchanged(repo)
646 671 revsprepull = len(repo)
647 672 origpostincoming = commands.postincoming
648 673 def _dummy(*args, **kwargs):
649 674 pass
650 675 commands.postincoming = _dummy
651 676 try:
652 677 orig(ui, repo, *args, **opts)
653 678 finally:
654 679 commands.postincoming = origpostincoming
655 680 revspostpull = len(repo)
656 681 if revspostpull > revsprepull:
657 682 rebase(ui, repo, **opts)
658 683 branch = repo[None].branch()
659 684 dest = repo[branch].rev()
660 685 if dest != repo['.'].rev():
661 686 # there was nothing to rebase we force an update
662 687 hg.update(repo, dest)
663 688 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
664 689 ui.status(_("updating bookmark %s\n")
665 690 % repo._bookmarkcurrent)
666 691 else:
667 692 if opts.get('tool'):
668 693 raise util.Abort(_('--tool can only be used with --rebase'))
669 694 orig(ui, repo, *args, **opts)
670 695
671 696 def uisetup(ui):
672 697 'Replace pull with a decorator to provide --rebase option'
673 698 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
674 699 entry[1].append(('', 'rebase', None,
675 700 _("rebase working directory to branch head")))
676 701 entry[1].append(('t', 'tool', '',
677 702 _("specify merge tool for rebase")))
@@ -1,67 +1,66 b''
1 1 $ echo "[extensions]" >> $HGRCPATH
2 2 $ echo "rebase=" >> $HGRCPATH
3 3
4 4 initialize repository
5 5
6 6 $ hg init
7 7
8 8 $ echo 'a' > a
9 9 $ hg ci -A -m "0"
10 10 adding a
11 11
12 12 $ echo 'b' > b
13 13 $ hg ci -A -m "1"
14 14 adding b
15 15
16 16 $ hg up 0
17 17 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
18 18 $ echo 'c' > c
19 19 $ hg ci -A -m "2"
20 20 adding c
21 21 created new head
22 22
23 23 $ echo 'd' > d
24 24 $ hg ci -A -m "3"
25 25 adding d
26 26
27 27 $ hg bookmark -r 1 one
28 28 $ hg bookmark -r 3 two
29 29
30 30 bookmark list
31 31
32 32 $ hg bookmark
33 33 one 1:925d80f479bb
34 34 * two 3:2ae46b1d99a7
35 35
36 36 rebase
37 37
38 38 $ hg rebase -s two -d one
39 39 saved backup bundle to $TESTTMP/.hg/strip-backup/*-backup.hg (glob)
40 40
41 41 $ hg log
42 changeset: 3:9163974d1cb5
42 changeset: 3:42e5ed2cdcf4
43 43 bookmark: two
44 44 tag: tip
45 45 parent: 1:925d80f479bb
46 parent: 2:db815d6d32e6
47 46 user: test
48 47 date: Thu Jan 01 00:00:00 1970 +0000
49 48 summary: 3
50 49
51 50 changeset: 2:db815d6d32e6
52 51 parent: 0:f7b1eb17ad24
53 52 user: test
54 53 date: Thu Jan 01 00:00:00 1970 +0000
55 54 summary: 2
56 55
57 56 changeset: 1:925d80f479bb
58 57 bookmark: one
59 58 user: test
60 59 date: Thu Jan 01 00:00:00 1970 +0000
61 60 summary: 1
62 61
63 62 changeset: 0:f7b1eb17ad24
64 63 user: test
65 64 date: Thu Jan 01 00:00:00 1970 +0000
66 65 summary: 0
67 66
@@ -1,90 +1,90 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' bookmarks: {bookmarks}\n"
11 11 > EOF
12 12
13 13 Create a repo with several bookmarks
14 14 $ hg init a
15 15 $ cd a
16 16
17 17 $ echo a > a
18 18 $ hg ci -Am A
19 19 adding a
20 20
21 21 $ echo b > b
22 22 $ hg ci -Am B
23 23 adding b
24 24 $ hg book 'X'
25 25 $ hg book 'Y'
26 26
27 27 $ echo c > c
28 28 $ hg ci -Am C
29 29 adding c
30 30 $ hg book 'Z'
31 31
32 32 $ hg up -q 0
33 33
34 34 $ echo d > d
35 35 $ hg ci -Am D
36 36 adding d
37 37 created new head
38 38
39 39 $ hg tglog
40 40 @ 3: 'D' bookmarks:
41 41 |
42 42 | o 2: 'C' bookmarks: Y Z
43 43 | |
44 44 | o 1: 'B' bookmarks: X
45 45 |/
46 46 o 0: 'A' bookmarks:
47 47
48 48
49 49 Move only rebased bookmarks
50 50
51 51 $ cd ..
52 52 $ hg clone -q a a1
53 53
54 54 $ cd a1
55 55 $ hg up -q Z
56 56
57 $ hg rebase --detach -s Y -d 3
57 $ hg rebase -s Y -d 3
58 58 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
59 59
60 60 $ hg tglog
61 61 @ 3: 'C' bookmarks: Y Z
62 62 |
63 63 o 2: 'D' bookmarks:
64 64 |
65 65 | o 1: 'B' bookmarks: X
66 66 |/
67 67 o 0: 'A' bookmarks:
68 68
69 69 Keep bookmarks to the correct rebased changeset
70 70
71 71 $ cd ..
72 72 $ hg clone -q a a2
73 73
74 74 $ cd a2
75 75 $ hg up -q Z
76 76
77 77 $ hg rebase -s 1 -d 3
78 78 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
79 79
80 80 $ hg tglog
81 81 @ 3: 'C' bookmarks: Y Z
82 82 |
83 83 o 2: 'B' bookmarks: X
84 84 |
85 85 o 1: 'D' bookmarks:
86 86 |
87 87 o 0: 'A' bookmarks:
88 88
89 89
90 90 $ cd ..
@@ -1,265 +1,265 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > theads = heads --template "{rev}: '{desc}' {branches}\n"
12 12 > EOF
13 13
14 14 $ hg init a
15 15 $ cd a
16 16
17 17 $ echo a > a
18 18 $ hg ci -Am A
19 19 adding a
20 20
21 21 $ hg branch branch1
22 22 marked working directory as branch branch1
23 23 (branches are permanent and global, did you want a bookmark?)
24 24 $ hg ci -m 'branch1'
25 25
26 26 $ echo b > b
27 27 $ hg ci -Am B
28 28 adding b
29 29
30 30 $ hg up -q 0
31 31
32 32 $ hg branch branch2
33 33 marked working directory as branch branch2
34 34 (branches are permanent and global, did you want a bookmark?)
35 35 $ hg ci -m 'branch2'
36 36
37 37 $ echo c > C
38 38 $ hg ci -Am C
39 39 adding C
40 40
41 41 $ hg up -q 2
42 42
43 43 $ hg branch -f branch2
44 44 marked working directory as branch branch2
45 45 (branches are permanent and global, did you want a bookmark?)
46 46 $ echo d > d
47 47 $ hg ci -Am D
48 48 adding d
49 49 created new head
50 50
51 51 $ echo e > e
52 52 $ hg ci -Am E
53 53 adding e
54 54
55 55 $ hg update default
56 56 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
57 57
58 58 $ hg branch branch3
59 59 marked working directory as branch branch3
60 60 (branches are permanent and global, did you want a bookmark?)
61 61 $ hg ci -m 'branch3'
62 62
63 63 $ echo f > f
64 64 $ hg ci -Am F
65 65 adding f
66 66
67 67 $ cd ..
68 68
69 69
70 70 Rebase part of branch2 (5-6) onto branch3 (8):
71 71
72 72 $ hg clone -q -u . a a1
73 73 $ cd a1
74 74
75 75 $ hg tglog
76 76 @ 8: 'F' branch3
77 77 |
78 78 o 7: 'branch3' branch3
79 79 |
80 80 | o 6: 'E' branch2
81 81 | |
82 82 | o 5: 'D' branch2
83 83 | |
84 84 | | o 4: 'C' branch2
85 85 | | |
86 86 +---o 3: 'branch2' branch2
87 87 | |
88 88 | o 2: 'B' branch1
89 89 | |
90 90 | o 1: 'branch1' branch1
91 91 |/
92 92 o 0: 'A'
93 93
94 94 $ hg branches
95 95 branch3 8:4666b71e8e32
96 96 branch2 6:5097051d331d
97 97 branch1 2:0a03079c47fd (inactive)
98 98 default 0:1994f17a630e (inactive)
99 99
100 100 $ hg theads
101 101 8: 'F' branch3
102 102 6: 'E' branch2
103 103 4: 'C' branch2
104 104 2: 'B' branch1
105 105 0: 'A'
106 106
107 $ hg rebase --detach -s 5 -d 8
107 $ hg rebase -s 5 -d 8
108 108 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
109 109
110 110 $ hg branches
111 111 branch3 8:466cdfb14b62
112 112 branch2 4:e4fdb121d036
113 113 branch1 2:0a03079c47fd
114 114 default 0:1994f17a630e (inactive)
115 115
116 116 $ hg theads
117 117 8: 'E' branch3
118 118 4: 'C' branch2
119 119 2: 'B' branch1
120 120 0: 'A'
121 121
122 122 $ hg tglog
123 123 @ 8: 'E' branch3
124 124 |
125 125 o 7: 'D' branch3
126 126 |
127 127 o 6: 'F' branch3
128 128 |
129 129 o 5: 'branch3' branch3
130 130 |
131 131 | o 4: 'C' branch2
132 132 | |
133 133 | o 3: 'branch2' branch2
134 134 |/
135 135 | o 2: 'B' branch1
136 136 | |
137 137 | o 1: 'branch1' branch1
138 138 |/
139 139 o 0: 'A'
140 140
141 141 $ cd ..
142 142
143 143
144 144 Rebase head of branch3 (8) onto branch2 (6):
145 145
146 146 $ hg clone -q -u . a a2
147 147 $ cd a2
148 148
149 149 $ hg tglog
150 150 @ 8: 'F' branch3
151 151 |
152 152 o 7: 'branch3' branch3
153 153 |
154 154 | o 6: 'E' branch2
155 155 | |
156 156 | o 5: 'D' branch2
157 157 | |
158 158 | | o 4: 'C' branch2
159 159 | | |
160 160 +---o 3: 'branch2' branch2
161 161 | |
162 162 | o 2: 'B' branch1
163 163 | |
164 164 | o 1: 'branch1' branch1
165 165 |/
166 166 o 0: 'A'
167 167
168 $ hg rebase --detach -s 8 -d 6
168 $ hg rebase -s 8 -d 6
169 169 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
170 170
171 171 $ hg branches
172 172 branch2 8:6b4bdc1b5ac0
173 173 branch3 7:653b9feb4616
174 174 branch1 2:0a03079c47fd (inactive)
175 175 default 0:1994f17a630e (inactive)
176 176
177 177 $ hg theads
178 178 8: 'F' branch2
179 179 7: 'branch3' branch3
180 180 4: 'C' branch2
181 181 2: 'B' branch1
182 182 0: 'A'
183 183
184 184 $ hg tglog
185 185 @ 8: 'F' branch2
186 186 |
187 187 | o 7: 'branch3' branch3
188 188 | |
189 189 o | 6: 'E' branch2
190 190 | |
191 191 o | 5: 'D' branch2
192 192 | |
193 193 | | o 4: 'C' branch2
194 194 | | |
195 195 | | o 3: 'branch2' branch2
196 196 | |/
197 197 o | 2: 'B' branch1
198 198 | |
199 199 o | 1: 'branch1' branch1
200 200 |/
201 201 o 0: 'A'
202 202
203 203 $ hg verify -q
204 204
205 205 $ cd ..
206 206
207 207
208 208 Rebase entire branch3 (7-8) onto branch2 (6):
209 209
210 210 $ hg clone -q -u . a a3
211 211 $ cd a3
212 212
213 213 $ hg tglog
214 214 @ 8: 'F' branch3
215 215 |
216 216 o 7: 'branch3' branch3
217 217 |
218 218 | o 6: 'E' branch2
219 219 | |
220 220 | o 5: 'D' branch2
221 221 | |
222 222 | | o 4: 'C' branch2
223 223 | | |
224 224 +---o 3: 'branch2' branch2
225 225 | |
226 226 | o 2: 'B' branch1
227 227 | |
228 228 | o 1: 'branch1' branch1
229 229 |/
230 230 o 0: 'A'
231 231
232 $ hg rebase --detach -s 7 -d 6
232 $ hg rebase -s 7 -d 6
233 233 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
234 234
235 235 $ hg branches
236 236 branch2 7:6b4bdc1b5ac0
237 237 branch1 2:0a03079c47fd (inactive)
238 238 default 0:1994f17a630e (inactive)
239 239
240 240 $ hg theads
241 241 7: 'F' branch2
242 242 4: 'C' branch2
243 243 2: 'B' branch1
244 244 0: 'A'
245 245
246 246 $ hg tglog
247 247 @ 7: 'F' branch2
248 248 |
249 249 o 6: 'E' branch2
250 250 |
251 251 o 5: 'D' branch2
252 252 |
253 253 | o 4: 'C' branch2
254 254 | |
255 255 | o 3: 'branch2' branch2
256 256 | |
257 257 o | 2: 'B' branch1
258 258 | |
259 259 o | 1: 'branch1' branch1
260 260 |/
261 261 o 0: 'A'
262 262
263 263 $ hg verify -q
264 264
265 265 $ cd ..
@@ -1,632 +1,630 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > tglogp = log -G --template "{rev}:{phase} '{desc}' {branches}\n"
12 12 > EOF
13 13
14 14 Create repo a:
15 15
16 16 $ hg init a
17 17 $ cd a
18 18 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
19 19 adding changesets
20 20 adding manifests
21 21 adding file changes
22 22 added 8 changesets with 7 changes to 7 files (+2 heads)
23 23 (run 'hg heads' to see heads, 'hg merge' to merge)
24 24 $ hg up tip
25 25 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 26
27 27 $ hg tglog
28 28 @ 7: 'H'
29 29 |
30 30 | o 6: 'G'
31 31 |/|
32 32 o | 5: 'F'
33 33 | |
34 34 | o 4: 'E'
35 35 |/
36 36 | o 3: 'D'
37 37 | |
38 38 | o 2: 'C'
39 39 | |
40 40 | o 1: 'B'
41 41 |/
42 42 o 0: 'A'
43 43
44 44 $ cd ..
45 45
46 46
47 47 Rebasing B onto H and collapsing changesets with different phases:
48 48
49 49
50 50 $ hg clone -q -u 3 a a1
51 51 $ cd a1
52 52
53 53 $ hg phase --force --secret 3
54 54
55 55 $ hg rebase --collapse --keepbranches
56 56 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
57 57
58 58 $ hg tglogp
59 59 @ 5:secret 'Collapsed revision
60 60 | * B
61 61 | * C
62 62 | * D'
63 63 o 4:draft 'H'
64 64 |
65 65 | o 3:draft 'G'
66 66 |/|
67 67 o | 2:draft 'F'
68 68 | |
69 69 | o 1:draft 'E'
70 70 |/
71 71 o 0:draft 'A'
72 72
73 73 $ hg manifest
74 74 A
75 75 B
76 76 C
77 77 D
78 78 F
79 79 H
80 80
81 81 $ cd ..
82 82
83 83
84 84 Rebasing E onto H:
85 85
86 86 $ hg clone -q -u . a a2
87 87 $ cd a2
88 88
89 89 $ hg phase --force --secret 6
90 90 $ hg rebase --source 4 --collapse
91 91 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
92 92
93 93 $ hg tglog
94 94 @ 6: 'Collapsed revision
95 95 | * E
96 96 | * G'
97 97 o 5: 'H'
98 98 |
99 99 o 4: 'F'
100 100 |
101 101 | o 3: 'D'
102 102 | |
103 103 | o 2: 'C'
104 104 | |
105 105 | o 1: 'B'
106 106 |/
107 107 o 0: 'A'
108 108
109 109 $ hg manifest
110 110 A
111 111 E
112 112 F
113 113 H
114 114
115 115 $ cd ..
116 116
117 117 Rebasing G onto H with custom message:
118 118
119 119 $ hg clone -q -u . a a3
120 120 $ cd a3
121 121
122 122 $ hg rebase --base 6 -m 'custom message'
123 123 abort: message can only be specified with collapse
124 124 [255]
125 125
126 126 $ hg rebase --source 4 --collapse -m 'custom message'
127 127 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
128 128
129 129 $ hg tglog
130 130 @ 6: 'custom message'
131 131 |
132 132 o 5: 'H'
133 133 |
134 134 o 4: 'F'
135 135 |
136 136 | o 3: 'D'
137 137 | |
138 138 | o 2: 'C'
139 139 | |
140 140 | o 1: 'B'
141 141 |/
142 142 o 0: 'A'
143 143
144 144 $ hg manifest
145 145 A
146 146 E
147 147 F
148 148 H
149 149
150 150 $ cd ..
151 151
152 152 Create repo b:
153 153
154 154 $ hg init b
155 155 $ cd b
156 156
157 157 $ echo A > A
158 158 $ hg ci -Am A
159 159 adding A
160 160 $ echo B > B
161 161 $ hg ci -Am B
162 162 adding B
163 163
164 164 $ hg up -q 0
165 165
166 166 $ echo C > C
167 167 $ hg ci -Am C
168 168 adding C
169 169 created new head
170 170
171 171 $ hg merge
172 172 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 173 (branch merge, don't forget to commit)
174 174
175 175 $ echo D > D
176 176 $ hg ci -Am D
177 177 adding D
178 178
179 179 $ hg up -q 1
180 180
181 181 $ echo E > E
182 182 $ hg ci -Am E
183 183 adding E
184 184 created new head
185 185
186 186 $ echo F > F
187 187 $ hg ci -Am F
188 188 adding F
189 189
190 190 $ hg merge
191 191 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 192 (branch merge, don't forget to commit)
193 193 $ hg ci -m G
194 194
195 195 $ hg up -q 0
196 196
197 197 $ echo H > H
198 198 $ hg ci -Am H
199 199 adding H
200 200 created new head
201 201
202 202 $ hg tglog
203 203 @ 7: 'H'
204 204 |
205 205 | o 6: 'G'
206 206 | |\
207 207 | | o 5: 'F'
208 208 | | |
209 209 | | o 4: 'E'
210 210 | | |
211 211 | o | 3: 'D'
212 212 | |\|
213 213 | o | 2: 'C'
214 214 |/ /
215 215 | o 1: 'B'
216 216 |/
217 217 o 0: 'A'
218 218
219 219 $ cd ..
220 220
221 221
222 222 Rebase and collapse - more than one external (fail):
223 223
224 224 $ hg clone -q -u . b b1
225 225 $ cd b1
226 226
227 227 $ hg rebase -s 2 --collapse
228 228 abort: unable to collapse, there is more than one external parent
229 229 [255]
230 230
231 231 Rebase and collapse - E onto H:
232 232
233 $ hg rebase -s 4 --collapse
233 $ hg rebase -s 4 --collapse # root (4) is not a merge
234 234 saved backup bundle to $TESTTMP/b1/.hg/strip-backup/*-backup.hg (glob)
235 235
236 236 $ hg tglog
237 237 @ 5: 'Collapsed revision
238 238 |\ * E
239 239 | | * F
240 240 | | * G'
241 241 | o 4: 'H'
242 242 | |
243 243 o | 3: 'D'
244 244 |\ \
245 245 | o | 2: 'C'
246 246 | |/
247 247 o / 1: 'B'
248 248 |/
249 249 o 0: 'A'
250 250
251 251 $ hg manifest
252 252 A
253 B
254 253 C
255 254 D
256 255 E
257 256 F
258 257 H
259 258
260 259 $ cd ..
261 260
262 261
263 262 Create repo c:
264 263
265 264 $ hg init c
266 265 $ cd c
267 266
268 267 $ echo A > A
269 268 $ hg ci -Am A
270 269 adding A
271 270 $ echo B > B
272 271 $ hg ci -Am B
273 272 adding B
274 273
275 274 $ hg up -q 0
276 275
277 276 $ echo C > C
278 277 $ hg ci -Am C
279 278 adding C
280 279 created new head
281 280
282 281 $ hg merge
283 282 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 283 (branch merge, don't forget to commit)
285 284
286 285 $ echo D > D
287 286 $ hg ci -Am D
288 287 adding D
289 288
290 289 $ hg up -q 1
291 290
292 291 $ echo E > E
293 292 $ hg ci -Am E
294 293 adding E
295 294 created new head
296 295 $ echo F > E
297 296 $ hg ci -m 'F'
298 297
299 298 $ echo G > G
300 299 $ hg ci -Am G
301 300 adding G
302 301
303 302 $ hg merge
304 303 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
305 304 (branch merge, don't forget to commit)
306 305
307 306 $ hg ci -m H
308 307
309 308 $ hg up -q 0
310 309
311 310 $ echo I > I
312 311 $ hg ci -Am I
313 312 adding I
314 313 created new head
315 314
316 315 $ hg tglog
317 316 @ 8: 'I'
318 317 |
319 318 | o 7: 'H'
320 319 | |\
321 320 | | o 6: 'G'
322 321 | | |
323 322 | | o 5: 'F'
324 323 | | |
325 324 | | o 4: 'E'
326 325 | | |
327 326 | o | 3: 'D'
328 327 | |\|
329 328 | o | 2: 'C'
330 329 |/ /
331 330 | o 1: 'B'
332 331 |/
333 332 o 0: 'A'
334 333
335 334 $ cd ..
336 335
337 336
338 337 Rebase and collapse - E onto I:
339 338
340 339 $ hg clone -q -u . c c1
341 340 $ cd c1
342 341
343 $ hg rebase -s 4 --collapse
342 $ hg rebase -s 4 --collapse # root (4) is not a merge
344 343 merging E
345 344 saved backup bundle to $TESTTMP/c1/.hg/strip-backup/*-backup.hg (glob)
346 345
347 346 $ hg tglog
348 347 @ 5: 'Collapsed revision
349 348 |\ * E
350 349 | | * F
351 350 | | * G
352 351 | | * H'
353 352 | o 4: 'I'
354 353 | |
355 354 o | 3: 'D'
356 355 |\ \
357 356 | o | 2: 'C'
358 357 | |/
359 358 o / 1: 'B'
360 359 |/
361 360 o 0: 'A'
362 361
363 362 $ hg manifest
364 363 A
365 B
366 364 C
367 365 D
368 366 E
369 367 G
370 368 I
371 369
372 370 $ cat E
373 371 F
374 372
375 373 $ cd ..
376 374
377 375
378 376 Create repo d:
379 377
380 378 $ hg init d
381 379 $ cd d
382 380
383 381 $ echo A > A
384 382 $ hg ci -Am A
385 383 adding A
386 384 $ echo B > B
387 385 $ hg ci -Am B
388 386 adding B
389 387 $ echo C > C
390 388 $ hg ci -Am C
391 389 adding C
392 390
393 391 $ hg up -q 1
394 392
395 393 $ echo D > D
396 394 $ hg ci -Am D
397 395 adding D
398 396 created new head
399 397 $ hg merge
400 398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
401 399 (branch merge, don't forget to commit)
402 400
403 401 $ hg ci -m E
404 402
405 403 $ hg up -q 0
406 404
407 405 $ echo F > F
408 406 $ hg ci -Am F
409 407 adding F
410 408 created new head
411 409
412 410 $ hg tglog
413 411 @ 5: 'F'
414 412 |
415 413 | o 4: 'E'
416 414 | |\
417 415 | | o 3: 'D'
418 416 | | |
419 417 | o | 2: 'C'
420 418 | |/
421 419 | o 1: 'B'
422 420 |/
423 421 o 0: 'A'
424 422
425 423 $ cd ..
426 424
427 425
428 426 Rebase and collapse - B onto F:
429 427
430 428 $ hg clone -q -u . d d1
431 429 $ cd d1
432 430
433 431 $ hg rebase -s 1 --collapse
434 432 saved backup bundle to $TESTTMP/d1/.hg/strip-backup/*-backup.hg (glob)
435 433
436 434 $ hg tglog
437 435 @ 2: 'Collapsed revision
438 436 | * B
439 437 | * C
440 438 | * D
441 439 | * E'
442 440 o 1: 'F'
443 441 |
444 442 o 0: 'A'
445 443
446 444 $ hg manifest
447 445 A
448 446 B
449 447 C
450 448 D
451 449 F
452 450
453 451 Interactions between collapse and keepbranches
454 452 $ cd ..
455 453 $ hg init e
456 454 $ cd e
457 455 $ echo 'a' > a
458 456 $ hg ci -Am 'A'
459 457 adding a
460 458
461 459 $ hg branch '1'
462 460 marked working directory as branch 1
463 461 (branches are permanent and global, did you want a bookmark?)
464 462 $ echo 'b' > b
465 463 $ hg ci -Am 'B'
466 464 adding b
467 465
468 466 $ hg branch '2'
469 467 marked working directory as branch 2
470 468 (branches are permanent and global, did you want a bookmark?)
471 469 $ echo 'c' > c
472 470 $ hg ci -Am 'C'
473 471 adding c
474 472
475 473 $ hg up -q 0
476 474 $ echo 'd' > d
477 475 $ hg ci -Am 'D'
478 476 adding d
479 477
480 478 $ hg tglog
481 479 @ 3: 'D'
482 480 |
483 481 | o 2: 'C' 2
484 482 | |
485 483 | o 1: 'B' 1
486 484 |/
487 485 o 0: 'A'
488 486
489 487 $ hg rebase --keepbranches --collapse -s 1 -d 3
490 488 abort: cannot collapse multiple named branches
491 489 [255]
492 490
493 491 $ repeatchange() {
494 492 > hg checkout $1
495 493 > hg cp d z
496 494 > echo blah >> z
497 495 > hg commit -Am "$2" --user "$3"
498 496 > }
499 497 $ repeatchange 3 "E" "user1"
500 498 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
501 499 $ repeatchange 3 "E" "user2"
502 500 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
503 501 created new head
504 502 $ hg tglog
505 503 @ 5: 'E'
506 504 |
507 505 | o 4: 'E'
508 506 |/
509 507 o 3: 'D'
510 508 |
511 509 | o 2: 'C' 2
512 510 | |
513 511 | o 1: 'B' 1
514 512 |/
515 513 o 0: 'A'
516 514
517 515 $ hg rebase -s 5 -d 4
518 516 saved backup bundle to $TESTTMP/e/.hg/strip-backup/*-backup.hg (glob)
519 517 $ hg tglog
520 518 @ 4: 'E'
521 519 |
522 520 o 3: 'D'
523 521 |
524 522 | o 2: 'C' 2
525 523 | |
526 524 | o 1: 'B' 1
527 525 |/
528 526 o 0: 'A'
529 527
530 528 $ hg export tip
531 529 # HG changeset patch
532 530 # User user1
533 531 # Date 0 0
534 532 # Node ID f338eb3c2c7cc5b5915676a2376ba7ac558c5213
535 533 # Parent 41acb9dca9eb976e84cd21fcb756b4afa5a35c09
536 534 E
537 535
538 536 diff -r 41acb9dca9eb -r f338eb3c2c7c z
539 537 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
540 538 +++ b/z Thu Jan 01 00:00:00 1970 +0000
541 539 @@ -0,0 +1,2 @@
542 540 +d
543 541 +blah
544 542
545 543 $ cd ..
546 544
547 545 Rebase, collapse and copies
548 546
549 547 $ hg init copies
550 548 $ cd copies
551 549 $ hg unbundle "$TESTDIR/bundles/renames.hg"
552 550 adding changesets
553 551 adding manifests
554 552 adding file changes
555 553 added 4 changesets with 11 changes to 7 files (+1 heads)
556 554 (run 'hg heads' to see heads, 'hg merge' to merge)
557 555 $ hg up -q tip
558 556 $ hg tglog
559 557 @ 3: 'move2'
560 558 |
561 559 o 2: 'move1'
562 560 |
563 561 | o 1: 'change'
564 562 |/
565 563 o 0: 'add'
566 564
567 565 $ hg rebase --collapse -d 1
568 566 merging a and d to d
569 567 merging b and e to e
570 568 merging c and f to f
571 569 merging e and g to g
572 570 merging f and c to c
573 571 saved backup bundle to $TESTTMP/copies/.hg/strip-backup/*-backup.hg (glob)
574 572 $ hg st
575 573 $ hg st --copies --change .
576 574 A d
577 575 a
578 576 A g
579 577 b
580 578 R b
581 579 $ cat c
582 580 c
583 581 c
584 582 $ cat d
585 583 a
586 584 a
587 585 $ cat g
588 586 b
589 587 b
590 588 $ hg log -r . --template "{file_copies}\n"
591 589 d (a)g (b)
592 590
593 591 Test collapsing a middle revision in-place
594 592
595 593 $ hg tglog
596 594 @ 2: 'Collapsed revision
597 595 | * move1
598 596 | * move2'
599 597 o 1: 'change'
600 598 |
601 599 o 0: 'add'
602 600
603 601 $ hg rebase --collapse -r 1 -d 0
604 602 abort: can't remove original changesets with unrebased descendants
605 603 (use --keep to keep original changesets)
606 604 [255]
607 605
608 606 Test collapsing in place
609 607
610 608 $ hg rebase --collapse -b . -d 0
611 609 saved backup bundle to $TESTTMP/copies/.hg/strip-backup/*-backup.hg (glob)
612 610 $ hg st --change . --copies
613 611 M a
614 612 M c
615 613 A d
616 614 a
617 615 A g
618 616 b
619 617 R b
620 618 $ cat a
621 619 a
622 620 a
623 621 $ cat c
624 622 c
625 623 c
626 624 $ cat d
627 625 a
628 626 a
629 627 $ cat g
630 628 b
631 629 b
632 630 $ cd ..
@@ -1,400 +1,400 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 8 changesets with 7 changes to 7 files (+2 heads)
21 21 (run 'hg heads' to see heads, 'hg merge' to merge)
22 22 $ hg up tip
23 23 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24
25 25 $ cd ..
26 26
27 27
28 28 Rebasing D onto H detaching from C:
29 29
30 30 $ hg clone -q -u . a a1
31 31 $ cd a1
32 32
33 33 $ hg tglog
34 34 @ 7: 'H'
35 35 |
36 36 | o 6: 'G'
37 37 |/|
38 38 o | 5: 'F'
39 39 | |
40 40 | o 4: 'E'
41 41 |/
42 42 | o 3: 'D'
43 43 | |
44 44 | o 2: 'C'
45 45 | |
46 46 | o 1: 'B'
47 47 |/
48 48 o 0: 'A'
49 49
50 50 $ hg phase --force --secret 3
51 $ hg rebase --detach -s 3 -d 7
51 $ hg rebase -s 3 -d 7
52 52 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
53 53
54 54 $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
55 55 @ 7:secret 'D'
56 56 |
57 57 o 6:draft 'H'
58 58 |
59 59 | o 5:draft 'G'
60 60 |/|
61 61 o | 4:draft 'F'
62 62 | |
63 63 | o 3:draft 'E'
64 64 |/
65 65 | o 2:draft 'C'
66 66 | |
67 67 | o 1:draft 'B'
68 68 |/
69 69 o 0:draft 'A'
70 70
71 71 $ hg manifest
72 72 A
73 73 D
74 74 F
75 75 H
76 76
77 77 $ cd ..
78 78
79 79
80 80 Rebasing C onto H detaching from B:
81 81
82 82 $ hg clone -q -u . a a2
83 83 $ cd a2
84 84
85 85 $ hg tglog
86 86 @ 7: 'H'
87 87 |
88 88 | o 6: 'G'
89 89 |/|
90 90 o | 5: 'F'
91 91 | |
92 92 | o 4: 'E'
93 93 |/
94 94 | o 3: 'D'
95 95 | |
96 96 | o 2: 'C'
97 97 | |
98 98 | o 1: 'B'
99 99 |/
100 100 o 0: 'A'
101 101
102 $ hg rebase --detach -s 2 -d 7
102 $ hg rebase -s 2 -d 7
103 103 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
104 104
105 105 $ hg tglog
106 106 @ 7: 'D'
107 107 |
108 108 o 6: 'C'
109 109 |
110 110 o 5: 'H'
111 111 |
112 112 | o 4: 'G'
113 113 |/|
114 114 o | 3: 'F'
115 115 | |
116 116 | o 2: 'E'
117 117 |/
118 118 | o 1: 'B'
119 119 |/
120 120 o 0: 'A'
121 121
122 122 $ hg manifest
123 123 A
124 124 C
125 125 D
126 126 F
127 127 H
128 128
129 129 $ cd ..
130 130
131 131
132 132 Rebasing B onto H using detach (same as not using it):
133 133
134 134 $ hg clone -q -u . a a3
135 135 $ cd a3
136 136
137 137 $ hg tglog
138 138 @ 7: 'H'
139 139 |
140 140 | o 6: 'G'
141 141 |/|
142 142 o | 5: 'F'
143 143 | |
144 144 | o 4: 'E'
145 145 |/
146 146 | o 3: 'D'
147 147 | |
148 148 | o 2: 'C'
149 149 | |
150 150 | o 1: 'B'
151 151 |/
152 152 o 0: 'A'
153 153
154 $ hg rebase --detach -s 1 -d 7
154 $ hg rebase -s 1 -d 7
155 155 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
156 156
157 157 $ hg tglog
158 158 @ 7: 'D'
159 159 |
160 160 o 6: 'C'
161 161 |
162 162 o 5: 'B'
163 163 |
164 164 o 4: 'H'
165 165 |
166 166 | o 3: 'G'
167 167 |/|
168 168 o | 2: 'F'
169 169 | |
170 170 | o 1: 'E'
171 171 |/
172 172 o 0: 'A'
173 173
174 174 $ hg manifest
175 175 A
176 176 B
177 177 C
178 178 D
179 179 F
180 180 H
181 181
182 182 $ cd ..
183 183
184 184
185 185 Rebasing C onto H detaching from B and collapsing:
186 186
187 187 $ hg clone -q -u . a a4
188 188 $ cd a4
189 189 $ hg phase --force --secret 3
190 190
191 191 $ hg tglog
192 192 @ 7: 'H'
193 193 |
194 194 | o 6: 'G'
195 195 |/|
196 196 o | 5: 'F'
197 197 | |
198 198 | o 4: 'E'
199 199 |/
200 200 | o 3: 'D'
201 201 | |
202 202 | o 2: 'C'
203 203 | |
204 204 | o 1: 'B'
205 205 |/
206 206 o 0: 'A'
207 207
208 $ hg rebase --detach --collapse -s 2 -d 7
208 $ hg rebase --collapse -s 2 -d 7
209 209 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
210 210
211 211 $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
212 212 @ 6:secret 'Collapsed revision
213 213 | * C
214 214 | * D'
215 215 o 5:draft 'H'
216 216 |
217 217 | o 4:draft 'G'
218 218 |/|
219 219 o | 3:draft 'F'
220 220 | |
221 221 | o 2:draft 'E'
222 222 |/
223 223 | o 1:draft 'B'
224 224 |/
225 225 o 0:draft 'A'
226 226
227 227 $ hg manifest
228 228 A
229 229 C
230 230 D
231 231 F
232 232 H
233 233
234 234 $ cd ..
235 235
236 236 Rebasing across null as ancestor
237 237 $ hg clone -q -U a a5
238 238
239 239 $ cd a5
240 240
241 241 $ echo x > x
242 242
243 243 $ hg add x
244 244
245 245 $ hg ci -m "extra branch"
246 246 created new head
247 247
248 248 $ hg tglog
249 249 @ 8: 'extra branch'
250 250
251 251 o 7: 'H'
252 252 |
253 253 | o 6: 'G'
254 254 |/|
255 255 o | 5: 'F'
256 256 | |
257 257 | o 4: 'E'
258 258 |/
259 259 | o 3: 'D'
260 260 | |
261 261 | o 2: 'C'
262 262 | |
263 263 | o 1: 'B'
264 264 |/
265 265 o 0: 'A'
266 266
267 $ hg rebase --detach -s 1 -d tip
267 $ hg rebase -s 1 -d tip
268 268 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
269 269
270 270 $ hg tglog
271 271 @ 8: 'D'
272 272 |
273 273 o 7: 'C'
274 274 |
275 275 o 6: 'B'
276 276 |
277 277 o 5: 'extra branch'
278 278
279 279 o 4: 'H'
280 280 |
281 281 | o 3: 'G'
282 282 |/|
283 283 o | 2: 'F'
284 284 | |
285 285 | o 1: 'E'
286 286 |/
287 287 o 0: 'A'
288 288
289 289
290 290 $ hg rebase -d 5 -s 7
291 291 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/13547172c9c0-backup.hg (glob)
292 292 $ hg tglog
293 293 @ 8: 'D'
294 294 |
295 295 o 7: 'C'
296 296 |
297 297 | o 6: 'B'
298 298 |/
299 299 o 5: 'extra branch'
300 300
301 301 o 4: 'H'
302 302 |
303 303 | o 3: 'G'
304 304 |/|
305 305 o | 2: 'F'
306 306 | |
307 307 | o 1: 'E'
308 308 |/
309 309 o 0: 'A'
310 310
311 311 $ cd ..
312 312
313 313 Verify that target is not selected as external rev (issue3085)
314 314
315 315 $ hg clone -q -U a a6
316 316 $ cd a6
317 317 $ hg up -q 6
318 318
319 319 $ echo "I" >> E
320 320 $ hg ci -m "I"
321 321 $ hg merge 7
322 322 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
323 323 (branch merge, don't forget to commit)
324 324 $ hg ci -m "Merge"
325 325 $ echo "J" >> F
326 326 $ hg ci -m "J"
327 327
328 $ hg rebase -s 8 -d 7 --collapse --detach --config ui.merge=internal:other
328 $ hg rebase -s 8 -d 7 --collapse --config ui.merge=internal:other
329 329 remote changed E which local deleted
330 330 use (c)hanged version or leave (d)eleted? c
331 331 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
332 332
333 333 $ hg tglog
334 334 @ 8: 'Collapsed revision
335 335 | * I
336 336 | * Merge
337 337 | * J'
338 338 o 7: 'H'
339 339 |
340 340 | o 6: 'G'
341 341 |/|
342 342 o | 5: 'F'
343 343 | |
344 344 | o 4: 'E'
345 345 |/
346 346 | o 3: 'D'
347 347 | |
348 348 | o 2: 'C'
349 349 | |
350 350 | o 1: 'B'
351 351 |/
352 352 o 0: 'A'
353 353
354 354
355 355 $ hg parents
356 356 changeset: 8:9472f4b1d736
357 357 tag: tip
358 358 user: test
359 359 date: Thu Jan 01 00:00:00 1970 +0000
360 360 summary: Collapsed revision
361 361
362 362
363 363 $ cd ..
364 364
365 365 Ensure --continue restores a correct state (issue3046) and phase:
366 366 $ hg clone -q a a7
367 367 $ cd a7
368 368 $ hg up -q 3
369 369 $ echo 'H2' > H
370 370 $ hg ci -A -m 'H2'
371 371 adding H
372 372 $ hg phase --force --secret 8
373 $ hg rebase -s 8 -d 7 --detach --config ui.merge=internal:fail
373 $ hg rebase -s 8 -d 7 --config ui.merge=internal:fail
374 374 merging H
375 375 warning: conflicts during merge.
376 376 merging H incomplete! (edit conflicts, then use 'hg resolve --mark')
377 377 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
378 378 [255]
379 379 $ hg resolve --all -t internal:local
380 380 $ hg rebase -c
381 381 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/6215fafa5447-backup.hg (glob)
382 382 $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
383 383 @ 7:draft 'H'
384 384 |
385 385 | o 6:draft 'G'
386 386 |/|
387 387 o | 5:draft 'F'
388 388 | |
389 389 | o 4:draft 'E'
390 390 |/
391 391 | o 3:draft 'D'
392 392 | |
393 393 | o 2:draft 'C'
394 394 | |
395 395 | o 1:draft 'B'
396 396 |/
397 397 o 0:draft 'A'
398 398
399 399
400 400 $ cd ..
@@ -1,430 +1,430 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 8 changesets with 7 changes to 7 files (+2 heads)
21 21 (run 'hg heads' to see heads, 'hg merge' to merge)
22 22 $ hg up tip
23 23 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24
25 25 $ echo I > I
26 26 $ hg ci -AmI
27 27 adding I
28 28
29 29 $ hg tglog
30 30 @ 8: 'I'
31 31 |
32 32 o 7: 'H'
33 33 |
34 34 | o 6: 'G'
35 35 |/|
36 36 o | 5: 'F'
37 37 | |
38 38 | o 4: 'E'
39 39 |/
40 40 | o 3: 'D'
41 41 | |
42 42 | o 2: 'C'
43 43 | |
44 44 | o 1: 'B'
45 45 |/
46 46 o 0: 'A'
47 47
48 48 $ cd ..
49 49
50 50
51 51 These fail:
52 52
53 53 $ hg clone -q -u . a a1
54 54 $ cd a1
55 55
56 56 $ hg rebase -s 8 -d 7
57 57 nothing to rebase
58 58 [1]
59 59
60 60 $ hg rebase --continue --abort
61 61 abort: cannot use both abort and continue
62 62 [255]
63 63
64 64 $ hg rebase --continue --collapse
65 65 abort: cannot use collapse with continue or abort
66 66 [255]
67 67
68 68 $ hg rebase --continue --dest 4
69 69 abort: abort and continue do not allow specifying revisions
70 70 [255]
71 71
72 72 $ hg rebase --base 5 --source 4
73 73 abort: cannot specify both a source and a base
74 74 [255]
75 75
76 76 $ hg rebase --rev 5 --source 4
77 77 abort: cannot specify both a revision and a source
78 78 [255]
79 79 $ hg rebase --base 5 --rev 4
80 80 abort: cannot specify both a revision and a base
81 81 [255]
82 82
83 83 $ hg rebase
84 84 nothing to rebase
85 85 [1]
86 86
87 87 $ hg up -q 7
88 88
89 89 $ hg rebase --traceback
90 90 nothing to rebase
91 91 [1]
92 92
93 93
94 94 These work:
95 95
96 96 Rebase with no arguments (from 3 onto 8):
97 97
98 98 $ hg up -q -C 3
99 99
100 100 $ hg rebase
101 101 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
102 102
103 103 $ hg tglog
104 104 @ 8: 'D'
105 105 |
106 106 o 7: 'C'
107 107 |
108 108 o 6: 'B'
109 109 |
110 110 o 5: 'I'
111 111 |
112 112 o 4: 'H'
113 113 |
114 114 | o 3: 'G'
115 115 |/|
116 116 o | 2: 'F'
117 117 | |
118 118 | o 1: 'E'
119 119 |/
120 120 o 0: 'A'
121 121
122 122 Try to rollback after a rebase (fail):
123 123
124 124 $ hg rollback
125 125 no rollback information available
126 126 [1]
127 127
128 128 $ cd ..
129 129
130 130
131 131 Rebase with base == '.' => same as no arguments (from 3 onto 8):
132 132
133 133 $ hg clone -q -u 3 a a2
134 134 $ cd a2
135 135
136 136 $ hg rebase --base .
137 137 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
138 138
139 139 $ hg tglog
140 140 @ 8: 'D'
141 141 |
142 142 o 7: 'C'
143 143 |
144 144 o 6: 'B'
145 145 |
146 146 o 5: 'I'
147 147 |
148 148 o 4: 'H'
149 149 |
150 150 | o 3: 'G'
151 151 |/|
152 152 o | 2: 'F'
153 153 | |
154 154 | o 1: 'E'
155 155 |/
156 156 o 0: 'A'
157 157
158 158 $ cd ..
159 159
160 160
161 161 Rebase with dest == branch(.) => same as no arguments (from 3 onto 8):
162 162
163 163 $ hg clone -q -u 3 a a3
164 164 $ cd a3
165 165
166 166 $ hg rebase --dest 'branch(.)'
167 167 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
168 168
169 169 $ hg tglog
170 170 @ 8: 'D'
171 171 |
172 172 o 7: 'C'
173 173 |
174 174 o 6: 'B'
175 175 |
176 176 o 5: 'I'
177 177 |
178 178 o 4: 'H'
179 179 |
180 180 | o 3: 'G'
181 181 |/|
182 182 o | 2: 'F'
183 183 | |
184 184 | o 1: 'E'
185 185 |/
186 186 o 0: 'A'
187 187
188 188 $ cd ..
189 189
190 190
191 191 Specify only source (from 2 onto 8):
192 192
193 193 $ hg clone -q -u . a a4
194 194 $ cd a4
195 195
196 196 $ hg rebase --source 'desc("C")'
197 197 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
198 198
199 199 $ hg tglog
200 200 @ 8: 'D'
201 201 |
202 o 7: 'C'
203 |\
204 | o 6: 'I'
205 | |
206 | o 5: 'H'
202 o 7: 'C'
203 |
204 o 6: 'I'
205 |
206 o 5: 'H'
207 |
208 | o 4: 'G'
209 |/|
210 o | 3: 'F'
207 211 | |
208 | | o 4: 'G'
209 | |/|
210 | o | 3: 'F'
211 | | |
212 | | o 2: 'E'
213 | |/
214 o | 1: 'B'
212 | o 2: 'E'
213 |/
214 | o 1: 'B'
215 215 |/
216 216 o 0: 'A'
217 217
218 218 $ cd ..
219 219
220 220
221 221 Specify only dest (from 3 onto 6):
222 222
223 223 $ hg clone -q -u 3 a a5
224 224 $ cd a5
225 225
226 226 $ hg rebase --dest 6
227 227 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
228 228
229 229 $ hg tglog
230 230 @ 8: 'D'
231 231 |
232 232 o 7: 'C'
233 233 |
234 234 o 6: 'B'
235 235 |
236 236 | o 5: 'I'
237 237 | |
238 238 | o 4: 'H'
239 239 | |
240 240 o | 3: 'G'
241 241 |\|
242 242 | o 2: 'F'
243 243 | |
244 244 o | 1: 'E'
245 245 |/
246 246 o 0: 'A'
247 247
248 248 $ cd ..
249 249
250 250
251 251 Specify only base (from 1 onto 8):
252 252
253 253 $ hg clone -q -u . a a6
254 254 $ cd a6
255 255
256 256 $ hg rebase --base 'desc("D")'
257 257 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
258 258
259 259 $ hg tglog
260 260 @ 8: 'D'
261 261 |
262 262 o 7: 'C'
263 263 |
264 264 o 6: 'B'
265 265 |
266 266 o 5: 'I'
267 267 |
268 268 o 4: 'H'
269 269 |
270 270 | o 3: 'G'
271 271 |/|
272 272 o | 2: 'F'
273 273 | |
274 274 | o 1: 'E'
275 275 |/
276 276 o 0: 'A'
277 277
278 278 $ cd ..
279 279
280 280
281 281 Specify source and dest (from 2 onto 7):
282 282
283 283 $ hg clone -q -u . a a7
284 284 $ cd a7
285 285
286 $ hg rebase --detach --source 2 --dest 7
286 $ hg rebase --source 2 --dest 7
287 287 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/*-backup.hg (glob)
288 288
289 289 $ hg tglog
290 290 @ 8: 'D'
291 291 |
292 292 o 7: 'C'
293 293 |
294 294 | o 6: 'I'
295 295 |/
296 296 o 5: 'H'
297 297 |
298 298 | o 4: 'G'
299 299 |/|
300 300 o | 3: 'F'
301 301 | |
302 302 | o 2: 'E'
303 303 |/
304 304 | o 1: 'B'
305 305 |/
306 306 o 0: 'A'
307 307
308 308 $ cd ..
309 309
310 310
311 311 Specify base and dest (from 1 onto 7):
312 312
313 313 $ hg clone -q -u . a a8
314 314 $ cd a8
315 315
316 316 $ hg rebase --base 3 --dest 7
317 317 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/*-backup.hg (glob)
318 318
319 319 $ hg tglog
320 320 @ 8: 'D'
321 321 |
322 322 o 7: 'C'
323 323 |
324 324 o 6: 'B'
325 325 |
326 326 | o 5: 'I'
327 327 |/
328 328 o 4: 'H'
329 329 |
330 330 | o 3: 'G'
331 331 |/|
332 332 o | 2: 'F'
333 333 | |
334 334 | o 1: 'E'
335 335 |/
336 336 o 0: 'A'
337 337
338 338 $ cd ..
339 339
340 340
341 341 Specify only revs (from 2 onto 8)
342 342
343 343 $ hg clone -q -u . a a9
344 344 $ cd a9
345 345
346 346 $ hg rebase --rev 'desc("C")::'
347 347 saved backup bundle to $TESTTMP/a9/.hg/strip-backup/*-backup.hg (glob)
348 348
349 349 $ hg tglog
350 350 @ 8: 'D'
351 351 |
352 o 7: 'C'
353 |\
354 | o 6: 'I'
355 | |
356 | o 5: 'H'
352 o 7: 'C'
353 |
354 o 6: 'I'
355 |
356 o 5: 'H'
357 |
358 | o 4: 'G'
359 |/|
360 o | 3: 'F'
357 361 | |
358 | | o 4: 'G'
359 | |/|
360 | o | 3: 'F'
361 | | |
362 | | o 2: 'E'
363 | |/
364 o | 1: 'B'
362 | o 2: 'E'
363 |/
364 | o 1: 'B'
365 365 |/
366 366 o 0: 'A'
367 367
368 368 $ cd ..
369 369
370 370 Test --tool parameter:
371 371
372 372 $ hg init b
373 373 $ cd b
374 374
375 375 $ echo c1 > c1
376 376 $ hg ci -Am c1
377 377 adding c1
378 378
379 379 $ echo c2 > c2
380 380 $ hg ci -Am c2
381 381 adding c2
382 382
383 383 $ hg up -q 0
384 384 $ echo c2b > c2
385 385 $ hg ci -Am c2b
386 386 adding c2
387 387 created new head
388 388
389 389 $ cd ..
390 390
391 391 $ hg clone -q -u . b b1
392 392 $ cd b1
393 393
394 394 $ hg rebase -s 2 -d 1 --tool internal:local
395 395 saved backup bundle to $TESTTMP/b1/.hg/strip-backup/*-backup.hg (glob)
396 396
397 397 $ hg cat c2
398 398 c2
399 399
400 400 $ cd ..
401 401
402 402
403 403 $ hg clone -q -u . b b2
404 404 $ cd b2
405 405
406 406 $ hg rebase -s 2 -d 1 --tool internal:other
407 407 saved backup bundle to $TESTTMP/b2/.hg/strip-backup/*-backup.hg (glob)
408 408
409 409 $ hg cat c2
410 410 c2b
411 411
412 412 $ cd ..
413 413
414 414
415 415 $ hg clone -q -u . b b3
416 416 $ cd b3
417 417
418 418 $ hg rebase -s 2 -d 1 --tool internal:fail
419 419 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
420 420 [255]
421 421
422 422 $ hg resolve -l
423 423 U c2
424 424
425 425 $ hg resolve -m c2
426 426 $ hg rebase -c --tool internal:fail
427 427 tool option will be ignored
428 428 saved backup bundle to $TESTTMP/b3/.hg/strip-backup/*-backup.hg (glob)
429 429
430 430 $ cd ..
@@ -1,547 +1,547 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 8 changesets with 7 changes to 7 files (+2 heads)
21 21 (run 'hg heads' to see heads, 'hg merge' to merge)
22 22 $ hg up tip
23 23 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24 $ cd ..
25 25
26 26
27 27 Rebasing
28 28 D onto H - simple rebase:
29 29
30 30 $ hg clone -q -u . a a1
31 31 $ cd a1
32 32
33 33 $ hg tglog
34 34 @ 7: 'H'
35 35 |
36 36 | o 6: 'G'
37 37 |/|
38 38 o | 5: 'F'
39 39 | |
40 40 | o 4: 'E'
41 41 |/
42 42 | o 3: 'D'
43 43 | |
44 44 | o 2: 'C'
45 45 | |
46 46 | o 1: 'B'
47 47 |/
48 48 o 0: 'A'
49 49
50 50
51 51 $ hg rebase -s 3 -d 7
52 52 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
53 53
54 54 $ hg tglog
55 @ 7: 'D'
56 |\
57 | o 6: 'H'
55 @ 7: 'D'
56 |
57 o 6: 'H'
58 |
59 | o 5: 'G'
60 |/|
61 o | 4: 'F'
58 62 | |
59 | | o 5: 'G'
60 | |/|
61 | o | 4: 'F'
62 | | |
63 | | o 3: 'E'
64 | |/
65 o | 2: 'C'
63 | o 3: 'E'
64 |/
65 | o 2: 'C'
66 66 | |
67 o | 1: 'B'
67 | o 1: 'B'
68 68 |/
69 69 o 0: 'A'
70 70
71 71 $ cd ..
72 72
73 73
74 74 D onto F - intermediate point:
75 75
76 76 $ hg clone -q -u . a a2
77 77 $ cd a2
78 78
79 79 $ hg rebase -s 3 -d 5
80 80 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
81 81
82 82 $ hg tglog
83 @ 7: 'D'
84 |\
85 | | o 6: 'H'
86 | |/
87 | | o 5: 'G'
88 | |/|
89 | o | 4: 'F'
90 | | |
91 | | o 3: 'E'
92 | |/
93 o | 2: 'C'
83 @ 7: 'D'
84 |
85 | o 6: 'H'
86 |/
87 | o 5: 'G'
88 |/|
89 o | 4: 'F'
94 90 | |
95 o | 1: 'B'
91 | o 3: 'E'
92 |/
93 | o 2: 'C'
94 | |
95 | o 1: 'B'
96 96 |/
97 97 o 0: 'A'
98 98
99 99 $ cd ..
100 100
101 101
102 102 E onto H - skip of G:
103 103
104 104 $ hg clone -q -u . a a3
105 105 $ cd a3
106 106
107 107 $ hg rebase -s 4 -d 7
108 108 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
109 109
110 110 $ hg tglog
111 111 @ 6: 'E'
112 112 |
113 113 o 5: 'H'
114 114 |
115 115 o 4: 'F'
116 116 |
117 117 | o 3: 'D'
118 118 | |
119 119 | o 2: 'C'
120 120 | |
121 121 | o 1: 'B'
122 122 |/
123 123 o 0: 'A'
124 124
125 125 $ cd ..
126 126
127 127
128 128 F onto E - rebase of a branching point (skip G):
129 129
130 130 $ hg clone -q -u . a a4
131 131 $ cd a4
132 132
133 133 $ hg rebase -s 5 -d 4
134 134 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
135 135
136 136 $ hg tglog
137 137 @ 6: 'H'
138 138 |
139 139 o 5: 'F'
140 140 |
141 141 o 4: 'E'
142 142 |
143 143 | o 3: 'D'
144 144 | |
145 145 | o 2: 'C'
146 146 | |
147 147 | o 1: 'B'
148 148 |/
149 149 o 0: 'A'
150 150
151 151 $ cd ..
152 152
153 153
154 154 G onto H - merged revision having a parent in ancestors of target:
155 155
156 156 $ hg clone -q -u . a a5
157 157 $ cd a5
158 158
159 159 $ hg rebase -s 6 -d 7
160 160 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
161 161
162 162 $ hg tglog
163 163 @ 7: 'G'
164 164 |\
165 165 | o 6: 'H'
166 166 | |
167 167 | o 5: 'F'
168 168 | |
169 169 o | 4: 'E'
170 170 |/
171 171 | o 3: 'D'
172 172 | |
173 173 | o 2: 'C'
174 174 | |
175 175 | o 1: 'B'
176 176 |/
177 177 o 0: 'A'
178 178
179 179 $ cd ..
180 180
181 181
182 182 F onto B - G maintains E as parent:
183 183
184 184 $ hg clone -q -u . a a6
185 185 $ cd a6
186 186
187 187 $ hg rebase -s 5 -d 1
188 188 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
189 189
190 190 $ hg tglog
191 191 @ 7: 'H'
192 192 |
193 193 | o 6: 'G'
194 194 |/|
195 195 o | 5: 'F'
196 196 | |
197 197 | o 4: 'E'
198 198 | |
199 199 | | o 3: 'D'
200 200 | | |
201 201 +---o 2: 'C'
202 202 | |
203 203 o | 1: 'B'
204 204 |/
205 205 o 0: 'A'
206 206
207 207 $ cd ..
208 208
209 209
210 210 These will fail (using --source):
211 211
212 212 G onto F - rebase onto an ancestor:
213 213
214 214 $ hg clone -q -u . a a7
215 215 $ cd a7
216 216
217 217 $ hg rebase -s 6 -d 5
218 218 nothing to rebase
219 219 [1]
220 220
221 221 F onto G - rebase onto a descendant:
222 222
223 223 $ hg rebase -s 5 -d 6
224 224 abort: source is ancestor of destination
225 225 [255]
226 226
227 227 G onto B - merge revision with both parents not in ancestors of target:
228 228
229 229 $ hg rebase -s 6 -d 1
230 230 abort: cannot use revision 6 as base, result would have 3 parents
231 231 [255]
232 232
233 233
234 234 These will abort gracefully (using --base):
235 235
236 236 G onto G - rebase onto same changeset:
237 237
238 238 $ hg rebase -b 6 -d 6
239 239 nothing to rebase
240 240 [1]
241 241
242 242 G onto F - rebase onto an ancestor:
243 243
244 244 $ hg rebase -b 6 -d 5
245 245 nothing to rebase
246 246 [1]
247 247
248 248 F onto G - rebase onto a descendant:
249 249
250 250 $ hg rebase -b 5 -d 6
251 251 nothing to rebase
252 252 [1]
253 253
254 254 C onto A - rebase onto an ancestor:
255 255
256 256 $ hg rebase -d 0 -s 2
257 257 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-backup.hg (glob)
258 258 $ hg tglog
259 259 @ 7: 'D'
260 260 |
261 261 o 6: 'C'
262 262 |
263 263 | o 5: 'H'
264 264 | |
265 265 | | o 4: 'G'
266 266 | |/|
267 267 | o | 3: 'F'
268 268 |/ /
269 269 | o 2: 'E'
270 270 |/
271 271 | o 1: 'B'
272 272 |/
273 273 o 0: 'A'
274 274
275 275
276 276 Check rebasing public changeset
277 277
278 278 $ hg pull --config phases.publish=True -q -r 6 . # update phase of 6
279 279 $ hg rebase -d 5 -b 6
280 280 abort: can't rebase immutable changeset e1c4361dd923
281 281 (see hg help phases for details)
282 282 [255]
283 283
284 284 $ hg rebase -d 5 -b 6 --keep
285 285
286 286 Check rebasing mutable changeset
287 287 Source phase greater or equal to destination phase: new changeset get the phase of source:
288 288 $ hg rebase -s9 -d0
289 289 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2b23e52411f4-backup.hg (glob)
290 290 $ hg log --template "{phase}\n" -r 9
291 291 draft
292 292 $ hg rebase -s9 -d1
293 293 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2cb10d0cfc6c-backup.hg (glob)
294 294 $ hg log --template "{phase}\n" -r 9
295 295 draft
296 296 $ hg phase --force --secret 9
297 297 $ hg rebase -s9 -d0
298 298 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/c5b12b67163a-backup.hg (glob)
299 299 $ hg log --template "{phase}\n" -r 9
300 300 secret
301 301 $ hg rebase -s9 -d1
302 302 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2a0524f868ac-backup.hg (glob)
303 303 $ hg log --template "{phase}\n" -r 9
304 304 secret
305 305 Source phase lower than destination phase: new changeset get the phase of destination:
306 $ hg rebase -s7 -d9
307 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/c9659aac0000-backup.hg (glob)
308 $ hg log --template "{phase}\n" -r 9
306 $ hg rebase -s8 -d9
307 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/6d4f22462821-backup.hg
308 $ hg log --template "{phase}\n" -r 'rev(9)'
309 309 secret
310 310
311 311 $ cd ..
312 312
313 313 Test for revset
314 314
315 315 We need a bit different graph
316 316 All destination are B
317 317
318 318 $ hg init ah
319 319 $ cd ah
320 320 $ hg unbundle "$TESTDIR/bundles/rebase-revset.hg"
321 321 adding changesets
322 322 adding manifests
323 323 adding file changes
324 324 added 9 changesets with 9 changes to 9 files (+2 heads)
325 325 (run 'hg heads' to see heads, 'hg merge' to merge)
326 326 $ hg tglog
327 327 o 8: 'I'
328 328 |
329 329 o 7: 'H'
330 330 |
331 331 o 6: 'G'
332 332 |
333 333 | o 5: 'F'
334 334 | |
335 335 | o 4: 'E'
336 336 |/
337 337 o 3: 'D'
338 338 |
339 339 o 2: 'C'
340 340 |
341 341 | o 1: 'B'
342 342 |/
343 343 o 0: 'A'
344 344
345 345 $ cd ..
346 346
347 347
348 348 Simple case with keep:
349 349
350 350 Source on have two descendant heads but ask for one
351 351
352 352 $ hg clone -q -u . ah ah1
353 353 $ cd ah1
354 354 $ hg rebase -r '2::8' -d 1
355 355 abort: can't remove original changesets with unrebased descendants
356 356 (use --keep to keep original changesets)
357 357 [255]
358 358 $ hg rebase -r '2::8' -d 1 --keep
359 359 $ hg tglog
360 360 @ 13: 'I'
361 361 |
362 362 o 12: 'H'
363 363 |
364 364 o 11: 'G'
365 365 |
366 366 o 10: 'D'
367 367 |
368 368 o 9: 'C'
369 369 |
370 370 | o 8: 'I'
371 371 | |
372 372 | o 7: 'H'
373 373 | |
374 374 | o 6: 'G'
375 375 | |
376 376 | | o 5: 'F'
377 377 | | |
378 378 | | o 4: 'E'
379 379 | |/
380 380 | o 3: 'D'
381 381 | |
382 382 | o 2: 'C'
383 383 | |
384 384 o | 1: 'B'
385 385 |/
386 386 o 0: 'A'
387 387
388 388
389 389 $ cd ..
390 390
391 391 Base on have one descendant heads we ask for but common ancestor have two
392 392
393 393 $ hg clone -q -u . ah ah2
394 394 $ cd ah2
395 395 $ hg rebase -r '3::8' -d 1
396 396 abort: can't remove original changesets with unrebased descendants
397 397 (use --keep to keep original changesets)
398 398 [255]
399 399 $ hg rebase -r '3::8' -d 1 --keep
400 400 $ hg tglog
401 401 @ 12: 'I'
402 402 |
403 403 o 11: 'H'
404 404 |
405 405 o 10: 'G'
406 406 |
407 o 9: 'D'
408 |\
409 | | o 8: 'I'
410 | | |
411 | | o 7: 'H'
407 o 9: 'D'
408 |
409 | o 8: 'I'
410 | |
411 | o 7: 'H'
412 | |
413 | o 6: 'G'
414 | |
415 | | o 5: 'F'
412 416 | | |
413 | | o 6: 'G'
414 | | |
415 | | | o 5: 'F'
416 | | | |
417 | | | o 4: 'E'
418 | | |/
419 | | o 3: 'D'
417 | | o 4: 'E'
420 418 | |/
419 | o 3: 'D'
420 | |
421 421 | o 2: 'C'
422 422 | |
423 423 o | 1: 'B'
424 424 |/
425 425 o 0: 'A'
426 426
427 427
428 428 $ cd ..
429 429
430 430 rebase subset
431 431
432 432 $ hg clone -q -u . ah ah3
433 433 $ cd ah3
434 434 $ hg rebase -r '3::7' -d 1
435 435 abort: can't remove original changesets with unrebased descendants
436 436 (use --keep to keep original changesets)
437 437 [255]
438 438 $ hg rebase -r '3::7' -d 1 --keep
439 439 $ hg tglog
440 440 @ 11: 'H'
441 441 |
442 442 o 10: 'G'
443 443 |
444 o 9: 'D'
445 |\
446 | | o 8: 'I'
447 | | |
448 | | o 7: 'H'
444 o 9: 'D'
445 |
446 | o 8: 'I'
447 | |
448 | o 7: 'H'
449 | |
450 | o 6: 'G'
451 | |
452 | | o 5: 'F'
449 453 | | |
450 | | o 6: 'G'
451 | | |
452 | | | o 5: 'F'
453 | | | |
454 | | | o 4: 'E'
455 | | |/
456 | | o 3: 'D'
454 | | o 4: 'E'
457 455 | |/
456 | o 3: 'D'
457 | |
458 458 | o 2: 'C'
459 459 | |
460 460 o | 1: 'B'
461 461 |/
462 462 o 0: 'A'
463 463
464 464
465 465 $ cd ..
466 466
467 467 rebase subset with multiple head
468 468
469 469 $ hg clone -q -u . ah ah4
470 470 $ cd ah4
471 471 $ hg rebase -r '3::(7+5)' -d 1
472 472 abort: can't remove original changesets with unrebased descendants
473 473 (use --keep to keep original changesets)
474 474 [255]
475 475 $ hg rebase -r '3::(7+5)' -d 1 --keep
476 476 $ hg tglog
477 477 @ 13: 'H'
478 478 |
479 479 o 12: 'G'
480 480 |
481 481 | o 11: 'F'
482 482 | |
483 483 | o 10: 'E'
484 484 |/
485 o 9: 'D'
486 |\
487 | | o 8: 'I'
488 | | |
489 | | o 7: 'H'
485 o 9: 'D'
486 |
487 | o 8: 'I'
488 | |
489 | o 7: 'H'
490 | |
491 | o 6: 'G'
492 | |
493 | | o 5: 'F'
490 494 | | |
491 | | o 6: 'G'
492 | | |
493 | | | o 5: 'F'
494 | | | |
495 | | | o 4: 'E'
496 | | |/
497 | | o 3: 'D'
495 | | o 4: 'E'
498 496 | |/
497 | o 3: 'D'
498 | |
499 499 | o 2: 'C'
500 500 | |
501 501 o | 1: 'B'
502 502 |/
503 503 o 0: 'A'
504 504
505 505
506 506 $ cd ..
507 507
508 508 More advanced tests
509 509
510 510 rebase on ancestor with revset
511 511
512 512 $ hg clone -q -u . ah ah5
513 513 $ cd ah5
514 514 $ hg rebase -r '6::' -d 2
515 515 saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-backup.hg (glob)
516 516 $ hg tglog
517 517 @ 8: 'I'
518 518 |
519 519 o 7: 'H'
520 520 |
521 521 o 6: 'G'
522 522 |
523 523 | o 5: 'F'
524 524 | |
525 525 | o 4: 'E'
526 526 | |
527 527 | o 3: 'D'
528 528 |/
529 529 o 2: 'C'
530 530 |
531 531 | o 1: 'B'
532 532 |/
533 533 o 0: 'A'
534 534
535 535 $ cd ..
536 536
537 537
538 538 rebase with multiple root.
539 539 We rebase E and G on B
540 540 We would expect heads are I, F if it was supported
541 541
542 542 $ hg clone -q -u . ah ah6
543 543 $ cd ah6
544 544 $ hg rebase -r '(4+6)::' -d 1
545 545 abort: can't rebase multiple roots
546 546 [255]
547 547 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now