##// END OF EJS Templates
errors: use more specific errors in rebase extension...
Martin von Zweigbergk -
r47377:9989a276 default
parent child Browse files
Show More
@@ -1,2301 +1,2303 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 https://mercurial-scm.org/wiki/RebaseExtension
15 15 '''
16 16
17 17 from __future__ import absolute_import
18 18
19 19 import errno
20 20 import os
21 21
22 22 from mercurial.i18n import _
23 23 from mercurial.node import (
24 24 nullrev,
25 25 short,
26 26 wdirrev,
27 27 )
28 28 from mercurial.pycompat import open
29 29 from mercurial import (
30 30 bookmarks,
31 31 cmdutil,
32 32 commands,
33 33 copies,
34 34 destutil,
35 35 dirstateguard,
36 36 error,
37 37 extensions,
38 38 merge as mergemod,
39 39 mergestate as mergestatemod,
40 40 mergeutil,
41 41 obsolete,
42 42 obsutil,
43 43 patch,
44 44 phases,
45 45 pycompat,
46 46 registrar,
47 47 repair,
48 48 revset,
49 49 revsetlang,
50 50 rewriteutil,
51 51 scmutil,
52 52 smartset,
53 53 state as statemod,
54 54 util,
55 55 )
56 56
57 57 # The following constants are used throughout the rebase module. The ordering of
58 58 # their values must be maintained.
59 59
60 60 # Indicates that a revision needs to be rebased
61 61 revtodo = -1
62 62 revtodostr = b'-1'
63 63
64 64 # legacy revstates no longer needed in current code
65 65 # -2: nullmerge, -3: revignored, -4: revprecursor, -5: revpruned
66 66 legacystates = {b'-2', b'-3', b'-4', b'-5'}
67 67
68 68 cmdtable = {}
69 69 command = registrar.command(cmdtable)
70 70
71 71 configtable = {}
72 72 configitem = registrar.configitem(configtable)
73 73 configitem(
74 74 b'devel',
75 75 b'rebase.force-in-memory-merge',
76 76 default=False,
77 77 )
78 78 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
79 79 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
80 80 # be specifying the version(s) of Mercurial they are tested with, or
81 81 # leave the attribute unspecified.
82 82 testedwith = b'ships-with-hg-core'
83 83
84 84
85 85 def _nothingtorebase():
86 86 return 1
87 87
88 88
89 89 def _savegraft(ctx, extra):
90 90 s = ctx.extra().get(b'source', None)
91 91 if s is not None:
92 92 extra[b'source'] = s
93 93 s = ctx.extra().get(b'intermediate-source', None)
94 94 if s is not None:
95 95 extra[b'intermediate-source'] = s
96 96
97 97
98 98 def _savebranch(ctx, extra):
99 99 extra[b'branch'] = ctx.branch()
100 100
101 101
102 102 def _destrebase(repo, sourceset, destspace=None):
103 103 """small wrapper around destmerge to pass the right extra args
104 104
105 105 Please wrap destutil.destmerge instead."""
106 106 return destutil.destmerge(
107 107 repo,
108 108 action=b'rebase',
109 109 sourceset=sourceset,
110 110 onheadcheck=False,
111 111 destspace=destspace,
112 112 )
113 113
114 114
115 115 revsetpredicate = registrar.revsetpredicate()
116 116
117 117
118 118 @revsetpredicate(b'_destrebase')
119 119 def _revsetdestrebase(repo, subset, x):
120 120 # ``_rebasedefaultdest()``
121 121
122 122 # default destination for rebase.
123 123 # # XXX: Currently private because I expect the signature to change.
124 124 # # XXX: - bailing out in case of ambiguity vs returning all data.
125 125 # i18n: "_rebasedefaultdest" is a keyword
126 126 sourceset = None
127 127 if x is not None:
128 128 sourceset = revset.getset(repo, smartset.fullreposet(repo), x)
129 129 return subset & smartset.baseset([_destrebase(repo, sourceset)])
130 130
131 131
132 132 @revsetpredicate(b'_destautoorphanrebase')
133 133 def _revsetdestautoorphanrebase(repo, subset, x):
134 134 # ``_destautoorphanrebase()``
135 135
136 136 # automatic rebase destination for a single orphan revision.
137 137 unfi = repo.unfiltered()
138 138 obsoleted = unfi.revs(b'obsolete()')
139 139
140 140 src = revset.getset(repo, subset, x).first()
141 141
142 142 # Empty src or already obsoleted - Do not return a destination
143 143 if not src or src in obsoleted:
144 144 return smartset.baseset()
145 145 dests = destutil.orphanpossibledestination(repo, src)
146 146 if len(dests) > 1:
147 raise error.Abort(
147 raise error.StateError(
148 148 _(b"ambiguous automatic rebase: %r could end up on any of %r")
149 149 % (src, dests)
150 150 )
151 151 # We have zero or one destination, so we can just return here.
152 152 return smartset.baseset(dests)
153 153
154 154
155 155 def _ctxdesc(ctx):
156 156 """short description for a context"""
157 157 return cmdutil.format_changeset_summary(
158 158 ctx.repo().ui, ctx, command=b'rebase'
159 159 )
160 160
161 161
162 162 class rebaseruntime(object):
163 163 """This class is a container for rebase runtime state"""
164 164
165 165 def __init__(self, repo, ui, inmemory=False, dryrun=False, opts=None):
166 166 if opts is None:
167 167 opts = {}
168 168
169 169 # prepared: whether we have rebasestate prepared or not. Currently it
170 170 # decides whether "self.repo" is unfiltered or not.
171 171 # The rebasestate has explicit hash to hash instructions not depending
172 172 # on visibility. If rebasestate exists (in-memory or on-disk), use
173 173 # unfiltered repo to avoid visibility issues.
174 174 # Before knowing rebasestate (i.e. when starting a new rebase (not
175 175 # --continue or --abort)), the original repo should be used so
176 176 # visibility-dependent revsets are correct.
177 177 self.prepared = False
178 178 self.resume = False
179 179 self._repo = repo
180 180
181 181 self.ui = ui
182 182 self.opts = opts
183 183 self.originalwd = None
184 184 self.external = nullrev
185 185 # Mapping between the old revision id and either what is the new rebased
186 186 # revision or what needs to be done with the old revision. The state
187 187 # dict will be what contains most of the rebase progress state.
188 188 self.state = {}
189 189 self.activebookmark = None
190 190 self.destmap = {}
191 191 self.skipped = set()
192 192
193 193 self.collapsef = opts.get(b'collapse', False)
194 194 self.collapsemsg = cmdutil.logmessage(ui, opts)
195 195 self.date = opts.get(b'date', None)
196 196
197 197 e = opts.get(b'extrafn') # internal, used by e.g. hgsubversion
198 198 self.extrafns = [_savegraft]
199 199 if e:
200 200 self.extrafns = [e]
201 201
202 202 self.backupf = ui.configbool(b'rewrite', b'backup-bundle')
203 203 self.keepf = opts.get(b'keep', False)
204 204 self.keepbranchesf = opts.get(b'keepbranches', False)
205 205 self.skipemptysuccessorf = rewriteutil.skip_empty_successor(
206 206 repo.ui, b'rebase'
207 207 )
208 208 self.obsoletenotrebased = {}
209 209 self.obsoletewithoutsuccessorindestination = set()
210 210 self.inmemory = inmemory
211 211 self.dryrun = dryrun
212 212 self.stateobj = statemod.cmdstate(repo, b'rebasestate')
213 213
214 214 @property
215 215 def repo(self):
216 216 if self.prepared:
217 217 return self._repo.unfiltered()
218 218 else:
219 219 return self._repo
220 220
221 221 def storestatus(self, tr=None):
222 222 """Store the current status to allow recovery"""
223 223 if tr:
224 224 tr.addfilegenerator(
225 225 b'rebasestate',
226 226 (b'rebasestate',),
227 227 self._writestatus,
228 228 location=b'plain',
229 229 )
230 230 else:
231 231 with self.repo.vfs(b"rebasestate", b"w") as f:
232 232 self._writestatus(f)
233 233
234 234 def _writestatus(self, f):
235 235 repo = self.repo
236 236 assert repo.filtername is None
237 237 f.write(repo[self.originalwd].hex() + b'\n')
238 238 # was "dest". we now write dest per src root below.
239 239 f.write(b'\n')
240 240 f.write(repo[self.external].hex() + b'\n')
241 241 f.write(b'%d\n' % int(self.collapsef))
242 242 f.write(b'%d\n' % int(self.keepf))
243 243 f.write(b'%d\n' % int(self.keepbranchesf))
244 244 f.write(b'%s\n' % (self.activebookmark or b''))
245 245 destmap = self.destmap
246 246 for d, v in pycompat.iteritems(self.state):
247 247 oldrev = repo[d].hex()
248 248 if v >= 0:
249 249 newrev = repo[v].hex()
250 250 else:
251 251 newrev = b"%d" % v
252 252 destnode = repo[destmap[d]].hex()
253 253 f.write(b"%s:%s:%s\n" % (oldrev, newrev, destnode))
254 254 repo.ui.debug(b'rebase status stored\n')
255 255
256 256 def restorestatus(self):
257 257 """Restore a previously stored status"""
258 258 if not self.stateobj.exists():
259 259 cmdutil.wrongtooltocontinue(self.repo, _(b'rebase'))
260 260
261 261 data = self._read()
262 262 self.repo.ui.debug(b'rebase status resumed\n')
263 263
264 264 self.originalwd = data[b'originalwd']
265 265 self.destmap = data[b'destmap']
266 266 self.state = data[b'state']
267 267 self.skipped = data[b'skipped']
268 268 self.collapsef = data[b'collapse']
269 269 self.keepf = data[b'keep']
270 270 self.keepbranchesf = data[b'keepbranches']
271 271 self.external = data[b'external']
272 272 self.activebookmark = data[b'activebookmark']
273 273
274 274 def _read(self):
275 275 self.prepared = True
276 276 repo = self.repo
277 277 assert repo.filtername is None
278 278 data = {
279 279 b'keepbranches': None,
280 280 b'collapse': None,
281 281 b'activebookmark': None,
282 282 b'external': nullrev,
283 283 b'keep': None,
284 284 b'originalwd': None,
285 285 }
286 286 legacydest = None
287 287 state = {}
288 288 destmap = {}
289 289
290 290 if True:
291 291 f = repo.vfs(b"rebasestate")
292 292 for i, l in enumerate(f.read().splitlines()):
293 293 if i == 0:
294 294 data[b'originalwd'] = repo[l].rev()
295 295 elif i == 1:
296 296 # this line should be empty in newer version. but legacy
297 297 # clients may still use it
298 298 if l:
299 299 legacydest = repo[l].rev()
300 300 elif i == 2:
301 301 data[b'external'] = repo[l].rev()
302 302 elif i == 3:
303 303 data[b'collapse'] = bool(int(l))
304 304 elif i == 4:
305 305 data[b'keep'] = bool(int(l))
306 306 elif i == 5:
307 307 data[b'keepbranches'] = bool(int(l))
308 308 elif i == 6 and not (len(l) == 81 and b':' in l):
309 309 # line 6 is a recent addition, so for backwards
310 310 # compatibility check that the line doesn't look like the
311 311 # oldrev:newrev lines
312 312 data[b'activebookmark'] = l
313 313 else:
314 314 args = l.split(b':')
315 315 oldrev = repo[args[0]].rev()
316 316 newrev = args[1]
317 317 if newrev in legacystates:
318 318 continue
319 319 if len(args) > 2:
320 320 destrev = repo[args[2]].rev()
321 321 else:
322 322 destrev = legacydest
323 323 destmap[oldrev] = destrev
324 324 if newrev == revtodostr:
325 325 state[oldrev] = revtodo
326 326 # Legacy compat special case
327 327 else:
328 328 state[oldrev] = repo[newrev].rev()
329 329
330 330 if data[b'keepbranches'] is None:
331 331 raise error.Abort(_(b'.hg/rebasestate is incomplete'))
332 332
333 333 data[b'destmap'] = destmap
334 334 data[b'state'] = state
335 335 skipped = set()
336 336 # recompute the set of skipped revs
337 337 if not data[b'collapse']:
338 338 seen = set(destmap.values())
339 339 for old, new in sorted(state.items()):
340 340 if new != revtodo and new in seen:
341 341 skipped.add(old)
342 342 seen.add(new)
343 343 data[b'skipped'] = skipped
344 344 repo.ui.debug(
345 345 b'computed skipped revs: %s\n'
346 346 % (b' '.join(b'%d' % r for r in sorted(skipped)) or b'')
347 347 )
348 348
349 349 return data
350 350
351 351 def _handleskippingobsolete(self, obsoleterevs, destmap):
352 352 """Compute structures necessary for skipping obsolete revisions
353 353
354 354 obsoleterevs: iterable of all obsolete revisions in rebaseset
355 355 destmap: {srcrev: destrev} destination revisions
356 356 """
357 357 self.obsoletenotrebased = {}
358 358 if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
359 359 return
360 360 obsoleteset = set(obsoleterevs)
361 361 (
362 362 self.obsoletenotrebased,
363 363 self.obsoletewithoutsuccessorindestination,
364 364 obsoleteextinctsuccessors,
365 365 ) = _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
366 366 skippedset = set(self.obsoletenotrebased)
367 367 skippedset.update(self.obsoletewithoutsuccessorindestination)
368 368 skippedset.update(obsoleteextinctsuccessors)
369 369 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
370 370
371 371 def _prepareabortorcontinue(
372 372 self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False
373 373 ):
374 374 self.resume = True
375 375 try:
376 376 self.restorestatus()
377 377 self.collapsemsg = restorecollapsemsg(self.repo, isabort)
378 378 except error.RepoLookupError:
379 379 if isabort:
380 380 clearstatus(self.repo)
381 381 clearcollapsemsg(self.repo)
382 382 self.repo.ui.warn(
383 383 _(
384 384 b'rebase aborted (no revision is removed,'
385 385 b' only broken state is cleared)\n'
386 386 )
387 387 )
388 388 return 0
389 389 else:
390 390 msg = _(b'cannot continue inconsistent rebase')
391 391 hint = _(b'use "hg rebase --abort" to clear broken state')
392 392 raise error.Abort(msg, hint=hint)
393 393
394 394 if isabort:
395 395 backup = backup and self.backupf
396 396 return self._abort(
397 397 backup=backup,
398 398 suppwarns=suppwarns,
399 399 dryrun=dryrun,
400 400 confirm=confirm,
401 401 )
402 402
403 403 def _preparenewrebase(self, destmap):
404 404 if not destmap:
405 405 return _nothingtorebase()
406 406
407 407 rebaseset = destmap.keys()
408 408 if not self.keepf:
409 409 try:
410 410 rewriteutil.precheck(self.repo, rebaseset, action=b'rebase')
411 411 except error.Abort as e:
412 412 if e.hint is None:
413 413 e.hint = _(b'use --keep to keep original changesets')
414 414 raise e
415 415
416 416 result = buildstate(self.repo, destmap, self.collapsef)
417 417
418 418 if not result:
419 419 # Empty state built, nothing to rebase
420 420 self.ui.status(_(b'nothing to rebase\n'))
421 421 return _nothingtorebase()
422 422
423 423 (self.originalwd, self.destmap, self.state) = result
424 424 if self.collapsef:
425 425 dests = set(self.destmap.values())
426 426 if len(dests) != 1:
427 raise error.Abort(
427 raise error.InputError(
428 428 _(b'--collapse does not work with multiple destinations')
429 429 )
430 430 destrev = next(iter(dests))
431 431 destancestors = self.repo.changelog.ancestors(
432 432 [destrev], inclusive=True
433 433 )
434 434 self.external = externalparent(self.repo, self.state, destancestors)
435 435
436 436 for destrev in sorted(set(destmap.values())):
437 437 dest = self.repo[destrev]
438 438 if dest.closesbranch() and not self.keepbranchesf:
439 439 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
440 440
441 441 self.prepared = True
442 442
443 443 def _assignworkingcopy(self):
444 444 if self.inmemory:
445 445 from mercurial.context import overlayworkingctx
446 446
447 447 self.wctx = overlayworkingctx(self.repo)
448 448 self.repo.ui.debug(b"rebasing in memory\n")
449 449 else:
450 450 self.wctx = self.repo[None]
451 451 self.repo.ui.debug(b"rebasing on disk\n")
452 452 self.repo.ui.log(
453 453 b"rebase",
454 454 b"using in-memory rebase: %r\n",
455 455 self.inmemory,
456 456 rebase_imm_used=self.inmemory,
457 457 )
458 458
459 459 def _performrebase(self, tr):
460 460 self._assignworkingcopy()
461 461 repo, ui = self.repo, self.ui
462 462 if self.keepbranchesf:
463 463 # insert _savebranch at the start of extrafns so if
464 464 # there's a user-provided extrafn it can clobber branch if
465 465 # desired
466 466 self.extrafns.insert(0, _savebranch)
467 467 if self.collapsef:
468 468 branches = set()
469 469 for rev in self.state:
470 470 branches.add(repo[rev].branch())
471 471 if len(branches) > 1:
472 raise error.Abort(
472 raise error.InputError(
473 473 _(b'cannot collapse multiple named branches')
474 474 )
475 475
476 476 # Calculate self.obsoletenotrebased
477 477 obsrevs = _filterobsoleterevs(self.repo, self.state)
478 478 self._handleskippingobsolete(obsrevs, self.destmap)
479 479
480 480 # Keep track of the active bookmarks in order to reset them later
481 481 self.activebookmark = self.activebookmark or repo._activebookmark
482 482 if self.activebookmark:
483 483 bookmarks.deactivate(repo)
484 484
485 485 # Store the state before we begin so users can run 'hg rebase --abort'
486 486 # if we fail before the transaction closes.
487 487 self.storestatus()
488 488 if tr:
489 489 # When using single transaction, store state when transaction
490 490 # commits.
491 491 self.storestatus(tr)
492 492
493 493 cands = [k for k, v in pycompat.iteritems(self.state) if v == revtodo]
494 494 p = repo.ui.makeprogress(
495 495 _(b"rebasing"), unit=_(b'changesets'), total=len(cands)
496 496 )
497 497
498 498 def progress(ctx):
499 499 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx)))
500 500
501 501 allowdivergence = self.ui.configbool(
502 502 b'experimental', b'evolution.allowdivergence'
503 503 )
504 504 for subset in sortsource(self.destmap):
505 505 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
506 506 if not allowdivergence:
507 507 sortedrevs -= self.repo.revs(
508 508 b'descendants(%ld) and not %ld',
509 509 self.obsoletewithoutsuccessorindestination,
510 510 self.obsoletewithoutsuccessorindestination,
511 511 )
512 512 for rev in sortedrevs:
513 513 self._rebasenode(tr, rev, allowdivergence, progress)
514 514 p.complete()
515 515 ui.note(_(b'rebase merging completed\n'))
516 516
517 517 def _concludenode(self, rev, editor, commitmsg=None):
518 518 """Commit the wd changes with parents p1 and p2.
519 519
520 520 Reuse commit info from rev but also store useful information in extra.
521 521 Return node of committed revision."""
522 522 repo = self.repo
523 523 ctx = repo[rev]
524 524 if commitmsg is None:
525 525 commitmsg = ctx.description()
526 526
527 527 # Skip replacement if collapsing, as that degenerates to p1 for all
528 528 # nodes.
529 529 if not self.collapsef:
530 530 cl = repo.changelog
531 531 commitmsg = rewriteutil.update_hash_refs(
532 532 repo,
533 533 commitmsg,
534 534 {
535 535 cl.node(oldrev): [cl.node(newrev)]
536 536 for oldrev, newrev in self.state.items()
537 537 if newrev != revtodo
538 538 },
539 539 )
540 540
541 541 date = self.date
542 542 if date is None:
543 543 date = ctx.date()
544 544 extra = {b'rebase_source': ctx.hex()}
545 545 for c in self.extrafns:
546 546 c(ctx, extra)
547 547 destphase = max(ctx.phase(), phases.draft)
548 548 overrides = {
549 549 (b'phases', b'new-commit'): destphase,
550 550 (b'ui', b'allowemptycommit'): not self.skipemptysuccessorf,
551 551 }
552 552 with repo.ui.configoverride(overrides, b'rebase'):
553 553 if self.inmemory:
554 554 newnode = commitmemorynode(
555 555 repo,
556 556 wctx=self.wctx,
557 557 extra=extra,
558 558 commitmsg=commitmsg,
559 559 editor=editor,
560 560 user=ctx.user(),
561 561 date=date,
562 562 )
563 563 else:
564 564 newnode = commitnode(
565 565 repo,
566 566 extra=extra,
567 567 commitmsg=commitmsg,
568 568 editor=editor,
569 569 user=ctx.user(),
570 570 date=date,
571 571 )
572 572
573 573 return newnode
574 574
575 575 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
576 576 repo, ui, opts = self.repo, self.ui, self.opts
577 577 ctx = repo[rev]
578 578 desc = _ctxdesc(ctx)
579 579 if self.state[rev] == rev:
580 580 ui.status(_(b'already rebased %s\n') % desc)
581 581 elif (
582 582 not allowdivergence
583 583 and rev in self.obsoletewithoutsuccessorindestination
584 584 ):
585 585 msg = (
586 586 _(
587 587 b'note: not rebasing %s and its descendants as '
588 588 b'this would cause divergence\n'
589 589 )
590 590 % desc
591 591 )
592 592 repo.ui.status(msg)
593 593 self.skipped.add(rev)
594 594 elif rev in self.obsoletenotrebased:
595 595 succ = self.obsoletenotrebased[rev]
596 596 if succ is None:
597 597 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
598 598 else:
599 599 succdesc = _ctxdesc(repo[succ])
600 600 msg = _(
601 601 b'note: not rebasing %s, already in destination as %s\n'
602 602 ) % (desc, succdesc)
603 603 repo.ui.status(msg)
604 604 # Make clearrebased aware state[rev] is not a true successor
605 605 self.skipped.add(rev)
606 606 # Record rev as moved to its desired destination in self.state.
607 607 # This helps bookmark and working parent movement.
608 608 dest = max(
609 609 adjustdest(repo, rev, self.destmap, self.state, self.skipped)
610 610 )
611 611 self.state[rev] = dest
612 612 elif self.state[rev] == revtodo:
613 613 ui.status(_(b'rebasing %s\n') % desc)
614 614 progressfn(ctx)
615 615 p1, p2, base = defineparents(
616 616 repo,
617 617 rev,
618 618 self.destmap,
619 619 self.state,
620 620 self.skipped,
621 621 self.obsoletenotrebased,
622 622 )
623 623 if self.resume and self.wctx.p1().rev() == p1:
624 624 repo.ui.debug(b'resuming interrupted rebase\n')
625 625 self.resume = False
626 626 else:
627 627 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
628 628 with ui.configoverride(overrides, b'rebase'):
629 629 try:
630 630 rebasenode(
631 631 repo,
632 632 rev,
633 633 p1,
634 634 p2,
635 635 base,
636 636 self.collapsef,
637 637 wctx=self.wctx,
638 638 )
639 639 except error.InMemoryMergeConflictsError:
640 640 if self.dryrun:
641 641 raise error.ConflictResolutionRequired(b'rebase')
642 642 if self.collapsef:
643 643 # TODO: Make the overlayworkingctx reflected
644 644 # in the working copy here instead of re-raising
645 645 # so the entire rebase operation is retried.
646 646 raise
647 647 ui.status(
648 648 _(
649 649 b"hit merge conflicts; rebasing that "
650 650 b"commit again in the working copy\n"
651 651 )
652 652 )
653 653 try:
654 654 cmdutil.bailifchanged(repo)
655 655 except error.Abort:
656 656 clearstatus(repo)
657 657 clearcollapsemsg(repo)
658 658 raise
659 659 self.inmemory = False
660 660 self._assignworkingcopy()
661 661 mergemod.update(repo[p1], wc=self.wctx)
662 662 rebasenode(
663 663 repo,
664 664 rev,
665 665 p1,
666 666 p2,
667 667 base,
668 668 self.collapsef,
669 669 wctx=self.wctx,
670 670 )
671 671 if not self.collapsef:
672 672 merging = p2 != nullrev
673 673 editform = cmdutil.mergeeditform(merging, b'rebase')
674 674 editor = cmdutil.getcommiteditor(
675 675 editform=editform, **pycompat.strkwargs(opts)
676 676 )
677 677 # We need to set parents again here just in case we're continuing
678 678 # a rebase started with an old hg version (before 9c9cfecd4600),
679 679 # because those old versions would have left us with two dirstate
680 680 # parents, and we don't want to create a merge commit here (unless
681 681 # we're rebasing a merge commit).
682 682 self.wctx.setparents(repo[p1].node(), repo[p2].node())
683 683 newnode = self._concludenode(rev, editor)
684 684 else:
685 685 # Skip commit if we are collapsing
686 686 newnode = None
687 687 # Update the state
688 688 if newnode is not None:
689 689 self.state[rev] = repo[newnode].rev()
690 690 ui.debug(b'rebased as %s\n' % short(newnode))
691 691 if repo[newnode].isempty():
692 692 ui.warn(
693 693 _(
694 694 b'note: created empty successor for %s, its '
695 695 b'destination already has all its changes\n'
696 696 )
697 697 % desc
698 698 )
699 699 else:
700 700 if not self.collapsef:
701 701 ui.warn(
702 702 _(
703 703 b'note: not rebasing %s, its destination already '
704 704 b'has all its changes\n'
705 705 )
706 706 % desc
707 707 )
708 708 self.skipped.add(rev)
709 709 self.state[rev] = p1
710 710 ui.debug(b'next revision set to %d\n' % p1)
711 711 else:
712 712 ui.status(
713 713 _(b'already rebased %s as %s\n') % (desc, repo[self.state[rev]])
714 714 )
715 715 if not tr:
716 716 # When not using single transaction, store state after each
717 717 # commit is completely done. On InterventionRequired, we thus
718 718 # won't store the status. Instead, we'll hit the "len(parents) == 2"
719 719 # case and realize that the commit was in progress.
720 720 self.storestatus()
721 721
722 722 def _finishrebase(self):
723 723 repo, ui, opts = self.repo, self.ui, self.opts
724 724 fm = ui.formatter(b'rebase', opts)
725 725 fm.startitem()
726 726 if self.collapsef:
727 727 p1, p2, _base = defineparents(
728 728 repo,
729 729 min(self.state),
730 730 self.destmap,
731 731 self.state,
732 732 self.skipped,
733 733 self.obsoletenotrebased,
734 734 )
735 735 editopt = opts.get(b'edit')
736 736 editform = b'rebase.collapse'
737 737 if self.collapsemsg:
738 738 commitmsg = self.collapsemsg
739 739 else:
740 740 commitmsg = b'Collapsed revision'
741 741 for rebased in sorted(self.state):
742 742 if rebased not in self.skipped:
743 743 commitmsg += b'\n* %s' % repo[rebased].description()
744 744 editopt = True
745 745 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
746 746 revtoreuse = max(self.state)
747 747
748 748 self.wctx.setparents(repo[p1].node(), repo[self.external].node())
749 749 newnode = self._concludenode(
750 750 revtoreuse, editor, commitmsg=commitmsg
751 751 )
752 752
753 753 if newnode is not None:
754 754 newrev = repo[newnode].rev()
755 755 for oldrev in self.state:
756 756 self.state[oldrev] = newrev
757 757
758 758 if b'qtip' in repo.tags():
759 759 updatemq(repo, self.state, self.skipped, **pycompat.strkwargs(opts))
760 760
761 761 # restore original working directory
762 762 # (we do this before stripping)
763 763 newwd = self.state.get(self.originalwd, self.originalwd)
764 764 if newwd < 0:
765 765 # original directory is a parent of rebase set root or ignored
766 766 newwd = self.originalwd
767 767 if newwd not in [c.rev() for c in repo[None].parents()]:
768 768 ui.note(_(b"update back to initial working directory parent\n"))
769 769 mergemod.update(repo[newwd])
770 770
771 771 collapsedas = None
772 772 if self.collapsef and not self.keepf:
773 773 collapsedas = newnode
774 774 clearrebased(
775 775 ui,
776 776 repo,
777 777 self.destmap,
778 778 self.state,
779 779 self.skipped,
780 780 collapsedas,
781 781 self.keepf,
782 782 fm=fm,
783 783 backup=self.backupf,
784 784 )
785 785
786 786 clearstatus(repo)
787 787 clearcollapsemsg(repo)
788 788
789 789 ui.note(_(b"rebase completed\n"))
790 790 util.unlinkpath(repo.sjoin(b'undo'), ignoremissing=True)
791 791 if self.skipped:
792 792 skippedlen = len(self.skipped)
793 793 ui.note(_(b"%d revisions have been skipped\n") % skippedlen)
794 794 fm.end()
795 795
796 796 if (
797 797 self.activebookmark
798 798 and self.activebookmark in repo._bookmarks
799 799 and repo[b'.'].node() == repo._bookmarks[self.activebookmark]
800 800 ):
801 801 bookmarks.activate(repo, self.activebookmark)
802 802
803 803 def _abort(self, backup=True, suppwarns=False, dryrun=False, confirm=False):
804 804 '''Restore the repository to its original state.'''
805 805
806 806 repo = self.repo
807 807 try:
808 808 # If the first commits in the rebased set get skipped during the
809 809 # rebase, their values within the state mapping will be the dest
810 810 # rev id. The rebased list must must not contain the dest rev
811 811 # (issue4896)
812 812 rebased = [
813 813 s
814 814 for r, s in self.state.items()
815 815 if s >= 0 and s != r and s != self.destmap[r]
816 816 ]
817 817 immutable = [d for d in rebased if not repo[d].mutable()]
818 818 cleanup = True
819 819 if immutable:
820 820 repo.ui.warn(
821 821 _(b"warning: can't clean up public changesets %s\n")
822 822 % b', '.join(bytes(repo[r]) for r in immutable),
823 823 hint=_(b"see 'hg help phases' for details"),
824 824 )
825 825 cleanup = False
826 826
827 827 descendants = set()
828 828 if rebased:
829 829 descendants = set(repo.changelog.descendants(rebased))
830 830 if descendants - set(rebased):
831 831 repo.ui.warn(
832 832 _(
833 833 b"warning: new changesets detected on "
834 834 b"destination branch, can't strip\n"
835 835 )
836 836 )
837 837 cleanup = False
838 838
839 839 if cleanup:
840 840 if rebased:
841 841 strippoints = [
842 842 c.node() for c in repo.set(b'roots(%ld)', rebased)
843 843 ]
844 844
845 845 updateifonnodes = set(rebased)
846 846 updateifonnodes.update(self.destmap.values())
847 847
848 848 if not dryrun and not confirm:
849 849 updateifonnodes.add(self.originalwd)
850 850
851 851 shouldupdate = repo[b'.'].rev() in updateifonnodes
852 852
853 853 # Update away from the rebase if necessary
854 854 if shouldupdate:
855 855 mergemod.clean_update(repo[self.originalwd])
856 856
857 857 # Strip from the first rebased revision
858 858 if rebased:
859 859 repair.strip(repo.ui, repo, strippoints, backup=backup)
860 860
861 861 if self.activebookmark and self.activebookmark in repo._bookmarks:
862 862 bookmarks.activate(repo, self.activebookmark)
863 863
864 864 finally:
865 865 clearstatus(repo)
866 866 clearcollapsemsg(repo)
867 867 if not suppwarns:
868 868 repo.ui.warn(_(b'rebase aborted\n'))
869 869 return 0
870 870
871 871
872 872 @command(
873 873 b'rebase',
874 874 [
875 875 (
876 876 b's',
877 877 b'source',
878 878 [],
879 879 _(b'rebase the specified changesets and their descendants'),
880 880 _(b'REV'),
881 881 ),
882 882 (
883 883 b'b',
884 884 b'base',
885 885 [],
886 886 _(b'rebase everything from branching point of specified changeset'),
887 887 _(b'REV'),
888 888 ),
889 889 (b'r', b'rev', [], _(b'rebase these revisions'), _(b'REV')),
890 890 (
891 891 b'd',
892 892 b'dest',
893 893 b'',
894 894 _(b'rebase onto the specified changeset'),
895 895 _(b'REV'),
896 896 ),
897 897 (b'', b'collapse', False, _(b'collapse the rebased changesets')),
898 898 (
899 899 b'm',
900 900 b'message',
901 901 b'',
902 902 _(b'use text as collapse commit message'),
903 903 _(b'TEXT'),
904 904 ),
905 905 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
906 906 (
907 907 b'l',
908 908 b'logfile',
909 909 b'',
910 910 _(b'read collapse commit message from file'),
911 911 _(b'FILE'),
912 912 ),
913 913 (b'k', b'keep', False, _(b'keep original changesets')),
914 914 (b'', b'keepbranches', False, _(b'keep original branch names')),
915 915 (b'D', b'detach', False, _(b'(DEPRECATED)')),
916 916 (b'i', b'interactive', False, _(b'(DEPRECATED)')),
917 917 (b't', b'tool', b'', _(b'specify merge tool')),
918 918 (b'', b'stop', False, _(b'stop interrupted rebase')),
919 919 (b'c', b'continue', False, _(b'continue an interrupted rebase')),
920 920 (b'a', b'abort', False, _(b'abort an interrupted rebase')),
921 921 (
922 922 b'',
923 923 b'auto-orphans',
924 924 b'',
925 925 _(
926 926 b'automatically rebase orphan revisions '
927 927 b'in the specified revset (EXPERIMENTAL)'
928 928 ),
929 929 ),
930 930 ]
931 931 + cmdutil.dryrunopts
932 932 + cmdutil.formatteropts
933 933 + cmdutil.confirmopts,
934 934 _(b'[[-s REV]... | [-b REV]... | [-r REV]...] [-d REV] [OPTION]...'),
935 935 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
936 936 )
937 937 def rebase(ui, repo, **opts):
938 938 """move changeset (and descendants) to a different branch
939 939
940 940 Rebase uses repeated merging to graft changesets from one part of
941 941 history (the source) onto another (the destination). This can be
942 942 useful for linearizing *local* changes relative to a master
943 943 development tree.
944 944
945 945 Published commits cannot be rebased (see :hg:`help phases`).
946 946 To copy commits, see :hg:`help graft`.
947 947
948 948 If you don't specify a destination changeset (``-d/--dest``), rebase
949 949 will use the same logic as :hg:`merge` to pick a destination. if
950 950 the current branch contains exactly one other head, the other head
951 951 is merged with by default. Otherwise, an explicit revision with
952 952 which to merge with must be provided. (destination changeset is not
953 953 modified by rebasing, but new changesets are added as its
954 954 descendants.)
955 955
956 956 Here are the ways to select changesets:
957 957
958 958 1. Explicitly select them using ``--rev``.
959 959
960 960 2. Use ``--source`` to select a root changeset and include all of its
961 961 descendants.
962 962
963 963 3. Use ``--base`` to select a changeset; rebase will find ancestors
964 964 and their descendants which are not also ancestors of the destination.
965 965
966 966 4. If you do not specify any of ``--rev``, ``--source``, or ``--base``,
967 967 rebase will use ``--base .`` as above.
968 968
969 969 If ``--source`` or ``--rev`` is used, special names ``SRC`` and ``ALLSRC``
970 970 can be used in ``--dest``. Destination would be calculated per source
971 971 revision with ``SRC`` substituted by that single source revision and
972 972 ``ALLSRC`` substituted by all source revisions.
973 973
974 974 Rebase will destroy original changesets unless you use ``--keep``.
975 975 It will also move your bookmarks (even if you do).
976 976
977 977 Some changesets may be dropped if they do not contribute changes
978 978 (e.g. merges from the destination branch).
979 979
980 980 Unlike ``merge``, rebase will do nothing if you are at the branch tip of
981 981 a named branch with two heads. You will need to explicitly specify source
982 982 and/or destination.
983 983
984 984 If you need to use a tool to automate merge/conflict decisions, you
985 985 can specify one with ``--tool``, see :hg:`help merge-tools`.
986 986 As a caveat: the tool will not be used to mediate when a file was
987 987 deleted, there is no hook presently available for this.
988 988
989 989 If a rebase is interrupted to manually resolve a conflict, it can be
990 990 continued with --continue/-c, aborted with --abort/-a, or stopped with
991 991 --stop.
992 992
993 993 .. container:: verbose
994 994
995 995 Examples:
996 996
997 997 - move "local changes" (current commit back to branching point)
998 998 to the current branch tip after a pull::
999 999
1000 1000 hg rebase
1001 1001
1002 1002 - move a single changeset to the stable branch::
1003 1003
1004 1004 hg rebase -r 5f493448 -d stable
1005 1005
1006 1006 - splice a commit and all its descendants onto another part of history::
1007 1007
1008 1008 hg rebase --source c0c3 --dest 4cf9
1009 1009
1010 1010 - rebase everything on a branch marked by a bookmark onto the
1011 1011 default branch::
1012 1012
1013 1013 hg rebase --base myfeature --dest default
1014 1014
1015 1015 - collapse a sequence of changes into a single commit::
1016 1016
1017 1017 hg rebase --collapse -r 1520:1525 -d .
1018 1018
1019 1019 - move a named branch while preserving its name::
1020 1020
1021 1021 hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
1022 1022
1023 1023 - stabilize orphaned changesets so history looks linear::
1024 1024
1025 1025 hg rebase -r 'orphan()-obsolete()'\
1026 1026 -d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
1027 1027 max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
1028 1028
1029 1029 Configuration Options:
1030 1030
1031 1031 You can make rebase require a destination if you set the following config
1032 1032 option::
1033 1033
1034 1034 [commands]
1035 1035 rebase.requiredest = True
1036 1036
1037 1037 By default, rebase will close the transaction after each commit. For
1038 1038 performance purposes, you can configure rebase to use a single transaction
1039 1039 across the entire rebase. WARNING: This setting introduces a significant
1040 1040 risk of losing the work you've done in a rebase if the rebase aborts
1041 1041 unexpectedly::
1042 1042
1043 1043 [rebase]
1044 1044 singletransaction = True
1045 1045
1046 1046 By default, rebase writes to the working copy, but you can configure it to
1047 1047 run in-memory for better performance. When the rebase is not moving the
1048 1048 parent(s) of the working copy (AKA the "currently checked out changesets"),
1049 1049 this may also allow it to run even if the working copy is dirty::
1050 1050
1051 1051 [rebase]
1052 1052 experimental.inmemory = True
1053 1053
1054 1054 Return Values:
1055 1055
1056 1056 Returns 0 on success, 1 if nothing to rebase or there are
1057 1057 unresolved conflicts.
1058 1058
1059 1059 """
1060 1060 opts = pycompat.byteskwargs(opts)
1061 1061 inmemory = ui.configbool(b'rebase', b'experimental.inmemory')
1062 1062 action = cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
1063 1063 if action:
1064 1064 cmdutil.check_incompatible_arguments(
1065 1065 opts, action, [b'confirm', b'dry_run']
1066 1066 )
1067 1067 cmdutil.check_incompatible_arguments(
1068 1068 opts, action, [b'rev', b'source', b'base', b'dest']
1069 1069 )
1070 1070 cmdutil.check_at_most_one_arg(opts, b'confirm', b'dry_run')
1071 1071 cmdutil.check_at_most_one_arg(opts, b'rev', b'source', b'base')
1072 1072
1073 1073 if action or repo.currenttransaction() is not None:
1074 1074 # in-memory rebase is not compatible with resuming rebases.
1075 1075 # (Or if it is run within a transaction, since the restart logic can
1076 1076 # fail the entire transaction.)
1077 1077 inmemory = False
1078 1078
1079 1079 if opts.get(b'auto_orphans'):
1080 1080 disallowed_opts = set(opts) - {b'auto_orphans'}
1081 1081 cmdutil.check_incompatible_arguments(
1082 1082 opts, b'auto_orphans', disallowed_opts
1083 1083 )
1084 1084
1085 1085 userrevs = list(repo.revs(opts.get(b'auto_orphans')))
1086 1086 opts[b'rev'] = [revsetlang.formatspec(b'%ld and orphan()', userrevs)]
1087 1087 opts[b'dest'] = b'_destautoorphanrebase(SRC)'
1088 1088
1089 1089 if opts.get(b'dry_run') or opts.get(b'confirm'):
1090 1090 return _dryrunrebase(ui, repo, action, opts)
1091 1091 elif action == b'stop':
1092 1092 rbsrt = rebaseruntime(repo, ui)
1093 1093 with repo.wlock(), repo.lock():
1094 1094 rbsrt.restorestatus()
1095 1095 if rbsrt.collapsef:
1096 raise error.Abort(_(b"cannot stop in --collapse session"))
1096 raise error.StateError(_(b"cannot stop in --collapse session"))
1097 1097 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1098 1098 if not (rbsrt.keepf or allowunstable):
1099 raise error.Abort(
1099 raise error.StateError(
1100 1100 _(
1101 1101 b"cannot remove original changesets with"
1102 1102 b" unrebased descendants"
1103 1103 ),
1104 1104 hint=_(
1105 1105 b'either enable obsmarkers to allow unstable '
1106 1106 b'revisions or use --keep to keep original '
1107 1107 b'changesets'
1108 1108 ),
1109 1109 )
1110 1110 # update to the current working revision
1111 1111 # to clear interrupted merge
1112 1112 mergemod.clean_update(repo[rbsrt.originalwd])
1113 1113 rbsrt._finishrebase()
1114 1114 return 0
1115 1115 elif inmemory:
1116 1116 try:
1117 1117 # in-memory merge doesn't support conflicts, so if we hit any, abort
1118 1118 # and re-run as an on-disk merge.
1119 1119 overrides = {(b'rebase', b'singletransaction'): True}
1120 1120 with ui.configoverride(overrides, b'rebase'):
1121 1121 return _dorebase(ui, repo, action, opts, inmemory=inmemory)
1122 1122 except error.InMemoryMergeConflictsError:
1123 1123 if ui.configbool(b'devel', b'rebase.force-in-memory-merge'):
1124 1124 raise
1125 1125 ui.warn(
1126 1126 _(
1127 1127 b'hit merge conflicts; re-running rebase without in-memory'
1128 1128 b' merge\n'
1129 1129 )
1130 1130 )
1131 1131 clearstatus(repo)
1132 1132 clearcollapsemsg(repo)
1133 1133 return _dorebase(ui, repo, action, opts, inmemory=False)
1134 1134 else:
1135 1135 return _dorebase(ui, repo, action, opts)
1136 1136
1137 1137
1138 1138 def _dryrunrebase(ui, repo, action, opts):
1139 1139 rbsrt = rebaseruntime(repo, ui, inmemory=True, dryrun=True, opts=opts)
1140 1140 confirm = opts.get(b'confirm')
1141 1141 if confirm:
1142 1142 ui.status(_(b'starting in-memory rebase\n'))
1143 1143 else:
1144 1144 ui.status(
1145 1145 _(b'starting dry-run rebase; repository will not be changed\n')
1146 1146 )
1147 1147 with repo.wlock(), repo.lock():
1148 1148 needsabort = True
1149 1149 try:
1150 1150 overrides = {(b'rebase', b'singletransaction'): True}
1151 1151 with ui.configoverride(overrides, b'rebase'):
1152 1152 res = _origrebase(
1153 1153 ui,
1154 1154 repo,
1155 1155 action,
1156 1156 opts,
1157 1157 rbsrt,
1158 1158 )
1159 1159 if res == _nothingtorebase():
1160 1160 needsabort = False
1161 1161 return res
1162 1162 except error.ConflictResolutionRequired:
1163 1163 ui.status(_(b'hit a merge conflict\n'))
1164 1164 return 1
1165 1165 except error.Abort:
1166 1166 needsabort = False
1167 1167 raise
1168 1168 else:
1169 1169 if confirm:
1170 1170 ui.status(_(b'rebase completed successfully\n'))
1171 1171 if not ui.promptchoice(_(b'apply changes (yn)?$$ &Yes $$ &No')):
1172 1172 # finish unfinished rebase
1173 1173 rbsrt._finishrebase()
1174 1174 else:
1175 1175 rbsrt._prepareabortorcontinue(
1176 1176 isabort=True,
1177 1177 backup=False,
1178 1178 suppwarns=True,
1179 1179 confirm=confirm,
1180 1180 )
1181 1181 needsabort = False
1182 1182 else:
1183 1183 ui.status(
1184 1184 _(
1185 1185 b'dry-run rebase completed successfully; run without'
1186 1186 b' -n/--dry-run to perform this rebase\n'
1187 1187 )
1188 1188 )
1189 1189 return 0
1190 1190 finally:
1191 1191 if needsabort:
1192 1192 # no need to store backup in case of dryrun
1193 1193 rbsrt._prepareabortorcontinue(
1194 1194 isabort=True,
1195 1195 backup=False,
1196 1196 suppwarns=True,
1197 1197 dryrun=opts.get(b'dry_run'),
1198 1198 )
1199 1199
1200 1200
1201 1201 def _dorebase(ui, repo, action, opts, inmemory=False):
1202 1202 rbsrt = rebaseruntime(repo, ui, inmemory, opts=opts)
1203 1203 return _origrebase(ui, repo, action, opts, rbsrt)
1204 1204
1205 1205
1206 1206 def _origrebase(ui, repo, action, opts, rbsrt):
1207 1207 assert action != b'stop'
1208 1208 with repo.wlock(), repo.lock():
1209 1209 if opts.get(b'interactive'):
1210 1210 try:
1211 1211 if extensions.find(b'histedit'):
1212 1212 enablehistedit = b''
1213 1213 except KeyError:
1214 1214 enablehistedit = b" --config extensions.histedit="
1215 1215 help = b"hg%s help -e histedit" % enablehistedit
1216 1216 msg = (
1217 1217 _(
1218 1218 b"interactive history editing is supported by the "
1219 1219 b"'histedit' extension (see \"%s\")"
1220 1220 )
1221 1221 % help
1222 1222 )
1223 raise error.Abort(msg)
1223 raise error.InputError(msg)
1224 1224
1225 1225 if rbsrt.collapsemsg and not rbsrt.collapsef:
1226 raise error.Abort(_(b'message can only be specified with collapse'))
1226 raise error.InputError(
1227 _(b'message can only be specified with collapse')
1228 )
1227 1229
1228 1230 if action:
1229 1231 if rbsrt.collapsef:
1230 raise error.Abort(
1232 raise error.InputError(
1231 1233 _(b'cannot use collapse with continue or abort')
1232 1234 )
1233 1235 if action == b'abort' and opts.get(b'tool', False):
1234 1236 ui.warn(_(b'tool option will be ignored\n'))
1235 1237 if action == b'continue':
1236 1238 ms = mergestatemod.mergestate.read(repo)
1237 1239 mergeutil.checkunresolved(ms)
1238 1240
1239 1241 retcode = rbsrt._prepareabortorcontinue(
1240 1242 isabort=(action == b'abort')
1241 1243 )
1242 1244 if retcode is not None:
1243 1245 return retcode
1244 1246 else:
1245 1247 # search default destination in this space
1246 1248 # used in the 'hg pull --rebase' case, see issue 5214.
1247 1249 destspace = opts.get(b'_destspace')
1248 1250 destmap = _definedestmap(
1249 1251 ui,
1250 1252 repo,
1251 1253 rbsrt.inmemory,
1252 1254 opts.get(b'dest', None),
1253 1255 opts.get(b'source', []),
1254 1256 opts.get(b'base', []),
1255 1257 opts.get(b'rev', []),
1256 1258 destspace=destspace,
1257 1259 )
1258 1260 retcode = rbsrt._preparenewrebase(destmap)
1259 1261 if retcode is not None:
1260 1262 return retcode
1261 1263 storecollapsemsg(repo, rbsrt.collapsemsg)
1262 1264
1263 1265 tr = None
1264 1266
1265 1267 singletr = ui.configbool(b'rebase', b'singletransaction')
1266 1268 if singletr:
1267 1269 tr = repo.transaction(b'rebase')
1268 1270
1269 1271 # If `rebase.singletransaction` is enabled, wrap the entire operation in
1270 1272 # one transaction here. Otherwise, transactions are obtained when
1271 1273 # committing each node, which is slower but allows partial success.
1272 1274 with util.acceptintervention(tr):
1273 1275 # Same logic for the dirstate guard, except we don't create one when
1274 1276 # rebasing in-memory (it's not needed).
1275 1277 dsguard = None
1276 1278 if singletr and not rbsrt.inmemory:
1277 1279 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1278 1280 with util.acceptintervention(dsguard):
1279 1281 rbsrt._performrebase(tr)
1280 1282 if not rbsrt.dryrun:
1281 1283 rbsrt._finishrebase()
1282 1284
1283 1285
1284 1286 def _definedestmap(ui, repo, inmemory, destf, srcf, basef, revf, destspace):
1285 1287 """use revisions argument to define destmap {srcrev: destrev}"""
1286 1288 if revf is None:
1287 1289 revf = []
1288 1290
1289 1291 # destspace is here to work around issues with `hg pull --rebase` see
1290 1292 # issue5214 for details
1291 1293
1292 1294 cmdutil.checkunfinished(repo)
1293 1295 if not inmemory:
1294 1296 cmdutil.bailifchanged(repo)
1295 1297
1296 1298 if ui.configbool(b'commands', b'rebase.requiredest') and not destf:
1297 raise error.Abort(
1299 raise error.InputError(
1298 1300 _(b'you must specify a destination'),
1299 1301 hint=_(b'use: hg rebase -d REV'),
1300 1302 )
1301 1303
1302 1304 dest = None
1303 1305
1304 1306 if revf:
1305 1307 rebaseset = scmutil.revrange(repo, revf)
1306 1308 if not rebaseset:
1307 1309 ui.status(_(b'empty "rev" revision set - nothing to rebase\n'))
1308 1310 return None
1309 1311 elif srcf:
1310 1312 src = scmutil.revrange(repo, srcf)
1311 1313 if not src:
1312 1314 ui.status(_(b'empty "source" revision set - nothing to rebase\n'))
1313 1315 return None
1314 1316 # `+ (%ld)` to work around `wdir()::` being empty
1315 1317 rebaseset = repo.revs(b'(%ld):: + (%ld)', src, src)
1316 1318 else:
1317 1319 base = scmutil.revrange(repo, basef or [b'.'])
1318 1320 if not base:
1319 1321 ui.status(
1320 1322 _(b'empty "base" revision set - ' b"can't compute rebase set\n")
1321 1323 )
1322 1324 return None
1323 1325 if destf:
1324 1326 # --base does not support multiple destinations
1325 1327 dest = scmutil.revsingle(repo, destf)
1326 1328 else:
1327 1329 dest = repo[_destrebase(repo, base, destspace=destspace)]
1328 1330 destf = bytes(dest)
1329 1331
1330 1332 roots = [] # selected children of branching points
1331 1333 bpbase = {} # {branchingpoint: [origbase]}
1332 1334 for b in base: # group bases by branching points
1333 1335 bp = repo.revs(b'ancestor(%d, %d)', b, dest.rev()).first()
1334 1336 bpbase[bp] = bpbase.get(bp, []) + [b]
1335 1337 if None in bpbase:
1336 1338 # emulate the old behavior, showing "nothing to rebase" (a better
1337 1339 # behavior may be abort with "cannot find branching point" error)
1338 1340 bpbase.clear()
1339 1341 for bp, bs in pycompat.iteritems(bpbase): # calculate roots
1340 1342 roots += list(repo.revs(b'children(%d) & ancestors(%ld)', bp, bs))
1341 1343
1342 1344 rebaseset = repo.revs(b'%ld::', roots)
1343 1345
1344 1346 if not rebaseset:
1345 1347 # transform to list because smartsets are not comparable to
1346 1348 # lists. This should be improved to honor laziness of
1347 1349 # smartset.
1348 1350 if list(base) == [dest.rev()]:
1349 1351 if basef:
1350 1352 ui.status(
1351 1353 _(
1352 1354 b'nothing to rebase - %s is both "base"'
1353 1355 b' and destination\n'
1354 1356 )
1355 1357 % dest
1356 1358 )
1357 1359 else:
1358 1360 ui.status(
1359 1361 _(
1360 1362 b'nothing to rebase - working directory '
1361 1363 b'parent is also destination\n'
1362 1364 )
1363 1365 )
1364 1366 elif not repo.revs(b'%ld - ::%d', base, dest.rev()):
1365 1367 if basef:
1366 1368 ui.status(
1367 1369 _(
1368 1370 b'nothing to rebase - "base" %s is '
1369 1371 b'already an ancestor of destination '
1370 1372 b'%s\n'
1371 1373 )
1372 1374 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1373 1375 )
1374 1376 else:
1375 1377 ui.status(
1376 1378 _(
1377 1379 b'nothing to rebase - working '
1378 1380 b'directory parent is already an '
1379 1381 b'ancestor of destination %s\n'
1380 1382 )
1381 1383 % dest
1382 1384 )
1383 1385 else: # can it happen?
1384 1386 ui.status(
1385 1387 _(b'nothing to rebase from %s to %s\n')
1386 1388 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1387 1389 )
1388 1390 return None
1389 1391
1390 1392 if wdirrev in rebaseset:
1391 raise error.Abort(_(b'cannot rebase the working copy'))
1393 raise error.InputError(_(b'cannot rebase the working copy'))
1392 1394 rebasingwcp = repo[b'.'].rev() in rebaseset
1393 1395 ui.log(
1394 1396 b"rebase",
1395 1397 b"rebasing working copy parent: %r\n",
1396 1398 rebasingwcp,
1397 1399 rebase_rebasing_wcp=rebasingwcp,
1398 1400 )
1399 1401 if inmemory and rebasingwcp:
1400 1402 # Check these since we did not before.
1401 1403 cmdutil.checkunfinished(repo)
1402 1404 cmdutil.bailifchanged(repo)
1403 1405
1404 1406 if not destf:
1405 1407 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
1406 1408 destf = bytes(dest)
1407 1409
1408 1410 allsrc = revsetlang.formatspec(b'%ld', rebaseset)
1409 1411 alias = {b'ALLSRC': allsrc}
1410 1412
1411 1413 if dest is None:
1412 1414 try:
1413 1415 # fast path: try to resolve dest without SRC alias
1414 1416 dest = scmutil.revsingle(repo, destf, localalias=alias)
1415 1417 except error.RepoLookupError:
1416 1418 # multi-dest path: resolve dest for each SRC separately
1417 1419 destmap = {}
1418 1420 for r in rebaseset:
1419 1421 alias[b'SRC'] = revsetlang.formatspec(b'%d', r)
1420 1422 # use repo.anyrevs instead of scmutil.revsingle because we
1421 1423 # don't want to abort if destset is empty.
1422 1424 destset = repo.anyrevs([destf], user=True, localalias=alias)
1423 1425 size = len(destset)
1424 1426 if size == 1:
1425 1427 destmap[r] = destset.first()
1426 1428 elif size == 0:
1427 1429 ui.note(_(b'skipping %s - empty destination\n') % repo[r])
1428 1430 else:
1429 raise error.Abort(
1431 raise error.InputError(
1430 1432 _(b'rebase destination for %s is not unique') % repo[r]
1431 1433 )
1432 1434
1433 1435 if dest is not None:
1434 1436 # single-dest case: assign dest to each rev in rebaseset
1435 1437 destrev = dest.rev()
1436 1438 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
1437 1439
1438 1440 if not destmap:
1439 1441 ui.status(_(b'nothing to rebase - empty destination\n'))
1440 1442 return None
1441 1443
1442 1444 return destmap
1443 1445
1444 1446
1445 1447 def externalparent(repo, state, destancestors):
1446 1448 """Return the revision that should be used as the second parent
1447 1449 when the revisions in state is collapsed on top of destancestors.
1448 1450 Abort if there is more than one parent.
1449 1451 """
1450 1452 parents = set()
1451 1453 source = min(state)
1452 1454 for rev in state:
1453 1455 if rev == source:
1454 1456 continue
1455 1457 for p in repo[rev].parents():
1456 1458 if p.rev() not in state and p.rev() not in destancestors:
1457 1459 parents.add(p.rev())
1458 1460 if not parents:
1459 1461 return nullrev
1460 1462 if len(parents) == 1:
1461 1463 return parents.pop()
1462 raise error.Abort(
1464 raise error.StateError(
1463 1465 _(
1464 1466 b'unable to collapse on top of %d, there is more '
1465 1467 b'than one external parent: %s'
1466 1468 )
1467 1469 % (max(destancestors), b', '.join(b"%d" % p for p in sorted(parents)))
1468 1470 )
1469 1471
1470 1472
1471 1473 def commitmemorynode(repo, wctx, editor, extra, user, date, commitmsg):
1472 1474 """Commit the memory changes with parents p1 and p2.
1473 1475 Return node of committed revision."""
1474 1476 # By convention, ``extra['branch']`` (set by extrafn) clobbers
1475 1477 # ``branch`` (used when passing ``--keepbranches``).
1476 1478 branch = None
1477 1479 if b'branch' in extra:
1478 1480 branch = extra[b'branch']
1479 1481
1480 1482 # FIXME: We call _compact() because it's required to correctly detect
1481 1483 # changed files. This was added to fix a regression shortly before the 5.5
1482 1484 # release. A proper fix will be done in the default branch.
1483 1485 wctx._compact()
1484 1486 memctx = wctx.tomemctx(
1485 1487 commitmsg,
1486 1488 date=date,
1487 1489 extra=extra,
1488 1490 user=user,
1489 1491 branch=branch,
1490 1492 editor=editor,
1491 1493 )
1492 1494 if memctx.isempty() and not repo.ui.configbool(b'ui', b'allowemptycommit'):
1493 1495 return None
1494 1496 commitres = repo.commitctx(memctx)
1495 1497 wctx.clean() # Might be reused
1496 1498 return commitres
1497 1499
1498 1500
1499 1501 def commitnode(repo, editor, extra, user, date, commitmsg):
1500 1502 """Commit the wd changes with parents p1 and p2.
1501 1503 Return node of committed revision."""
1502 1504 dsguard = util.nullcontextmanager()
1503 1505 if not repo.ui.configbool(b'rebase', b'singletransaction'):
1504 1506 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1505 1507 with dsguard:
1506 1508 # Commit might fail if unresolved files exist
1507 1509 newnode = repo.commit(
1508 1510 text=commitmsg, user=user, date=date, extra=extra, editor=editor
1509 1511 )
1510 1512
1511 1513 repo.dirstate.setbranch(repo[newnode].branch())
1512 1514 return newnode
1513 1515
1514 1516
1515 1517 def rebasenode(repo, rev, p1, p2, base, collapse, wctx):
1516 1518 """Rebase a single revision rev on top of p1 using base as merge ancestor"""
1517 1519 # Merge phase
1518 1520 # Update to destination and merge it with local
1519 1521 p1ctx = repo[p1]
1520 1522 if wctx.isinmemory():
1521 1523 wctx.setbase(p1ctx)
1522 1524 else:
1523 1525 if repo[b'.'].rev() != p1:
1524 1526 repo.ui.debug(b" update to %d:%s\n" % (p1, p1ctx))
1525 1527 mergemod.clean_update(p1ctx)
1526 1528 else:
1527 1529 repo.ui.debug(b" already in destination\n")
1528 1530 # This is, alas, necessary to invalidate workingctx's manifest cache,
1529 1531 # as well as other data we litter on it in other places.
1530 1532 wctx = repo[None]
1531 1533 repo.dirstate.write(repo.currenttransaction())
1532 1534 ctx = repo[rev]
1533 1535 repo.ui.debug(b" merge against %d:%s\n" % (rev, ctx))
1534 1536 if base is not None:
1535 1537 repo.ui.debug(b" detach base %d:%s\n" % (base, repo[base]))
1536 1538
1537 1539 # See explanation in merge.graft()
1538 1540 mergeancestor = repo.changelog.isancestor(p1ctx.node(), ctx.node())
1539 1541 stats = mergemod._update(
1540 1542 repo,
1541 1543 rev,
1542 1544 branchmerge=True,
1543 1545 force=True,
1544 1546 ancestor=base,
1545 1547 mergeancestor=mergeancestor,
1546 1548 labels=[b'dest', b'source'],
1547 1549 wc=wctx,
1548 1550 )
1549 1551 wctx.setparents(p1ctx.node(), repo[p2].node())
1550 1552 if collapse:
1551 1553 copies.graftcopies(wctx, ctx, p1ctx)
1552 1554 else:
1553 1555 # If we're not using --collapse, we need to
1554 1556 # duplicate copies between the revision we're
1555 1557 # rebasing and its first parent.
1556 1558 copies.graftcopies(wctx, ctx, ctx.p1())
1557 1559
1558 1560 if stats.unresolvedcount > 0:
1559 1561 if wctx.isinmemory():
1560 1562 raise error.InMemoryMergeConflictsError()
1561 1563 else:
1562 1564 raise error.ConflictResolutionRequired(b'rebase')
1563 1565
1564 1566
1565 1567 def adjustdest(repo, rev, destmap, state, skipped):
1566 1568 r"""adjust rebase destination given the current rebase state
1567 1569
1568 1570 rev is what is being rebased. Return a list of two revs, which are the
1569 1571 adjusted destinations for rev's p1 and p2, respectively. If a parent is
1570 1572 nullrev, return dest without adjustment for it.
1571 1573
1572 1574 For example, when doing rebasing B+E to F, C to G, rebase will first move B
1573 1575 to B1, and E's destination will be adjusted from F to B1.
1574 1576
1575 1577 B1 <- written during rebasing B
1576 1578 |
1577 1579 F <- original destination of B, E
1578 1580 |
1579 1581 | E <- rev, which is being rebased
1580 1582 | |
1581 1583 | D <- prev, one parent of rev being checked
1582 1584 | |
1583 1585 | x <- skipped, ex. no successor or successor in (::dest)
1584 1586 | |
1585 1587 | C <- rebased as C', different destination
1586 1588 | |
1587 1589 | B <- rebased as B1 C'
1588 1590 |/ |
1589 1591 A G <- destination of C, different
1590 1592
1591 1593 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
1592 1594 first move C to C1, G to G1, and when it's checking H, the adjusted
1593 1595 destinations will be [C1, G1].
1594 1596
1595 1597 H C1 G1
1596 1598 /| | /
1597 1599 F G |/
1598 1600 K | | -> K
1599 1601 | C D |
1600 1602 | |/ |
1601 1603 | B | ...
1602 1604 |/ |/
1603 1605 A A
1604 1606
1605 1607 Besides, adjust dest according to existing rebase information. For example,
1606 1608
1607 1609 B C D B needs to be rebased on top of C, C needs to be rebased on top
1608 1610 \|/ of D. We will rebase C first.
1609 1611 A
1610 1612
1611 1613 C' After rebasing C, when considering B's destination, use C'
1612 1614 | instead of the original C.
1613 1615 B D
1614 1616 \ /
1615 1617 A
1616 1618 """
1617 1619 # pick already rebased revs with same dest from state as interesting source
1618 1620 dest = destmap[rev]
1619 1621 source = [
1620 1622 s
1621 1623 for s, d in state.items()
1622 1624 if d > 0 and destmap[s] == dest and s not in skipped
1623 1625 ]
1624 1626
1625 1627 result = []
1626 1628 for prev in repo.changelog.parentrevs(rev):
1627 1629 adjusted = dest
1628 1630 if prev != nullrev:
1629 1631 candidate = repo.revs(b'max(%ld and (::%d))', source, prev).first()
1630 1632 if candidate is not None:
1631 1633 adjusted = state[candidate]
1632 1634 if adjusted == dest and dest in state:
1633 1635 adjusted = state[dest]
1634 1636 if adjusted == revtodo:
1635 1637 # sortsource should produce an order that makes this impossible
1636 1638 raise error.ProgrammingError(
1637 1639 b'rev %d should be rebased already at this time' % dest
1638 1640 )
1639 1641 result.append(adjusted)
1640 1642 return result
1641 1643
1642 1644
1643 1645 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
1644 1646 """
1645 1647 Abort if rebase will create divergence or rebase is noop because of markers
1646 1648
1647 1649 `rebaseobsrevs`: set of obsolete revision in source
1648 1650 `rebaseobsskipped`: set of revisions from source skipped because they have
1649 1651 successors in destination or no non-obsolete successor.
1650 1652 """
1651 1653 # Obsolete node with successors not in dest leads to divergence
1652 1654 divergenceok = ui.configbool(b'experimental', b'evolution.allowdivergence')
1653 1655 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
1654 1656
1655 1657 if divergencebasecandidates and not divergenceok:
1656 1658 divhashes = (bytes(repo[r]) for r in divergencebasecandidates)
1657 1659 msg = _(b"this rebase will cause divergences from: %s")
1658 1660 h = _(
1659 1661 b"to force the rebase please set "
1660 1662 b"experimental.evolution.allowdivergence=True"
1661 1663 )
1662 raise error.Abort(msg % (b",".join(divhashes),), hint=h)
1664 raise error.StateError(msg % (b",".join(divhashes),), hint=h)
1663 1665
1664 1666
1665 1667 def successorrevs(unfi, rev):
1666 1668 """yield revision numbers for successors of rev"""
1667 1669 assert unfi.filtername is None
1668 1670 get_rev = unfi.changelog.index.get_rev
1669 1671 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
1670 1672 r = get_rev(s)
1671 1673 if r is not None:
1672 1674 yield r
1673 1675
1674 1676
1675 1677 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1676 1678 """Return new parents and optionally a merge base for rev being rebased
1677 1679
1678 1680 The destination specified by "dest" cannot always be used directly because
1679 1681 previously rebase result could affect destination. For example,
1680 1682
1681 1683 D E rebase -r C+D+E -d B
1682 1684 |/ C will be rebased to C'
1683 1685 B C D's new destination will be C' instead of B
1684 1686 |/ E's new destination will be C' instead of B
1685 1687 A
1686 1688
1687 1689 The new parents of a merge is slightly more complicated. See the comment
1688 1690 block below.
1689 1691 """
1690 1692 # use unfiltered changelog since successorrevs may return filtered nodes
1691 1693 assert repo.filtername is None
1692 1694 cl = repo.changelog
1693 1695 isancestor = cl.isancestorrev
1694 1696
1695 1697 dest = destmap[rev]
1696 1698 oldps = repo.changelog.parentrevs(rev) # old parents
1697 1699 newps = [nullrev, nullrev] # new parents
1698 1700 dests = adjustdest(repo, rev, destmap, state, skipped)
1699 1701 bases = list(oldps) # merge base candidates, initially just old parents
1700 1702
1701 1703 if all(r == nullrev for r in oldps[1:]):
1702 1704 # For non-merge changeset, just move p to adjusted dest as requested.
1703 1705 newps[0] = dests[0]
1704 1706 else:
1705 1707 # For merge changeset, if we move p to dests[i] unconditionally, both
1706 1708 # parents may change and the end result looks like "the merge loses a
1707 1709 # parent", which is a surprise. This is a limit because "--dest" only
1708 1710 # accepts one dest per src.
1709 1711 #
1710 1712 # Therefore, only move p with reasonable conditions (in this order):
1711 1713 # 1. use dest, if dest is a descendent of (p or one of p's successors)
1712 1714 # 2. use p's rebased result, if p is rebased (state[p] > 0)
1713 1715 #
1714 1716 # Comparing with adjustdest, the logic here does some additional work:
1715 1717 # 1. decide which parents will not be moved towards dest
1716 1718 # 2. if the above decision is "no", should a parent still be moved
1717 1719 # because it was rebased?
1718 1720 #
1719 1721 # For example:
1720 1722 #
1721 1723 # C # "rebase -r C -d D" is an error since none of the parents
1722 1724 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1723 1725 # A B D # B (using rule "2."), since B will be rebased.
1724 1726 #
1725 1727 # The loop tries to be not rely on the fact that a Mercurial node has
1726 1728 # at most 2 parents.
1727 1729 for i, p in enumerate(oldps):
1728 1730 np = p # new parent
1729 1731 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
1730 1732 np = dests[i]
1731 1733 elif p in state and state[p] > 0:
1732 1734 np = state[p]
1733 1735
1734 1736 # If one parent becomes an ancestor of the other, drop the ancestor
1735 1737 for j, x in enumerate(newps[:i]):
1736 1738 if x == nullrev:
1737 1739 continue
1738 1740 if isancestor(np, x): # CASE-1
1739 1741 np = nullrev
1740 1742 elif isancestor(x, np): # CASE-2
1741 1743 newps[j] = np
1742 1744 np = nullrev
1743 1745 # New parents forming an ancestor relationship does not
1744 1746 # mean the old parents have a similar relationship. Do not
1745 1747 # set bases[x] to nullrev.
1746 1748 bases[j], bases[i] = bases[i], bases[j]
1747 1749
1748 1750 newps[i] = np
1749 1751
1750 1752 # "rebasenode" updates to new p1, and the old p1 will be used as merge
1751 1753 # base. If only p2 changes, merging using unchanged p1 as merge base is
1752 1754 # suboptimal. Therefore swap parents to make the merge sane.
1753 1755 if newps[1] != nullrev and oldps[0] == newps[0]:
1754 1756 assert len(newps) == 2 and len(oldps) == 2
1755 1757 newps.reverse()
1756 1758 bases.reverse()
1757 1759
1758 1760 # No parent change might be an error because we fail to make rev a
1759 1761 # descendent of requested dest. This can happen, for example:
1760 1762 #
1761 1763 # C # rebase -r C -d D
1762 1764 # /| # None of A and B will be changed to D and rebase fails.
1763 1765 # A B D
1764 1766 if set(newps) == set(oldps) and dest not in newps:
1765 raise error.Abort(
1767 raise error.InputError(
1766 1768 _(
1767 1769 b'cannot rebase %d:%s without '
1768 1770 b'moving at least one of its parents'
1769 1771 )
1770 1772 % (rev, repo[rev])
1771 1773 )
1772 1774
1773 1775 # Source should not be ancestor of dest. The check here guarantees it's
1774 1776 # impossible. With multi-dest, the initial check does not cover complex
1775 1777 # cases since we don't have abstractions to dry-run rebase cheaply.
1776 1778 if any(p != nullrev and isancestor(rev, p) for p in newps):
1777 raise error.Abort(_(b'source is ancestor of destination'))
1779 raise error.InputError(_(b'source is ancestor of destination'))
1778 1780
1779 1781 # Check if the merge will contain unwanted changes. That may happen if
1780 1782 # there are multiple special (non-changelog ancestor) merge bases, which
1781 1783 # cannot be handled well by the 3-way merge algorithm. For example:
1782 1784 #
1783 1785 # F
1784 1786 # /|
1785 1787 # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
1786 1788 # | | # as merge base, the difference between D and F will include
1787 1789 # B C # C, so the rebased F will contain C surprisingly. If "E" was
1788 1790 # |/ # chosen, the rebased F will contain B.
1789 1791 # A Z
1790 1792 #
1791 1793 # But our merge base candidates (D and E in above case) could still be
1792 1794 # better than the default (ancestor(F, Z) == null). Therefore still
1793 1795 # pick one (so choose p1 above).
1794 1796 if sum(1 for b in set(bases) if b != nullrev and b not in newps) > 1:
1795 1797 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
1796 1798 for i, base in enumerate(bases):
1797 1799 if base == nullrev or base in newps:
1798 1800 continue
1799 1801 # Revisions in the side (not chosen as merge base) branch that
1800 1802 # might contain "surprising" contents
1801 1803 other_bases = set(bases) - {base}
1802 1804 siderevs = list(
1803 1805 repo.revs(b'(%ld %% (%d+%d))', other_bases, base, dest)
1804 1806 )
1805 1807
1806 1808 # If those revisions are covered by rebaseset, the result is good.
1807 1809 # A merge in rebaseset would be considered to cover its ancestors.
1808 1810 if siderevs:
1809 1811 rebaseset = [
1810 1812 r for r, d in state.items() if d > 0 and r not in obsskipped
1811 1813 ]
1812 1814 merges = [
1813 1815 r for r in rebaseset if cl.parentrevs(r)[1] != nullrev
1814 1816 ]
1815 1817 unwanted[i] = list(
1816 1818 repo.revs(
1817 1819 b'%ld - (::%ld) - %ld', siderevs, merges, rebaseset
1818 1820 )
1819 1821 )
1820 1822
1821 1823 if any(revs is not None for revs in unwanted):
1822 1824 # Choose a merge base that has a minimal number of unwanted revs.
1823 1825 l, i = min(
1824 1826 (len(revs), i)
1825 1827 for i, revs in enumerate(unwanted)
1826 1828 if revs is not None
1827 1829 )
1828 1830
1829 1831 # The merge will include unwanted revisions. Abort now. Revisit this if
1830 1832 # we have a more advanced merge algorithm that handles multiple bases.
1831 1833 if l > 0:
1832 1834 unwanteddesc = _(b' or ').join(
1833 1835 (
1834 1836 b', '.join(b'%d:%s' % (r, repo[r]) for r in revs)
1835 1837 for revs in unwanted
1836 1838 if revs is not None
1837 1839 )
1838 1840 )
1839 raise error.Abort(
1841 raise error.InputError(
1840 1842 _(b'rebasing %d:%s will include unwanted changes from %s')
1841 1843 % (rev, repo[rev], unwanteddesc)
1842 1844 )
1843 1845
1844 1846 # newps[0] should match merge base if possible. Currently, if newps[i]
1845 1847 # is nullrev, the only case is newps[i] and newps[j] (j < i), one is
1846 1848 # the other's ancestor. In that case, it's fine to not swap newps here.
1847 1849 # (see CASE-1 and CASE-2 above)
1848 1850 if i != 0:
1849 1851 if newps[i] != nullrev:
1850 1852 newps[0], newps[i] = newps[i], newps[0]
1851 1853 bases[0], bases[i] = bases[i], bases[0]
1852 1854
1853 1855 # "rebasenode" updates to new p1, use the corresponding merge base.
1854 1856 base = bases[0]
1855 1857
1856 1858 repo.ui.debug(b" future parents are %d and %d\n" % tuple(newps))
1857 1859
1858 1860 return newps[0], newps[1], base
1859 1861
1860 1862
1861 1863 def isagitpatch(repo, patchname):
1862 1864 """Return true if the given patch is in git format"""
1863 1865 mqpatch = os.path.join(repo.mq.path, patchname)
1864 1866 for line in patch.linereader(open(mqpatch, b'rb')):
1865 1867 if line.startswith(b'diff --git'):
1866 1868 return True
1867 1869 return False
1868 1870
1869 1871
1870 1872 def updatemq(repo, state, skipped, **opts):
1871 1873 """Update rebased mq patches - finalize and then import them"""
1872 1874 mqrebase = {}
1873 1875 mq = repo.mq
1874 1876 original_series = mq.fullseries[:]
1875 1877 skippedpatches = set()
1876 1878
1877 1879 for p in mq.applied:
1878 1880 rev = repo[p.node].rev()
1879 1881 if rev in state:
1880 1882 repo.ui.debug(
1881 1883 b'revision %d is an mq patch (%s), finalize it.\n'
1882 1884 % (rev, p.name)
1883 1885 )
1884 1886 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
1885 1887 else:
1886 1888 # Applied but not rebased, not sure this should happen
1887 1889 skippedpatches.add(p.name)
1888 1890
1889 1891 if mqrebase:
1890 1892 mq.finish(repo, mqrebase.keys())
1891 1893
1892 1894 # We must start import from the newest revision
1893 1895 for rev in sorted(mqrebase, reverse=True):
1894 1896 if rev not in skipped:
1895 1897 name, isgit = mqrebase[rev]
1896 1898 repo.ui.note(
1897 1899 _(b'updating mq patch %s to %d:%s\n')
1898 1900 % (name, state[rev], repo[state[rev]])
1899 1901 )
1900 1902 mq.qimport(
1901 1903 repo,
1902 1904 (),
1903 1905 patchname=name,
1904 1906 git=isgit,
1905 1907 rev=[b"%d" % state[rev]],
1906 1908 )
1907 1909 else:
1908 1910 # Rebased and skipped
1909 1911 skippedpatches.add(mqrebase[rev][0])
1910 1912
1911 1913 # Patches were either applied and rebased and imported in
1912 1914 # order, applied and removed or unapplied. Discard the removed
1913 1915 # ones while preserving the original series order and guards.
1914 1916 newseries = [
1915 1917 s
1916 1918 for s in original_series
1917 1919 if mq.guard_re.split(s, 1)[0] not in skippedpatches
1918 1920 ]
1919 1921 mq.fullseries[:] = newseries
1920 1922 mq.seriesdirty = True
1921 1923 mq.savedirty()
1922 1924
1923 1925
1924 1926 def storecollapsemsg(repo, collapsemsg):
1925 1927 """Store the collapse message to allow recovery"""
1926 1928 collapsemsg = collapsemsg or b''
1927 1929 f = repo.vfs(b"last-message.txt", b"w")
1928 1930 f.write(b"%s\n" % collapsemsg)
1929 1931 f.close()
1930 1932
1931 1933
1932 1934 def clearcollapsemsg(repo):
1933 1935 """Remove collapse message file"""
1934 1936 repo.vfs.unlinkpath(b"last-message.txt", ignoremissing=True)
1935 1937
1936 1938
1937 1939 def restorecollapsemsg(repo, isabort):
1938 1940 """Restore previously stored collapse message"""
1939 1941 try:
1940 1942 f = repo.vfs(b"last-message.txt")
1941 1943 collapsemsg = f.readline().strip()
1942 1944 f.close()
1943 1945 except IOError as err:
1944 1946 if err.errno != errno.ENOENT:
1945 1947 raise
1946 1948 if isabort:
1947 1949 # Oh well, just abort like normal
1948 1950 collapsemsg = b''
1949 1951 else:
1950 1952 raise error.Abort(_(b'missing .hg/last-message.txt for rebase'))
1951 1953 return collapsemsg
1952 1954
1953 1955
1954 1956 def clearstatus(repo):
1955 1957 """Remove the status files"""
1956 1958 # Make sure the active transaction won't write the state file
1957 1959 tr = repo.currenttransaction()
1958 1960 if tr:
1959 1961 tr.removefilegenerator(b'rebasestate')
1960 1962 repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True)
1961 1963
1962 1964
1963 1965 def sortsource(destmap):
1964 1966 """yield source revisions in an order that we only rebase things once
1965 1967
1966 1968 If source and destination overlaps, we should filter out revisions
1967 1969 depending on other revisions which hasn't been rebased yet.
1968 1970
1969 1971 Yield a sorted list of revisions each time.
1970 1972
1971 1973 For example, when rebasing A to B, B to C. This function yields [B], then
1972 1974 [A], indicating B needs to be rebased first.
1973 1975
1974 1976 Raise if there is a cycle so the rebase is impossible.
1975 1977 """
1976 1978 srcset = set(destmap)
1977 1979 while srcset:
1978 1980 srclist = sorted(srcset)
1979 1981 result = []
1980 1982 for r in srclist:
1981 1983 if destmap[r] not in srcset:
1982 1984 result.append(r)
1983 1985 if not result:
1984 raise error.Abort(_(b'source and destination form a cycle'))
1986 raise error.InputError(_(b'source and destination form a cycle'))
1985 1987 srcset -= set(result)
1986 1988 yield result
1987 1989
1988 1990
1989 1991 def buildstate(repo, destmap, collapse):
1990 1992 """Define which revisions are going to be rebased and where
1991 1993
1992 1994 repo: repo
1993 1995 destmap: {srcrev: destrev}
1994 1996 """
1995 1997 rebaseset = destmap.keys()
1996 1998 originalwd = repo[b'.'].rev()
1997 1999
1998 2000 # This check isn't strictly necessary, since mq detects commits over an
1999 2001 # applied patch. But it prevents messing up the working directory when
2000 2002 # a partially completed rebase is blocked by mq.
2001 2003 if b'qtip' in repo.tags():
2002 2004 mqapplied = {repo[s.node].rev() for s in repo.mq.applied}
2003 2005 if set(destmap.values()) & mqapplied:
2004 raise error.Abort(_(b'cannot rebase onto an applied mq patch'))
2006 raise error.StateError(_(b'cannot rebase onto an applied mq patch'))
2005 2007
2006 2008 # Get "cycle" error early by exhausting the generator.
2007 2009 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
2008 2010 if not sortedsrc:
2009 raise error.Abort(_(b'no matching revisions'))
2011 raise error.InputError(_(b'no matching revisions'))
2010 2012
2011 2013 # Only check the first batch of revisions to rebase not depending on other
2012 2014 # rebaseset. This means "source is ancestor of destination" for the second
2013 2015 # (and following) batches of revisions are not checked here. We rely on
2014 2016 # "defineparents" to do that check.
2015 2017 roots = list(repo.set(b'roots(%ld)', sortedsrc[0]))
2016 2018 if not roots:
2017 raise error.Abort(_(b'no matching revisions'))
2019 raise error.InputError(_(b'no matching revisions'))
2018 2020
2019 2021 def revof(r):
2020 2022 return r.rev()
2021 2023
2022 2024 roots = sorted(roots, key=revof)
2023 2025 state = dict.fromkeys(rebaseset, revtodo)
2024 2026 emptyrebase = len(sortedsrc) == 1
2025 2027 for root in roots:
2026 2028 dest = repo[destmap[root.rev()]]
2027 2029 commonbase = root.ancestor(dest)
2028 2030 if commonbase == root:
2029 raise error.Abort(_(b'source is ancestor of destination'))
2031 raise error.InputError(_(b'source is ancestor of destination'))
2030 2032 if commonbase == dest:
2031 2033 wctx = repo[None]
2032 2034 if dest == wctx.p1():
2033 2035 # when rebasing to '.', it will use the current wd branch name
2034 2036 samebranch = root.branch() == wctx.branch()
2035 2037 else:
2036 2038 samebranch = root.branch() == dest.branch()
2037 2039 if not collapse and samebranch and dest in root.parents():
2038 2040 # mark the revision as done by setting its new revision
2039 2041 # equal to its old (current) revisions
2040 2042 state[root.rev()] = root.rev()
2041 2043 repo.ui.debug(b'source is a child of destination\n')
2042 2044 continue
2043 2045
2044 2046 emptyrebase = False
2045 2047 repo.ui.debug(b'rebase onto %s starting from %s\n' % (dest, root))
2046 2048 if emptyrebase:
2047 2049 return None
2048 2050 for rev in sorted(state):
2049 2051 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
2050 2052 # if all parents of this revision are done, then so is this revision
2051 2053 if parents and all((state.get(p) == p for p in parents)):
2052 2054 state[rev] = rev
2053 2055 return originalwd, destmap, state
2054 2056
2055 2057
2056 2058 def clearrebased(
2057 2059 ui,
2058 2060 repo,
2059 2061 destmap,
2060 2062 state,
2061 2063 skipped,
2062 2064 collapsedas=None,
2063 2065 keepf=False,
2064 2066 fm=None,
2065 2067 backup=True,
2066 2068 ):
2067 2069 """dispose of rebased revision at the end of the rebase
2068 2070
2069 2071 If `collapsedas` is not None, the rebase was a collapse whose result if the
2070 2072 `collapsedas` node.
2071 2073
2072 2074 If `keepf` is not True, the rebase has --keep set and no nodes should be
2073 2075 removed (but bookmarks still need to be moved).
2074 2076
2075 2077 If `backup` is False, no backup will be stored when stripping rebased
2076 2078 revisions.
2077 2079 """
2078 2080 tonode = repo.changelog.node
2079 2081 replacements = {}
2080 2082 moves = {}
2081 2083 stripcleanup = not obsolete.isenabled(repo, obsolete.createmarkersopt)
2082 2084
2083 2085 collapsednodes = []
2084 2086 for rev, newrev in sorted(state.items()):
2085 2087 if newrev >= 0 and newrev != rev:
2086 2088 oldnode = tonode(rev)
2087 2089 newnode = collapsedas or tonode(newrev)
2088 2090 moves[oldnode] = newnode
2089 2091 succs = None
2090 2092 if rev in skipped:
2091 2093 if stripcleanup or not repo[rev].obsolete():
2092 2094 succs = ()
2093 2095 elif collapsedas:
2094 2096 collapsednodes.append(oldnode)
2095 2097 else:
2096 2098 succs = (newnode,)
2097 2099 if succs is not None:
2098 2100 replacements[(oldnode,)] = succs
2099 2101 if collapsednodes:
2100 2102 replacements[tuple(collapsednodes)] = (collapsedas,)
2101 2103 if fm:
2102 2104 hf = fm.hexfunc
2103 2105 fl = fm.formatlist
2104 2106 fd = fm.formatdict
2105 2107 changes = {}
2106 2108 for oldns, newn in pycompat.iteritems(replacements):
2107 2109 for oldn in oldns:
2108 2110 changes[hf(oldn)] = fl([hf(n) for n in newn], name=b'node')
2109 2111 nodechanges = fd(changes, key=b"oldnode", value=b"newnodes")
2110 2112 fm.data(nodechanges=nodechanges)
2111 2113 if keepf:
2112 2114 replacements = {}
2113 2115 scmutil.cleanupnodes(repo, replacements, b'rebase', moves, backup=backup)
2114 2116
2115 2117
2116 2118 def pullrebase(orig, ui, repo, *args, **opts):
2117 2119 """Call rebase after pull if the latter has been invoked with --rebase"""
2118 2120 if opts.get('rebase'):
2119 2121 if ui.configbool(b'commands', b'rebase.requiredest'):
2120 2122 msg = _(b'rebase destination required by configuration')
2121 2123 hint = _(b'use hg pull followed by hg rebase -d DEST')
2122 raise error.Abort(msg, hint=hint)
2124 raise error.InputError(msg, hint=hint)
2123 2125
2124 2126 with repo.wlock(), repo.lock():
2125 2127 if opts.get('update'):
2126 2128 del opts['update']
2127 2129 ui.debug(
2128 2130 b'--update and --rebase are not compatible, ignoring '
2129 2131 b'the update flag\n'
2130 2132 )
2131 2133
2132 2134 cmdutil.checkunfinished(repo, skipmerge=True)
2133 2135 cmdutil.bailifchanged(
2134 2136 repo,
2135 2137 hint=_(
2136 2138 b'cannot pull with rebase: '
2137 2139 b'please commit or shelve your changes first'
2138 2140 ),
2139 2141 )
2140 2142
2141 2143 revsprepull = len(repo)
2142 2144 origpostincoming = commands.postincoming
2143 2145
2144 2146 def _dummy(*args, **kwargs):
2145 2147 pass
2146 2148
2147 2149 commands.postincoming = _dummy
2148 2150 try:
2149 2151 ret = orig(ui, repo, *args, **opts)
2150 2152 finally:
2151 2153 commands.postincoming = origpostincoming
2152 2154 revspostpull = len(repo)
2153 2155 if revspostpull > revsprepull:
2154 2156 # --rev option from pull conflict with rebase own --rev
2155 2157 # dropping it
2156 2158 if 'rev' in opts:
2157 2159 del opts['rev']
2158 2160 # positional argument from pull conflicts with rebase's own
2159 2161 # --source.
2160 2162 if 'source' in opts:
2161 2163 del opts['source']
2162 2164 # revsprepull is the len of the repo, not revnum of tip.
2163 2165 destspace = list(repo.changelog.revs(start=revsprepull))
2164 2166 opts['_destspace'] = destspace
2165 2167 try:
2166 2168 rebase(ui, repo, **opts)
2167 2169 except error.NoMergeDestAbort:
2168 2170 # we can maybe update instead
2169 2171 rev, _a, _b = destutil.destupdate(repo)
2170 2172 if rev == repo[b'.'].rev():
2171 2173 ui.status(_(b'nothing to rebase\n'))
2172 2174 else:
2173 2175 ui.status(_(b'nothing to rebase - updating instead\n'))
2174 2176 # not passing argument to get the bare update behavior
2175 2177 # with warning and trumpets
2176 2178 commands.update(ui, repo)
2177 2179 else:
2178 2180 if opts.get('tool'):
2179 raise error.Abort(_(b'--tool can only be used with --rebase'))
2181 raise error.InputError(_(b'--tool can only be used with --rebase'))
2180 2182 ret = orig(ui, repo, *args, **opts)
2181 2183
2182 2184 return ret
2183 2185
2184 2186
2185 2187 def _filterobsoleterevs(repo, revs):
2186 2188 """returns a set of the obsolete revisions in revs"""
2187 2189 return {r for r in revs if repo[r].obsolete()}
2188 2190
2189 2191
2190 2192 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
2191 2193 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
2192 2194
2193 2195 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
2194 2196 obsolete nodes to be rebased given in `rebaseobsrevs`.
2195 2197
2196 2198 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
2197 2199 without a successor in destination.
2198 2200
2199 2201 `obsoleteextinctsuccessors` is a set of obsolete revisions with only
2200 2202 obsolete successors.
2201 2203 """
2202 2204 obsoletenotrebased = {}
2203 2205 obsoletewithoutsuccessorindestination = set()
2204 2206 obsoleteextinctsuccessors = set()
2205 2207
2206 2208 assert repo.filtername is None
2207 2209 cl = repo.changelog
2208 2210 get_rev = cl.index.get_rev
2209 2211 extinctrevs = set(repo.revs(b'extinct()'))
2210 2212 for srcrev in rebaseobsrevs:
2211 2213 srcnode = cl.node(srcrev)
2212 2214 # XXX: more advanced APIs are required to handle split correctly
2213 2215 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
2214 2216 # obsutil.allsuccessors includes node itself
2215 2217 successors.remove(srcnode)
2216 2218 succrevs = {get_rev(s) for s in successors}
2217 2219 succrevs.discard(None)
2218 2220 if succrevs.issubset(extinctrevs):
2219 2221 # all successors are extinct
2220 2222 obsoleteextinctsuccessors.add(srcrev)
2221 2223 if not successors:
2222 2224 # no successor
2223 2225 obsoletenotrebased[srcrev] = None
2224 2226 else:
2225 2227 dstrev = destmap[srcrev]
2226 2228 for succrev in succrevs:
2227 2229 if cl.isancestorrev(succrev, dstrev):
2228 2230 obsoletenotrebased[srcrev] = succrev
2229 2231 break
2230 2232 else:
2231 2233 # If 'srcrev' has a successor in rebase set but none in
2232 2234 # destination (which would be catched above), we shall skip it
2233 2235 # and its descendants to avoid divergence.
2234 2236 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
2235 2237 obsoletewithoutsuccessorindestination.add(srcrev)
2236 2238
2237 2239 return (
2238 2240 obsoletenotrebased,
2239 2241 obsoletewithoutsuccessorindestination,
2240 2242 obsoleteextinctsuccessors,
2241 2243 )
2242 2244
2243 2245
2244 2246 def abortrebase(ui, repo):
2245 2247 with repo.wlock(), repo.lock():
2246 2248 rbsrt = rebaseruntime(repo, ui)
2247 2249 rbsrt._prepareabortorcontinue(isabort=True)
2248 2250
2249 2251
2250 2252 def continuerebase(ui, repo):
2251 2253 with repo.wlock(), repo.lock():
2252 2254 rbsrt = rebaseruntime(repo, ui)
2253 2255 ms = mergestatemod.mergestate.read(repo)
2254 2256 mergeutil.checkunresolved(ms)
2255 2257 retcode = rbsrt._prepareabortorcontinue(isabort=False)
2256 2258 if retcode is not None:
2257 2259 return retcode
2258 2260 rbsrt._performrebase(None)
2259 2261 rbsrt._finishrebase()
2260 2262
2261 2263
2262 2264 def summaryhook(ui, repo):
2263 2265 if not repo.vfs.exists(b'rebasestate'):
2264 2266 return
2265 2267 try:
2266 2268 rbsrt = rebaseruntime(repo, ui, {})
2267 2269 rbsrt.restorestatus()
2268 2270 state = rbsrt.state
2269 2271 except error.RepoLookupError:
2270 2272 # i18n: column positioning for "hg summary"
2271 2273 msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n')
2272 2274 ui.write(msg)
2273 2275 return
2274 2276 numrebased = len([i for i in pycompat.itervalues(state) if i >= 0])
2275 2277 # i18n: column positioning for "hg summary"
2276 2278 ui.write(
2277 2279 _(b'rebase: %s, %s (rebase --continue)\n')
2278 2280 % (
2279 2281 ui.label(_(b'%d rebased'), b'rebase.rebased') % numrebased,
2280 2282 ui.label(_(b'%d remaining'), b'rebase.remaining')
2281 2283 % (len(state) - numrebased),
2282 2284 )
2283 2285 )
2284 2286
2285 2287
2286 2288 def uisetup(ui):
2287 2289 # Replace pull with a decorator to provide --rebase option
2288 2290 entry = extensions.wrapcommand(commands.table, b'pull', pullrebase)
2289 2291 entry[1].append(
2290 2292 (b'', b'rebase', None, _(b"rebase working directory to branch head"))
2291 2293 )
2292 2294 entry[1].append((b't', b'tool', b'', _(b"specify merge tool for rebase")))
2293 2295 cmdutil.summaryhooks.add(b'rebase', summaryhook)
2294 2296 statemod.addunfinished(
2295 2297 b'rebase',
2296 2298 fname=b'rebasestate',
2297 2299 stopflag=True,
2298 2300 continueflag=True,
2299 2301 abortfunc=abortrebase,
2300 2302 continuefunc=continuerebase,
2301 2303 )
@@ -1,776 +1,776 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 > mq=
5 5 > drawdag=$TESTDIR/drawdag.py
6 6 >
7 7 > [phases]
8 8 > publish=False
9 9 >
10 10 > [alias]
11 11 > tglog = log -G --template "{rev}: {node|short} '{desc}' {branches}\n"
12 12 > tglogp = log -G --template "{rev}: {node|short} {phase} '{desc}' {branches}\n"
13 13 > EOF
14 14
15 15 Highest phase of source commits is used:
16 16
17 17 $ hg init phase
18 18 $ cd phase
19 19 $ hg debugdrawdag << 'EOF'
20 20 > D
21 21 > |
22 22 > F C
23 23 > | |
24 24 > E B
25 25 > |/
26 26 > A
27 27 > EOF
28 28
29 29 $ hg phase --force --secret D
30 30
31 31 $ cat > $TESTTMP/editor.sh <<EOF
32 32 > echo "==== before editing"
33 33 > cat \$1
34 34 > echo "===="
35 35 > echo "edited manually" >> \$1
36 36 > EOF
37 37 $ HGEDITOR="sh $TESTTMP/editor.sh" hg rebase --collapse --keepbranches -e --source B --dest F
38 38 rebasing 1:112478962961 B "B"
39 39 rebasing 3:26805aba1e60 C "C"
40 40 rebasing 5:f585351a92f8 D tip "D"
41 41 ==== before editing
42 42 Collapsed revision
43 43 * B
44 44 * C
45 45 * D
46 46
47 47
48 48 HG: Enter commit message. Lines beginning with 'HG:' are removed.
49 49 HG: Leave message empty to abort commit.
50 50 HG: --
51 51 HG: user: test
52 52 HG: branch 'default'
53 53 HG: added B
54 54 HG: added C
55 55 HG: added D
56 56 ====
57 57 saved backup bundle to $TESTTMP/phase/.hg/strip-backup/112478962961-cb2a9b47-rebase.hg
58 58
59 59 $ hg tglogp
60 60 o 3: 92fa5f5fe108 secret 'Collapsed revision
61 61 | * B
62 62 | * C
63 63 | * D
64 64 |
65 65 |
66 66 | edited manually'
67 67 o 2: 64a8289d2492 draft 'F'
68 68 |
69 69 o 1: 7fb047a69f22 draft 'E'
70 70 |
71 71 o 0: 426bada5c675 draft 'A'
72 72
73 73 $ hg manifest --rev tip
74 74 A
75 75 B
76 76 C
77 77 D
78 78 E
79 79 F
80 80
81 81 $ cd ..
82 82
83 83
84 84 Merge gets linearized:
85 85
86 86 $ hg init linearized-merge
87 87 $ cd linearized-merge
88 88
89 89 $ hg debugdrawdag << 'EOF'
90 90 > F D
91 91 > |/|
92 92 > C B
93 93 > |/
94 94 > A
95 95 > EOF
96 96
97 97 $ hg phase --force --secret D
98 98 $ hg rebase --source B --collapse --dest F
99 99 rebasing 1:112478962961 B "B"
100 100 rebasing 3:4e4f9194f9f1 D "D"
101 101 saved backup bundle to $TESTTMP/linearized-merge/.hg/strip-backup/112478962961-e389075b-rebase.hg
102 102
103 103 $ hg tglog
104 104 o 3: 5bdc08b7da2b 'Collapsed revision
105 105 | * B
106 106 | * D'
107 107 o 2: afc707c82df0 'F'
108 108 |
109 109 o 1: dc0947a82db8 'C'
110 110 |
111 111 o 0: 426bada5c675 'A'
112 112
113 113 $ hg manifest --rev tip
114 114 A
115 115 B
116 116 C
117 117 F
118 118
119 119 $ cd ..
120 120
121 121 Custom message:
122 122
123 123 $ hg init message
124 124 $ cd message
125 125
126 126 $ hg debugdrawdag << 'EOF'
127 127 > C
128 128 > |
129 129 > D B
130 130 > |/
131 131 > A
132 132 > EOF
133 133
134 134
135 135 $ hg rebase --base B -m 'custom message'
136 136 abort: message can only be specified with collapse
137 [255]
137 [10]
138 138
139 139 $ cat > $TESTTMP/checkeditform.sh <<EOF
140 140 > env | grep HGEDITFORM
141 141 > true
142 142 > EOF
143 143 $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg rebase --source B --collapse -m 'custom message' -e --dest D
144 144 rebasing 1:112478962961 B "B"
145 145 rebasing 3:26805aba1e60 C tip "C"
146 146 HGEDITFORM=rebase.collapse
147 147 saved backup bundle to $TESTTMP/message/.hg/strip-backup/112478962961-f4131707-rebase.hg
148 148
149 149 $ hg tglog
150 150 o 2: 2f197b9a08f3 'custom message'
151 151 |
152 152 o 1: b18e25de2cf5 'D'
153 153 |
154 154 o 0: 426bada5c675 'A'
155 155
156 156 $ hg manifest --rev tip
157 157 A
158 158 B
159 159 C
160 160 D
161 161
162 162 $ cd ..
163 163
164 164 Rebase and collapse - more than one external (fail):
165 165
166 166 $ hg init multiple-external-parents
167 167 $ cd multiple-external-parents
168 168
169 169 $ hg debugdrawdag << 'EOF'
170 170 > G
171 171 > |\
172 172 > | F
173 173 > | |
174 174 > D E
175 175 > |\|
176 176 > H C B
177 177 > \|/
178 178 > A
179 179 > EOF
180 180
181 181 $ hg rebase -s C --dest H --collapse
182 182 abort: unable to collapse on top of 3, there is more than one external parent: 1, 6
183 [255]
183 [20]
184 184
185 185 Rebase and collapse - E onto H:
186 186
187 187 $ hg rebase -s E --dest H --collapse # root (E) is not a merge
188 188 rebasing 5:49cb92066bfd E "E"
189 189 rebasing 6:11abe3fb10b8 F "F"
190 190 rebasing 7:64e264db77f0 G tip "G"
191 191 saved backup bundle to $TESTTMP/multiple-external-parents/.hg/strip-backup/49cb92066bfd-ee8a8a79-rebase.hg
192 192
193 193 $ hg tglog
194 194 o 5: 8b2315790719 'Collapsed revision
195 195 |\ * E
196 196 | | * F
197 197 | | * G'
198 198 | o 4: 4e4f9194f9f1 'D'
199 199 | |\
200 200 o | | 3: 575c4b5ec114 'H'
201 201 | | |
202 202 +---o 2: dc0947a82db8 'C'
203 203 | |
204 204 | o 1: 112478962961 'B'
205 205 |/
206 206 o 0: 426bada5c675 'A'
207 207
208 208 $ hg manifest --rev tip
209 209 A
210 210 C
211 211 E
212 212 F
213 213 H
214 214
215 215 $ cd ..
216 216
217 217
218 218
219 219
220 220 Test that branchheads cache is updated correctly when doing a strip in which
221 221 the parent of the ancestor node to be stripped does not become a head and also,
222 222 the parent of a node that is a child of the node stripped becomes a head (node
223 223 3). The code is now much simpler and we could just test a simpler scenario
224 224 We keep it the test this way in case new complexity is injected.
225 225
226 226 Create repo b:
227 227
228 228 $ hg init branch-heads
229 229 $ cd branch-heads
230 230
231 231 $ hg debugdrawdag << 'EOF'
232 232 > G
233 233 > |\
234 234 > | F
235 235 > | |
236 236 > D E
237 237 > |\|
238 238 > H C B
239 239 > \|/
240 240 > A
241 241 > EOF
242 242
243 243 $ hg heads --template="{rev}:{node} {branch}\n"
244 244 7:64e264db77f061f16d9132b70c5a58e2461fb630 default
245 245 3:575c4b5ec114d64b681d33f8792853568bfb2b2c default
246 246
247 247 $ cat $TESTTMP/branch-heads/.hg/cache/branch2-served
248 248 64e264db77f061f16d9132b70c5a58e2461fb630 7
249 249 575c4b5ec114d64b681d33f8792853568bfb2b2c o default
250 250 64e264db77f061f16d9132b70c5a58e2461fb630 o default
251 251
252 252 $ hg strip 4
253 253 saved backup bundle to $TESTTMP/branch-heads/.hg/strip-backup/4e4f9194f9f1-5ec4b5e6-backup.hg
254 254
255 255 $ cat $TESTTMP/branch-heads/.hg/cache/branch2-served
256 256 11abe3fb10b8689b560681094b17fe161871d043 5
257 257 dc0947a82db884575bb76ea10ac97b08536bfa03 o default
258 258 575c4b5ec114d64b681d33f8792853568bfb2b2c o default
259 259 11abe3fb10b8689b560681094b17fe161871d043 o default
260 260
261 261 $ hg heads --template="{rev}:{node} {branch}\n"
262 262 5:11abe3fb10b8689b560681094b17fe161871d043 default
263 263 3:575c4b5ec114d64b681d33f8792853568bfb2b2c default
264 264 2:dc0947a82db884575bb76ea10ac97b08536bfa03 default
265 265
266 266 $ cd ..
267 267
268 268
269 269
270 270 Preserves external parent
271 271
272 272 $ hg init external-parent
273 273 $ cd external-parent
274 274
275 275 $ hg debugdrawdag << 'EOF'
276 276 > H
277 277 > |\
278 278 > | G
279 279 > | |
280 280 > | F # F/E = F\n
281 281 > | |
282 282 > D E # D/D = D\n
283 283 > |\|
284 284 > I C B
285 285 > \|/
286 286 > A
287 287 > EOF
288 288
289 289 $ hg rebase -s F --dest I --collapse # root (F) is not a merge
290 290 rebasing 6:c82b08f646f1 F "F"
291 291 file 'E' was deleted in local [dest] but was modified in other [source].
292 292 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
293 293 What do you want to do? u
294 294 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
295 295 [240]
296 296
297 297 $ echo F > E
298 298 $ hg resolve -m
299 299 (no more unresolved files)
300 300 continue: hg rebase --continue
301 301 $ hg rebase -c
302 302 rebasing 6:c82b08f646f1 F "F"
303 303 rebasing 7:a6db7fa104e1 G "G"
304 304 rebasing 8:e1d201b72d91 H tip "H"
305 305 saved backup bundle to $TESTTMP/external-parent/.hg/strip-backup/c82b08f646f1-f2721fbf-rebase.hg
306 306
307 307 $ hg tglog
308 308 o 6: 681daa3e686d 'Collapsed revision
309 309 |\ * F
310 310 | | * G
311 311 | | * H'
312 312 | | o 5: 49cb92066bfd 'E'
313 313 | | |
314 314 | o | 4: 09143c0bf13e 'D'
315 315 | |\|
316 316 o | | 3: 08ebfeb61bac 'I'
317 317 | | |
318 318 | o | 2: dc0947a82db8 'C'
319 319 |/ /
320 320 | o 1: 112478962961 'B'
321 321 |/
322 322 o 0: 426bada5c675 'A'
323 323
324 324 $ hg manifest --rev tip
325 325 A
326 326 C
327 327 D
328 328 E
329 329 F
330 330 G
331 331 I
332 332
333 333 $ hg up tip -q
334 334 $ cat E
335 335 F
336 336
337 337 $ cd ..
338 338
339 339 Rebasing from multiple bases:
340 340
341 341 $ hg init multiple-bases
342 342 $ cd multiple-bases
343 343 $ hg debugdrawdag << 'EOF'
344 344 > C B
345 345 > D |/
346 346 > |/
347 347 > A
348 348 > EOF
349 349 $ hg rebase --collapse -r 'B+C' -d D
350 350 rebasing 1:fc2b737bb2e5 B "B"
351 351 rebasing 2:dc0947a82db8 C "C"
352 352 saved backup bundle to $TESTTMP/multiple-bases/.hg/strip-backup/dc0947a82db8-b0c1a7ea-rebase.hg
353 353 $ hg tglog
354 354 o 2: 2127ae44d291 'Collapsed revision
355 355 | * B
356 356 | * C'
357 357 o 1: b18e25de2cf5 'D'
358 358 |
359 359 o 0: 426bada5c675 'A'
360 360
361 361 $ cd ..
362 362
363 363 With non-contiguous commits:
364 364
365 365 $ hg init non-contiguous
366 366 $ cd non-contiguous
367 367 $ cat >> .hg/hgrc <<EOF
368 368 > [experimental]
369 369 > evolution=all
370 370 > EOF
371 371
372 372 $ hg debugdrawdag << 'EOF'
373 373 > F
374 374 > |
375 375 > E
376 376 > |
377 377 > D
378 378 > |
379 379 > C
380 380 > |
381 381 > B G
382 382 > |/
383 383 > A
384 384 > EOF
385 385
386 386 BROKEN: should be allowed
387 387 $ hg rebase --collapse -r 'B+D+F' -d G
388 388 abort: unable to collapse on top of 2, there is more than one external parent: 3, 5
389 [255]
389 [20]
390 390 $ cd ..
391 391
392 392
393 393 $ hg init multiple-external-parents-2
394 394 $ cd multiple-external-parents-2
395 395 $ hg debugdrawdag << 'EOF'
396 396 > D G
397 397 > |\ /|
398 398 > B C E F
399 399 > \| |/
400 400 > \ H /
401 401 > \|/
402 402 > A
403 403 > EOF
404 404
405 405 $ hg rebase --collapse -d H -s 'B+F'
406 406 abort: unable to collapse on top of 5, there is more than one external parent: 1, 3
407 [255]
407 [20]
408 408 $ cd ..
409 409
410 410 With internal merge:
411 411
412 412 $ hg init internal-merge
413 413 $ cd internal-merge
414 414
415 415 $ hg debugdrawdag << 'EOF'
416 416 > E
417 417 > |\
418 418 > C D
419 419 > |/
420 420 > F B
421 421 > |/
422 422 > A
423 423 > EOF
424 424
425 425
426 426 $ hg rebase -s B --collapse --dest F
427 427 rebasing 1:112478962961 B "B"
428 428 rebasing 3:26805aba1e60 C "C"
429 429 rebasing 4:be0ef73c17ad D "D"
430 430 rebasing 5:02c4367d6973 E tip "E"
431 431 saved backup bundle to $TESTTMP/internal-merge/.hg/strip-backup/112478962961-1dfb057b-rebase.hg
432 432
433 433 $ hg tglog
434 434 o 2: c0512a1797b0 'Collapsed revision
435 435 | * B
436 436 | * C
437 437 | * D
438 438 | * E'
439 439 o 1: 8908a377a434 'F'
440 440 |
441 441 o 0: 426bada5c675 'A'
442 442
443 443 $ hg manifest --rev tip
444 444 A
445 445 B
446 446 C
447 447 D
448 448 F
449 449 $ cd ..
450 450
451 451 Interactions between collapse and keepbranches
452 452 $ hg init e
453 453 $ cd e
454 454 $ echo 'a' > a
455 455 $ hg ci -Am 'A'
456 456 adding a
457 457
458 458 $ hg branch 'one'
459 459 marked working directory as branch one
460 460 (branches are permanent and global, did you want a bookmark?)
461 461 $ echo 'b' > b
462 462 $ hg ci -Am 'B'
463 463 adding b
464 464
465 465 $ hg branch 'two'
466 466 marked working directory as branch two
467 467 $ echo 'c' > c
468 468 $ hg ci -Am 'C'
469 469 adding c
470 470
471 471 $ hg up -q 0
472 472 $ echo 'd' > d
473 473 $ hg ci -Am 'D'
474 474 adding d
475 475
476 476 $ hg tglog
477 477 @ 3: 41acb9dca9eb 'D'
478 478 |
479 479 | o 2: 8ac4a08debf1 'C' two
480 480 | |
481 481 | o 1: 1ba175478953 'B' one
482 482 |/
483 483 o 0: 1994f17a630e 'A'
484 484
485 485 $ hg rebase --keepbranches --collapse -s 1 -d 3
486 486 abort: cannot collapse multiple named branches
487 [255]
487 [10]
488 488
489 489 $ cd ..
490 490
491 491 Rebase, collapse and copies
492 492
493 493 $ hg init copies
494 494 $ cd copies
495 495 $ hg unbundle "$TESTDIR/bundles/renames.hg"
496 496 adding changesets
497 497 adding manifests
498 498 adding file changes
499 499 added 4 changesets with 11 changes to 7 files (+1 heads)
500 500 new changesets f447d5abf5ea:338e84e2e558 (4 drafts)
501 501 (run 'hg heads' to see heads, 'hg merge' to merge)
502 502 $ hg up -q tip
503 503 $ hg tglog
504 504 @ 3: 338e84e2e558 'move2'
505 505 |
506 506 o 2: 6e7340ee38c0 'move1'
507 507 |
508 508 | o 1: 1352765a01d4 'change'
509 509 |/
510 510 o 0: f447d5abf5ea 'add'
511 511
512 512 $ hg rebase --collapse -d 1
513 513 rebasing 2:6e7340ee38c0 "move1"
514 514 merging a and d to d
515 515 merging b and e to e
516 516 merging c and f to f
517 517 rebasing 3:338e84e2e558 tip "move2"
518 518 merging f and c to c
519 519 merging e and g to g
520 520 saved backup bundle to $TESTTMP/copies/.hg/strip-backup/6e7340ee38c0-ef8ef003-rebase.hg
521 521 $ hg st
522 522 $ hg st --copies --change tip
523 523 A d
524 524 a
525 525 A g
526 526 b
527 527 R b
528 528 $ hg up tip -q
529 529 $ cat c
530 530 c
531 531 c
532 532 $ cat d
533 533 a
534 534 a
535 535 $ cat g
536 536 b
537 537 b
538 538 $ hg log -r . --template "{file_copies}\n"
539 539 d (a)g (b)
540 540
541 541 Test collapsing a middle revision in-place
542 542
543 543 $ hg tglog
544 544 @ 2: 64b456429f67 'Collapsed revision
545 545 | * move1
546 546 | * move2'
547 547 o 1: 1352765a01d4 'change'
548 548 |
549 549 o 0: f447d5abf5ea 'add'
550 550
551 551 $ hg rebase --collapse -r 1 -d 0
552 552 abort: cannot rebase changeset with children
553 553 (use --keep to keep original changesets)
554 554 [10]
555 555
556 556 Test collapsing in place
557 557
558 558 $ hg rebase --collapse -b . -d 0
559 559 rebasing 1:1352765a01d4 "change"
560 560 rebasing 2:64b456429f67 tip "Collapsed revision"
561 561 saved backup bundle to $TESTTMP/copies/.hg/strip-backup/1352765a01d4-45a352ea-rebase.hg
562 562 $ hg st --change tip --copies
563 563 M a
564 564 M c
565 565 A d
566 566 a
567 567 A g
568 568 b
569 569 R b
570 570 $ hg up tip -q
571 571 $ cat a
572 572 a
573 573 a
574 574 $ cat c
575 575 c
576 576 c
577 577 $ cat d
578 578 a
579 579 a
580 580 $ cat g
581 581 b
582 582 b
583 583 $ cd ..
584 584
585 585
586 586 Test stripping a revision with another child
587 587
588 588 $ hg init f
589 589 $ cd f
590 590
591 591 $ hg debugdrawdag << 'EOF'
592 592 > C B
593 593 > |/
594 594 > A
595 595 > EOF
596 596
597 597 $ hg heads --template="{rev}:{node} {branch}: {desc}\n"
598 598 2:dc0947a82db884575bb76ea10ac97b08536bfa03 default: C
599 599 1:112478962961147124edd43549aedd1a335e44bf default: B
600 600
601 601 $ hg strip C
602 602 saved backup bundle to $TESTTMP/f/.hg/strip-backup/dc0947a82db8-d21b92a4-backup.hg
603 603
604 604 $ hg tglog
605 605 o 1: 112478962961 'B'
606 606 |
607 607 o 0: 426bada5c675 'A'
608 608
609 609
610 610
611 611 $ hg heads --template="{rev}:{node} {branch}: {desc}\n"
612 612 1:112478962961147124edd43549aedd1a335e44bf default: B
613 613
614 614 $ cd ..
615 615
616 616 Test collapsing changes that add then remove a file
617 617
618 618 $ hg init collapseaddremove
619 619 $ cd collapseaddremove
620 620
621 621 $ touch base
622 622 $ hg commit -Am base
623 623 adding base
624 624 $ touch a
625 625 $ hg commit -Am a
626 626 adding a
627 627 $ hg rm a
628 628 $ touch b
629 629 $ hg commit -Am b
630 630 adding b
631 631 $ hg book foo
632 632 $ hg rebase -d 0 -r "1::2" --collapse -m collapsed
633 633 rebasing 1:6d8d9f24eec3 "a"
634 634 rebasing 2:1cc73eca5ecc foo tip "b"
635 635 saved backup bundle to $TESTTMP/collapseaddremove/.hg/strip-backup/6d8d9f24eec3-77d3b6e2-rebase.hg
636 636 $ hg log -G --template "{rev}: '{desc}' {bookmarks}"
637 637 @ 1: 'collapsed' foo
638 638 |
639 639 o 0: 'base'
640 640
641 641 $ hg manifest --rev tip
642 642 b
643 643 base
644 644
645 645 $ cd ..
646 646
647 647 Test that rebase --collapse will remember message after
648 648 running into merge conflict and invoking rebase --continue.
649 649
650 650 $ hg init collapse_remember_message
651 651 $ cd collapse_remember_message
652 652 $ hg debugdrawdag << 'EOF'
653 653 > C B # B/A = B\n
654 654 > |/ # C/A = C\n
655 655 > A
656 656 > EOF
657 657 $ hg rebase --collapse -m "new message" -b B -d C
658 658 rebasing 1:81e5401e4d37 B "B"
659 659 merging A
660 660 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
661 661 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
662 662 [240]
663 663 $ rm A.orig
664 664 $ hg resolve --mark A
665 665 (no more unresolved files)
666 666 continue: hg rebase --continue
667 667 $ hg rebase --continue
668 668 rebasing 1:81e5401e4d37 B "B"
669 669 saved backup bundle to $TESTTMP/collapse_remember_message/.hg/strip-backup/81e5401e4d37-96c3dd30-rebase.hg
670 670 $ hg log
671 671 changeset: 2:17186933e123
672 672 tag: tip
673 673 user: test
674 674 date: Thu Jan 01 00:00:00 1970 +0000
675 675 summary: new message
676 676
677 677 changeset: 1:043039e9df84
678 678 tag: C
679 679 user: test
680 680 date: Thu Jan 01 00:00:00 1970 +0000
681 681 summary: C
682 682
683 683 changeset: 0:426bada5c675
684 684 tag: A
685 685 user: test
686 686 date: Thu Jan 01 00:00:00 1970 +0000
687 687 summary: A
688 688
689 689 $ cd ..
690 690
691 691 Test aborted editor on final message
692 692
693 693 $ HGMERGE=:merge3
694 694 $ export HGMERGE
695 695 $ hg init aborted-editor
696 696 $ cd aborted-editor
697 697 $ hg debugdrawdag << 'EOF'
698 698 > C # D/A = D\n
699 699 > | # C/A = C\n
700 700 > B D # B/A = B\n
701 701 > |/ # A/A = A\n
702 702 > A
703 703 > EOF
704 704 $ hg rebase --collapse -t internal:merge3 -s B -d D
705 705 rebasing 1:f899f3910ce7 B "B"
706 706 merging A
707 707 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
708 708 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
709 709 [240]
710 710 $ hg tglog
711 711 o 3: 63668d570d21 'C'
712 712 |
713 713 | @ 2: 82b8abf9c185 'D'
714 714 | |
715 715 % | 1: f899f3910ce7 'B'
716 716 |/
717 717 o 0: 4a2df7238c3b 'A'
718 718
719 719 $ cat A
720 720 <<<<<<< dest: 82b8abf9c185 D - test: D
721 721 D
722 722 ||||||| base
723 723 A
724 724 =======
725 725 B
726 726 >>>>>>> source: f899f3910ce7 B - test: B
727 727 $ echo BC > A
728 728 $ hg resolve -m
729 729 (no more unresolved files)
730 730 continue: hg rebase --continue
731 731 $ hg rebase --continue
732 732 rebasing 1:f899f3910ce7 B "B"
733 733 rebasing 3:63668d570d21 C tip "C"
734 734 merging A
735 735 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
736 736 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
737 737 [240]
738 738 $ hg tglog
739 739 % 3: 63668d570d21 'C'
740 740 |
741 741 | @ 2: 82b8abf9c185 'D'
742 742 | |
743 743 o | 1: f899f3910ce7 'B'
744 744 |/
745 745 o 0: 4a2df7238c3b 'A'
746 746
747 747 $ cat A
748 748 <<<<<<< dest: 82b8abf9c185 D - test: D
749 749 BC
750 750 ||||||| base
751 751 B
752 752 =======
753 753 C
754 754 >>>>>>> source: 63668d570d21 C tip - test: C
755 755 $ echo BD > A
756 756 $ hg resolve -m
757 757 (no more unresolved files)
758 758 continue: hg rebase --continue
759 759 $ HGEDITOR=false hg rebase --continue --config ui.interactive=1
760 760 already rebased 1:f899f3910ce7 B "B" as 82b8abf9c185
761 761 rebasing 3:63668d570d21 C tip "C"
762 762 abort: edit failed: false exited with status 1
763 763 [250]
764 764 $ hg tglog
765 765 o 3: 63668d570d21 'C'
766 766 |
767 767 | @ 2: 82b8abf9c185 'D'
768 768 | |
769 769 o | 1: f899f3910ce7 'B'
770 770 |/
771 771 o 0: 4a2df7238c3b 'A'
772 772
773 773 $ hg rebase --continue
774 774 already rebased 1:f899f3910ce7 B "B" as 82b8abf9c185
775 775 already rebased 3:63668d570d21 C tip "C" as 82b8abf9c185
776 776 saved backup bundle to $TESTTMP/aborted-editor/.hg/strip-backup/f899f3910ce7-7cab5e15-rebase.hg
@@ -1,465 +1,465 b''
1 1 Require a destination
2 2 $ cat >> $HGRCPATH <<EOF
3 3 > [extensions]
4 4 > rebase =
5 5 > [commands]
6 6 > rebase.requiredest = True
7 7 > EOF
8 8 $ hg init repo
9 9 $ cd repo
10 10 $ echo a >> a
11 11 $ hg commit -qAm aa
12 12 $ echo b >> b
13 13 $ hg commit -qAm bb
14 14 $ hg up ".^"
15 15 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
16 16 $ echo c >> c
17 17 $ hg commit -qAm cc
18 18 $ hg rebase
19 19 abort: you must specify a destination
20 20 (use: hg rebase -d REV)
21 [255]
21 [10]
22 22 $ hg rebase -d 1
23 23 rebasing 2:5db65b93a12b tip "cc"
24 24 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/5db65b93a12b-4fb789ec-rebase.hg
25 25 $ hg rebase -d 0 -r . -q
26 26 $ HGPLAIN=1 hg rebase
27 27 rebasing 2:889b0bc6a730 tip "cc"
28 28 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/889b0bc6a730-41ec4f81-rebase.hg
29 29 $ hg rebase -d 0 -r . -q
30 30 $ hg --config commands.rebase.requiredest=False rebase
31 31 rebasing 2:279de9495438 tip "cc"
32 32 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/279de9495438-ab0a5128-rebase.hg
33 33
34 34 Requiring dest should not break continue or other rebase options
35 35 $ hg up 1 -q
36 36 $ echo d >> c
37 37 $ hg commit -qAm dc
38 38 $ hg log -G -T '{rev} {desc}'
39 39 @ 3 dc
40 40 |
41 41 | o 2 cc
42 42 |/
43 43 o 1 bb
44 44 |
45 45 o 0 aa
46 46
47 47 $ hg rebase -d 2
48 48 rebasing 3:0537f6b50def tip "dc"
49 49 merging c
50 50 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
51 51 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
52 52 [240]
53 53 $ echo d > c
54 54 $ hg resolve --mark --all
55 55 (no more unresolved files)
56 56 continue: hg rebase --continue
57 57 $ hg rebase --continue
58 58 rebasing 3:0537f6b50def tip "dc"
59 59 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0537f6b50def-be4c7386-rebase.hg
60 60
61 61 $ cd ..
62 62
63 63 Check rebase.requiredest interaction with pull --rebase
64 64 $ hg clone repo clone
65 65 updating to branch default
66 66 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67 $ cd repo
68 68 $ echo e > e
69 69 $ hg commit -qAm ee
70 70 $ cd ..
71 71 $ cd clone
72 72 $ echo f > f
73 73 $ hg commit -qAm ff
74 74 $ hg pull --rebase
75 75 abort: rebase destination required by configuration
76 76 (use hg pull followed by hg rebase -d DEST)
77 [255]
77 [10]
78 78
79 79 Setup rebase with multiple destinations
80 80
81 81 $ cd $TESTTMP
82 82
83 83 $ cat >> $TESTTMP/maprevset.py <<EOF
84 84 > from __future__ import absolute_import
85 85 > from mercurial import registrar, revset, revsetlang, smartset
86 86 > revsetpredicate = registrar.revsetpredicate()
87 87 > cache = {}
88 88 > @revsetpredicate(b'map')
89 89 > def map(repo, subset, x):
90 90 > """(set, mapping)"""
91 91 > setarg, maparg = revsetlang.getargs(x, 2, 2, b'')
92 92 > rset = revset.getset(repo, smartset.fullreposet(repo), setarg)
93 93 > mapstr = revsetlang.getstring(maparg, b'')
94 94 > map = dict(a.split(b':') for a in mapstr.split(b','))
95 95 > rev = rset.first()
96 96 > desc = repo[rev].description()
97 97 > newdesc = map.get(desc)
98 98 > if newdesc == b'null':
99 99 > revs = [-1]
100 100 > else:
101 101 > query = revsetlang.formatspec(b'desc(%s)', newdesc)
102 102 > revs = repo.revs(query)
103 103 > return smartset.baseset(revs)
104 104 > EOF
105 105
106 106 $ cat >> $HGRCPATH <<EOF
107 107 > [ui]
108 108 > allowemptycommit=1
109 109 > [extensions]
110 110 > drawdag=$TESTDIR/drawdag.py
111 111 > [phases]
112 112 > publish=False
113 113 > [alias]
114 114 > tglog = log -G --template "{rev}: {node|short} {desc} {instabilities}" -r 'sort(all(), topo)'
115 115 > [extensions]
116 116 > maprevset=$TESTTMP/maprevset.py
117 117 > [experimental]
118 118 > evolution=true
119 119 > EOF
120 120
121 121 $ rebasewithdag() {
122 122 > N=`"$PYTHON" -c "print($N+1)"`
123 123 > hg init repo$N && cd repo$N
124 124 > hg debugdrawdag
125 125 > hg rebase "$@" > _rebasetmp
126 126 > r=$?
127 127 > grep -v 'saved backup bundle' _rebasetmp
128 128 > [ $r -eq 0 ] && rm -f .hg/localtags && hg tglog
129 129 > cd ..
130 130 > return $r
131 131 > }
132 132
133 133 Destination resolves to an empty set:
134 134
135 135 $ rebasewithdag -s B -d 'SRC - SRC' <<'EOS'
136 136 > C
137 137 > |
138 138 > B
139 139 > |
140 140 > A
141 141 > EOS
142 142 nothing to rebase - empty destination
143 143 [1]
144 144
145 145 Multiple destinations and --collapse are not compatible:
146 146
147 147 $ rebasewithdag -s C+E -d 'SRC^^' --collapse <<'EOS'
148 148 > C F
149 149 > | |
150 150 > B E
151 151 > | |
152 152 > A D
153 153 > EOS
154 154 abort: --collapse does not work with multiple destinations
155 [255]
155 [10]
156 156
157 157 Multiple destinations cannot be used with --base:
158 158
159 159 $ rebasewithdag -b B -b E -d 'SRC^^' --collapse <<'EOS'
160 160 > B E
161 161 > | |
162 162 > A D
163 163 > EOS
164 164 abort: unknown revision 'SRC'
165 165 [255]
166 166
167 167 Rebase to null should work:
168 168
169 169 $ rebasewithdag -r A+C+D -d 'null' <<'EOS'
170 170 > C D
171 171 > | |
172 172 > A B
173 173 > EOS
174 174 already rebased 0:426bada5c675 A "A"
175 175 already rebased 2:dc0947a82db8 C "C"
176 176 rebasing 3:004dc1679908 D tip "D"
177 177 o 4: d8d8601abd5e D
178 178
179 179 o 2: dc0947a82db8 C
180 180 |
181 181 | o 1: fc2b737bb2e5 B
182 182 |
183 183 o 0: 426bada5c675 A
184 184
185 185 Destination resolves to multiple changesets:
186 186
187 187 $ rebasewithdag -s B -d 'ALLSRC+SRC' <<'EOS'
188 188 > C
189 189 > |
190 190 > B
191 191 > |
192 192 > Z
193 193 > EOS
194 194 abort: rebase destination for f0a671a46792 is not unique
195 [255]
195 [10]
196 196
197 197 Destination is an ancestor of source:
198 198
199 199 $ rebasewithdag -s B -d 'SRC' <<'EOS'
200 200 > C
201 201 > |
202 202 > B
203 203 > |
204 204 > Z
205 205 > EOS
206 206 abort: source and destination form a cycle
207 [255]
207 [10]
208 208
209 209 BUG: cycles aren't flagged correctly when --dry-run is set:
210 210 $ rebasewithdag -s B -d 'SRC' --dry-run <<'EOS'
211 211 > C
212 212 > |
213 213 > B
214 214 > |
215 215 > Z
216 216 > EOS
217 217 abort: source and destination form a cycle
218 218 starting dry-run rebase; repository will not be changed
219 [255]
219 [10]
220 220
221 221 Switch roots:
222 222
223 223 $ rebasewithdag -s 'all() - roots(all())' -d 'roots(all()) - ::SRC' <<'EOS'
224 224 > C F
225 225 > | |
226 226 > B E
227 227 > | |
228 228 > A D
229 229 > EOS
230 230 rebasing 2:112478962961 B "B"
231 231 rebasing 4:26805aba1e60 C "C"
232 232 rebasing 3:cd488e83d208 E "E"
233 233 rebasing 5:0069ba24938a F tip "F"
234 234 o 9: d150ff263fc8 F
235 235 |
236 236 o 8: 66f30a1a2eab E
237 237 |
238 238 | o 7: 93db94ffae0e C
239 239 | |
240 240 | o 6: d0071c3b0c88 B
241 241 | |
242 242 | o 1: 058c1e1fb10a D
243 243 |
244 244 o 0: 426bada5c675 A
245 245
246 246 Different destinations for merge changesets with a same root:
247 247
248 248 $ rebasewithdag -s B -d '((parents(SRC)-B-A)::) - (::ALLSRC)' <<'EOS'
249 249 > C G
250 250 > |\|
251 251 > | F
252 252 > |
253 253 > B E
254 254 > |\|
255 255 > A D
256 256 > EOS
257 257 rebasing 3:a4256619d830 B "B"
258 258 rebasing 6:8e139e245220 C tip "C"
259 259 o 8: d7d1169e9b1c C
260 260 |\
261 261 | o 7: 2ed0c8546285 B
262 262 | |\
263 263 o | | 5: 8fdb2c1feb20 G
264 264 | | |
265 265 | | o 4: cd488e83d208 E
266 266 | | |
267 267 o | | 2: a6661b868de9 F
268 268 / /
269 269 | o 1: 058c1e1fb10a D
270 270 |
271 271 o 0: 426bada5c675 A
272 272
273 273 Move to a previous parent:
274 274
275 275 $ rebasewithdag -s E -s F -s G -d 'SRC^^' <<'EOS'
276 276 > H
277 277 > |
278 278 > D G
279 279 > |/
280 280 > C F
281 281 > |/
282 282 > B E # E will be ignored, since E^^ is empty
283 283 > |/
284 284 > A
285 285 > EOS
286 286 rebasing 4:33441538d4aa F "F"
287 287 rebasing 6:cf43ad9da869 G "G"
288 288 rebasing 7:eef94f3b5f03 H tip "H"
289 289 o 10: b3d84c6666cf H
290 290 |
291 291 | o 5: f585351a92f8 D
292 292 |/
293 293 o 3: 26805aba1e60 C
294 294 |
295 295 | o 9: f7c28a1a15e2 G
296 296 |/
297 297 o 1: 112478962961 B
298 298 |
299 299 | o 8: 02aa697facf7 F
300 300 |/
301 301 | o 2: 7fb047a69f22 E
302 302 |/
303 303 o 0: 426bada5c675 A
304 304
305 305 Source overlaps with destination:
306 306
307 307 $ rebasewithdag -s 'B+C+D' -d 'map(SRC, "B:C,C:D")' <<'EOS'
308 308 > B C D
309 309 > \|/
310 310 > A
311 311 > EOS
312 312 rebasing 2:dc0947a82db8 C "C"
313 313 rebasing 1:112478962961 B "B"
314 314 o 5: 5fe9935d5222 B
315 315 |
316 316 o 4: 12d20731b9e0 C
317 317 |
318 318 o 3: b18e25de2cf5 D
319 319 |
320 320 o 0: 426bada5c675 A
321 321
322 322 Detect cycles early:
323 323
324 324 $ rebasewithdag -r 'all()-Z' -d 'map(SRC, "A:B,B:C,C:D,D:B")' <<'EOS'
325 325 > A B C
326 326 > \|/
327 327 > | D
328 328 > |/
329 329 > Z
330 330 > EOS
331 331 abort: source and destination form a cycle
332 [255]
332 [10]
333 333
334 334 Detect source is ancestor of dest in runtime:
335 335
336 336 $ rebasewithdag -r 'C+B' -d 'map(SRC, "C:B,B:D")' -q <<'EOS'
337 337 > D
338 338 > |
339 339 > B C
340 340 > \|
341 341 > A
342 342 > EOS
343 343 abort: source is ancestor of destination
344 [255]
344 [10]
345 345
346 346 "Already rebased" fast path still works:
347 347
348 348 $ rebasewithdag -r 'all()' -d 'SRC^' <<'EOS'
349 349 > E F
350 350 > /| |
351 351 > B C D
352 352 > \|/
353 353 > A
354 354 > EOS
355 355 already rebased 1:112478962961 B "B"
356 356 already rebased 2:dc0947a82db8 C "C"
357 357 already rebased 3:b18e25de2cf5 D "D"
358 358 already rebased 4:312782b8f06e E "E"
359 359 already rebased 5:ad6717a6a58e F tip "F"
360 360 o 5: ad6717a6a58e F
361 361 |
362 362 o 3: b18e25de2cf5 D
363 363 |
364 364 | o 4: 312782b8f06e E
365 365 | |\
366 366 +---o 2: dc0947a82db8 C
367 367 | |
368 368 | o 1: 112478962961 B
369 369 |/
370 370 o 0: 426bada5c675 A
371 371
372 372 Massively rewrite the DAG:
373 373
374 374 $ rebasewithdag -r 'all()' -d 'map(SRC, "A:I,I:null,H:A,B:J,J:C,C:H,D:E,F:G,G:K,K:D,E:B")' <<'EOS'
375 375 > D G K
376 376 > | | |
377 377 > C F J
378 378 > | | |
379 379 > B E I
380 380 > \| |
381 381 > A H
382 382 > EOS
383 383 rebasing 4:701514e1408d I "I"
384 384 rebasing 0:426bada5c675 A "A"
385 385 rebasing 1:e7050b6e5048 H "H"
386 386 rebasing 5:26805aba1e60 C "C"
387 387 rebasing 7:cf89f86b485b J "J"
388 388 rebasing 2:112478962961 B "B"
389 389 rebasing 3:7fb047a69f22 E "E"
390 390 rebasing 8:f585351a92f8 D "D"
391 391 rebasing 10:ae41898d7875 K tip "K"
392 392 rebasing 9:711f53bbef0b G "G"
393 393 rebasing 6:64a8289d2492 F "F"
394 394 o 21: 3735afb3713a F
395 395 |
396 396 o 20: 07698142d7a7 G
397 397 |
398 398 o 19: 33aba52e7e72 K
399 399 |
400 400 o 18: 9fdae89dc5a1 D
401 401 |
402 402 o 17: 277dda9a65ee E
403 403 |
404 404 o 16: 9c74fd8657ad B
405 405 |
406 406 o 15: 6527eb0688bb J
407 407 |
408 408 o 14: e94d655b928d C
409 409 |
410 410 o 13: 620d6d349459 H
411 411 |
412 412 o 12: a569a116758f A
413 413 |
414 414 o 11: 2bf1302f5c18 I
415 415
416 416 Resolve instability:
417 417
418 418 $ rebasewithdag <<'EOF' -r 'orphan()-obsolete()' -d 'max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::)'
419 419 > F2
420 420 > |
421 421 > J E E2
422 422 > | |/
423 423 > I2 I | E3
424 424 > \| |/
425 425 > H | G
426 426 > | | |
427 427 > B2 D F
428 428 > | |/ # rebase: B -> B2
429 429 > N C # amend: E -> E2
430 430 > | | # amend: E2 -> E3
431 431 > M B # rebase: F -> F2
432 432 > \| # amend: I -> I2
433 433 > A
434 434 > EOF
435 435 6 new orphan changesets
436 436 rebasing 16:5c432343bf59 J tip "J"
437 437 rebasing 3:26805aba1e60 C "C"
438 438 rebasing 6:f585351a92f8 D "D"
439 439 rebasing 10:ffebc37c5d0b E3 "E3"
440 440 rebasing 13:fb184bcfeee8 F2 "F2"
441 441 rebasing 11:dc838ab4c0da G "G"
442 442 o 22: 174f63d574a8 G
443 443 |
444 444 o 21: c9d9fbe76705 F2
445 445 |
446 446 o 20: 0a03c2ede755 E3
447 447 |
448 448 o 19: 228d9d2541b1 D
449 449 |
450 450 o 18: cd856b400c95 C
451 451 |
452 452 o 17: 9148200c858c J
453 453 |
454 454 o 15: eb74780f5094 I2
455 455 |
456 456 o 12: 78309edd643f H
457 457 |
458 458 o 5: 4b4531bd8e1d B2
459 459 |
460 460 o 4: 337c285c272b N
461 461 |
462 462 o 2: 699bc4b6fa22 M
463 463 |
464 464 o 0: 426bada5c675 A
465 465
@@ -1,360 +1,360 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 > mq=
5 5 >
6 6 > [mq]
7 7 > plain=true
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: {node|short} '{desc}' tags: {tags}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ hg qinit -c
17 17
18 18 $ echo c1 > f
19 19 $ hg add f
20 20 $ hg ci -m C1
21 21
22 22 $ echo r1 > f
23 23 $ hg ci -m R1
24 24
25 25 $ hg up -q 0
26 26
27 27 $ hg qnew f.patch -d '1 0'
28 28 $ echo mq1 > f
29 29 $ hg qref -m P0
30 30
31 31 $ hg qnew f2.patch
32 32 $ echo mq2 > f
33 33 $ hg qref -m P1 -d '2 0'
34 34
35 35 $ hg tglog
36 36 @ 3: 929394423cd3 'P1' tags: f2.patch qtip tip
37 37 |
38 38 o 2: 3504f44bffc0 'P0' tags: f.patch qbase
39 39 |
40 40 | o 1: bac9ed9960d8 'R1' tags:
41 41 |/
42 42 o 0: 36f36ddbca61 'C1' tags: qparent
43 43
44 44
45 45 Rebase - try to rebase on an applied mq patch:
46 46
47 47 $ hg rebase -s 1 -d 3
48 48 abort: cannot rebase onto an applied mq patch
49 [255]
49 [20]
50 50
51 51 Rebase - same thing, but mq patch is default dest:
52 52
53 53 $ hg up -q 1
54 54 $ hg rebase
55 55 abort: cannot rebase onto an applied mq patch
56 [255]
56 [20]
57 57 $ hg up -q qtip
58 58
59 59 Rebase - generate a conflict:
60 60
61 61 $ hg rebase -s 2 -d 1
62 62 rebasing 2:3504f44bffc0 f.patch qbase "P0"
63 63 merging f
64 64 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
65 65 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
66 66 [240]
67 67
68 68 Fix the 1st conflict:
69 69
70 70 $ echo mq1r1 > f
71 71 $ hg resolve -m f
72 72 (no more unresolved files)
73 73 continue: hg rebase --continue
74 74 $ hg rebase -c
75 75 rebasing 2:3504f44bffc0 f.patch qbase "P0"
76 76 rebasing 3:929394423cd3 f2.patch qtip tip "P1"
77 77 merging f
78 78 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
79 79 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
80 80 [240]
81 81
82 82 Fix the 2nd conflict:
83 83
84 84 $ echo mq1r1mq2 > f
85 85 $ hg resolve -m f
86 86 (no more unresolved files)
87 87 continue: hg rebase --continue
88 88 $ hg rebase -c
89 89 already rebased 2:3504f44bffc0 f.patch qbase "P0" as ebe9914c0d1c
90 90 rebasing 3:929394423cd3 f2.patch qtip "P1"
91 91 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3504f44bffc0-30595b40-rebase.hg
92 92
93 93 $ hg tglog
94 94 @ 3: 462012cf340c 'P1' tags: f2.patch qtip tip
95 95 |
96 96 o 2: ebe9914c0d1c 'P0' tags: f.patch qbase
97 97 |
98 98 o 1: bac9ed9960d8 'R1' tags: qparent
99 99 |
100 100 o 0: 36f36ddbca61 'C1' tags:
101 101
102 102 $ hg up -q qbase
103 103
104 104 $ cat f
105 105 mq1r1
106 106
107 107 $ cat .hg/patches/f.patch
108 108 # HG changeset patch
109 109 # User test
110 110 # Date 1 0
111 111 # Thu Jan 01 00:00:01 1970 +0000
112 112 # Node ID ebe9914c0d1c3f60096e952fa4dbb3d377dea3ab
113 113 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
114 114 P0
115 115
116 116 diff -r bac9ed9960d8 -r ebe9914c0d1c f
117 117 --- a/f Thu Jan 01 00:00:00 1970 +0000
118 118 +++ b/f Thu Jan 01 00:00:01 1970 +0000
119 119 @@ -1,1 +1,1 @@
120 120 -r1
121 121 +mq1r1
122 122
123 123 Update to qtip:
124 124
125 125 $ hg up -q qtip
126 126
127 127 $ cat f
128 128 mq1r1mq2
129 129
130 130 $ cat .hg/patches/f2.patch
131 131 # HG changeset patch
132 132 # User test
133 133 # Date 2 0
134 134 # Thu Jan 01 00:00:02 1970 +0000
135 135 # Node ID 462012cf340c97d44d62377c985a423f6bb82f07
136 136 # Parent ebe9914c0d1c3f60096e952fa4dbb3d377dea3ab
137 137 P1
138 138
139 139 diff -r ebe9914c0d1c -r 462012cf340c f
140 140 --- a/f Thu Jan 01 00:00:01 1970 +0000
141 141 +++ b/f Thu Jan 01 00:00:02 1970 +0000
142 142 @@ -1,1 +1,1 @@
143 143 -mq1r1
144 144 +mq1r1mq2
145 145
146 146 Adding one git-style patch and one normal:
147 147
148 148 $ hg qpop -a
149 149 popping f2.patch
150 150 popping f.patch
151 151 patch queue now empty
152 152
153 153 $ rm -fr .hg/patches
154 154 $ hg qinit -c
155 155
156 156 $ hg up -q 0
157 157
158 158 $ hg qnew --git f_git.patch -d '3 0'
159 159 $ echo mq1 > p
160 160 $ hg add p
161 161 $ hg qref --git -m 'P0 (git)'
162 162
163 163 $ hg qnew f.patch -d '4 0'
164 164 $ echo mq2 > p
165 165 $ hg qref -m P1
166 166 $ hg qci -m 'save patch state'
167 167
168 168 $ hg qseries -s
169 169 f_git.patch: P0 (git)
170 170 f.patch: P1
171 171
172 172 $ hg -R .hg/patches manifest
173 173 .hgignore
174 174 f.patch
175 175 f_git.patch
176 176 series
177 177
178 178 $ cat .hg/patches/f_git.patch
179 179 Date: 3 0
180 180
181 181 P0 (git)
182 182
183 183 diff --git a/p b/p
184 184 new file mode 100644
185 185 --- /dev/null
186 186 +++ b/p
187 187 @@ -0,0 +1,1 @@
188 188 +mq1
189 189
190 190 $ cat .hg/patches/f.patch
191 191 Date: 4 0
192 192
193 193 P1
194 194
195 195 diff -r ???????????? p (glob)
196 196 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
197 197 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
198 198 @@ -1,1 +1,1 @@
199 199 -mq1
200 200 +mq2
201 201
202 202
203 203 Rebase the applied mq patches:
204 204
205 205 $ hg rebase -s 2 -d 1
206 206 rebasing 2:0c587ffcb480 f_git.patch qbase "P0 (git)"
207 207 rebasing 3:c7f18665e4bc f.patch qtip tip "P1"
208 208 saved backup bundle to $TESTTMP/a/.hg/strip-backup/0c587ffcb480-0ea5695f-rebase.hg
209 209
210 210 $ hg qci -m 'save patch state'
211 211
212 212 $ hg qseries -s
213 213 f_git.patch: P0 (git)
214 214 f.patch: P1
215 215
216 216 $ hg -R .hg/patches manifest
217 217 .hgignore
218 218 f.patch
219 219 f_git.patch
220 220 series
221 221
222 222 $ cat .hg/patches/f_git.patch
223 223 # HG changeset patch
224 224 # User test
225 225 # Date 3 0
226 226 # Thu Jan 01 00:00:03 1970 +0000
227 227 # Node ID 12d9f6a3bbe560dee50c7c454d434add7fb8e837
228 228 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
229 229 P0 (git)
230 230
231 231 diff --git a/p b/p
232 232 new file mode 100644
233 233 --- /dev/null
234 234 +++ b/p
235 235 @@ -0,0 +1,1 @@
236 236 +mq1
237 237
238 238 $ cat .hg/patches/f.patch
239 239 # HG changeset patch
240 240 # User test
241 241 # Date 4 0
242 242 # Thu Jan 01 00:00:04 1970 +0000
243 243 # Node ID c77a2661c64c60d82f63c4f7aefd95b3a948a557
244 244 # Parent 12d9f6a3bbe560dee50c7c454d434add7fb8e837
245 245 P1
246 246
247 247 diff -r 12d9f6a3bbe5 -r c77a2661c64c p
248 248 --- a/p Thu Jan 01 00:00:03 1970 +0000
249 249 +++ b/p Thu Jan 01 00:00:04 1970 +0000
250 250 @@ -1,1 +1,1 @@
251 251 -mq1
252 252 +mq2
253 253
254 254 $ cd ..
255 255
256 256 Rebase with guards
257 257
258 258 $ hg init foo
259 259 $ cd foo
260 260 $ echo a > a
261 261 $ hg ci -Am a
262 262 adding a
263 263
264 264 Create mq repo with guarded patches foo and bar and empty patch:
265 265
266 266 $ hg qinit
267 267 $ echo guarded > guarded
268 268 $ hg add guarded
269 269 $ hg qnew guarded
270 270 $ hg qnew empty-important -m 'important commit message' -d '1 0'
271 271 $ echo bar > bar
272 272 $ hg add bar
273 273 $ hg qnew bar -d '2 0'
274 274 $ echo foo > foo
275 275 $ hg add foo
276 276 $ hg qnew foo
277 277 $ hg qpop -a
278 278 popping foo
279 279 popping bar
280 280 popping empty-important
281 281 popping guarded
282 282 patch queue now empty
283 283 $ hg qguard guarded +guarded
284 284 $ hg qguard bar +baz
285 285 $ hg qguard foo +baz
286 286 $ hg qselect baz
287 287 number of unguarded, unapplied patches has changed from 1 to 3
288 288 $ hg qpush bar
289 289 applying empty-important
290 290 patch empty-important is empty
291 291 applying bar
292 292 now at: bar
293 293
294 294 $ hg qguard -l
295 295 guarded: +guarded
296 296 empty-important: unguarded
297 297 bar: +baz
298 298 foo: +baz
299 299
300 300 $ hg tglog
301 301 @ 2: 4f44b861d38c 'imported patch bar' tags: bar qtip tip
302 302 |
303 303 o 1: 0aaf4c3af7eb 'important commit message' tags: empty-important qbase
304 304 |
305 305 o 0: cb9a9f314b8b 'a' tags: qparent
306 306
307 307 Create new head to rebase bar onto:
308 308
309 309 $ hg up -C 0
310 310 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
311 311 $ echo b > b
312 312 $ hg add b
313 313 $ hg ci -m b
314 314 created new head
315 315 $ hg up -C 2
316 316 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
317 317 $ echo a >> a
318 318 $ hg qref
319 319
320 320 $ hg tglog
321 321 @ 3: d526d4536ed6 '[mq]: bar' tags: bar qtip tip
322 322 |
323 323 | o 2: d2ae7f538514 'b' tags:
324 324 | |
325 325 o | 1: 0aaf4c3af7eb 'important commit message' tags: empty-important qbase
326 326 |/
327 327 o 0: cb9a9f314b8b 'a' tags: qparent
328 328
329 329
330 330 Rebase bar (make sure series order is preserved and empty-important also is
331 331 removed from the series):
332 332
333 333 $ hg qseries
334 334 guarded
335 335 empty-important
336 336 bar
337 337 foo
338 338 $ [ -f .hg/patches/empty-important ]
339 339 $ hg -q rebase -d 2
340 340 note: not rebasing 1:0aaf4c3af7eb empty-important qbase "important commit message", its destination already has all its changes
341 341 $ hg qseries
342 342 guarded
343 343 bar
344 344 foo
345 345 $ [ -f .hg/patches/empty-important ]
346 346 [1]
347 347
348 348 $ hg qguard -l
349 349 guarded: +guarded
350 350 bar: +baz
351 351 foo: +baz
352 352
353 353 $ hg tglog
354 354 @ 2: 477d948bb2af '[mq]: bar' tags: bar qbase qtip tip
355 355 |
356 356 o 1: d2ae7f538514 'b' tags: qparent
357 357 |
358 358 o 0: cb9a9f314b8b 'a' tags:
359 359
360 360 $ cd ..
@@ -1,543 +1,543 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 >
5 5 > [phases]
6 6 > publish=False
7 7 >
8 8 > [alias]
9 9 > tglog = log -G --template "{rev}: {node|short} '{desc}' {branches}\n"
10 10 > EOF
11 11
12 12 $ hg init a
13 13 $ cd a
14 14 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
15 15 adding changesets
16 16 adding manifests
17 17 adding file changes
18 18 added 8 changesets with 7 changes to 7 files (+2 heads)
19 19 new changesets cd010b8cd998:02de42196ebe (8 drafts)
20 20 (run 'hg heads' to see heads, 'hg merge' to merge)
21 21 $ hg up tip
22 22 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 23 $ cd ..
24 24
25 25 $ hg clone -q -u . a a1
26 26
27 27 $ cd a1
28 28
29 29 $ hg update 3
30 30 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
31 31 $ hg branch dev-one
32 32 marked working directory as branch dev-one
33 33 (branches are permanent and global, did you want a bookmark?)
34 34 $ hg ci -m 'dev-one named branch'
35 35
36 36 $ hg update 7
37 37 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
38 38 $ hg branch dev-two
39 39 marked working directory as branch dev-two
40 40
41 41 $ echo x > x
42 42
43 43 $ hg add x
44 44
45 45 $ hg ci -m 'dev-two named branch'
46 46
47 47 $ hg tglog
48 48 @ 9: cb039b7cae8e 'dev-two named branch' dev-two
49 49 |
50 50 | o 8: 643fc9128048 'dev-one named branch' dev-one
51 51 | |
52 52 o | 7: 02de42196ebe 'H'
53 53 | |
54 54 +---o 6: eea13746799a 'G'
55 55 | | |
56 56 o | | 5: 24b6387c8c8c 'F'
57 57 | | |
58 58 +---o 4: 9520eea781bc 'E'
59 59 | |
60 60 | o 3: 32af7686d403 'D'
61 61 | |
62 62 | o 2: 5fddd98957c8 'C'
63 63 | |
64 64 | o 1: 42ccdea3bb16 'B'
65 65 |/
66 66 o 0: cd010b8cd998 'A'
67 67
68 68
69 69 Branch name containing a dash (issue3181)
70 70
71 71 $ hg rebase -b dev-two -d dev-one --keepbranches
72 72 rebasing 5:24b6387c8c8c "F"
73 73 rebasing 6:eea13746799a "G"
74 74 rebasing 7:02de42196ebe "H"
75 75 rebasing 9:cb039b7cae8e tip "dev-two named branch"
76 76 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/24b6387c8c8c-24cb8001-rebase.hg
77 77
78 78 $ hg tglog
79 79 @ 9: 9e70cd31750f 'dev-two named branch' dev-two
80 80 |
81 81 o 8: 31d0e4ba75e6 'H'
82 82 |
83 83 | o 7: 4b988a958030 'G'
84 84 |/|
85 85 o | 6: 24de4aff8e28 'F'
86 86 | |
87 87 o | 5: 643fc9128048 'dev-one named branch' dev-one
88 88 | |
89 89 | o 4: 9520eea781bc 'E'
90 90 | |
91 91 o | 3: 32af7686d403 'D'
92 92 | |
93 93 o | 2: 5fddd98957c8 'C'
94 94 | |
95 95 o | 1: 42ccdea3bb16 'B'
96 96 |/
97 97 o 0: cd010b8cd998 'A'
98 98
99 99 $ hg rebase -s dev-one -d 0 --keepbranches
100 100 rebasing 5:643fc9128048 "dev-one named branch"
101 101 rebasing 6:24de4aff8e28 "F"
102 102 rebasing 7:4b988a958030 "G"
103 103 rebasing 8:31d0e4ba75e6 "H"
104 104 rebasing 9:9e70cd31750f tip "dev-two named branch"
105 105 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/643fc9128048-c4ee9ef5-rebase.hg
106 106
107 107 $ hg tglog
108 108 @ 9: 59c2e59309fe 'dev-two named branch' dev-two
109 109 |
110 110 o 8: 904590360559 'H'
111 111 |
112 112 | o 7: 1a1e6f72ec38 'G'
113 113 |/|
114 114 o | 6: 42aa3cf0fa7a 'F'
115 115 | |
116 116 o | 5: bc8139ee757c 'dev-one named branch' dev-one
117 117 | |
118 118 | o 4: 9520eea781bc 'E'
119 119 |/
120 120 | o 3: 32af7686d403 'D'
121 121 | |
122 122 | o 2: 5fddd98957c8 'C'
123 123 | |
124 124 | o 1: 42ccdea3bb16 'B'
125 125 |/
126 126 o 0: cd010b8cd998 'A'
127 127
128 128 $ hg update 3
129 129 3 files updated, 0 files merged, 3 files removed, 0 files unresolved
130 130 $ hg branch -f dev-one
131 131 marked working directory as branch dev-one
132 132 $ hg ci -m 'dev-one named branch'
133 133 created new head
134 134
135 135 $ hg tglog
136 136 @ 10: 643fc9128048 'dev-one named branch' dev-one
137 137 |
138 138 | o 9: 59c2e59309fe 'dev-two named branch' dev-two
139 139 | |
140 140 | o 8: 904590360559 'H'
141 141 | |
142 142 | | o 7: 1a1e6f72ec38 'G'
143 143 | |/|
144 144 | o | 6: 42aa3cf0fa7a 'F'
145 145 | | |
146 146 | o | 5: bc8139ee757c 'dev-one named branch' dev-one
147 147 | | |
148 148 | | o 4: 9520eea781bc 'E'
149 149 | |/
150 150 o | 3: 32af7686d403 'D'
151 151 | |
152 152 o | 2: 5fddd98957c8 'C'
153 153 | |
154 154 o | 1: 42ccdea3bb16 'B'
155 155 |/
156 156 o 0: cd010b8cd998 'A'
157 157
158 158 $ hg rebase -b 'max(branch("dev-two"))' -d dev-one --keepbranches
159 159 rebasing 5:bc8139ee757c "dev-one named branch"
160 160 note: not rebasing 5:bc8139ee757c "dev-one named branch", its destination already has all its changes
161 161 rebasing 6:42aa3cf0fa7a "F"
162 162 rebasing 7:1a1e6f72ec38 "G"
163 163 rebasing 8:904590360559 "H"
164 164 rebasing 9:59c2e59309fe "dev-two named branch"
165 165 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/bc8139ee757c-f11c1080-rebase.hg
166 166
167 167 $ hg tglog
168 168 o 9: 71325f8bc082 'dev-two named branch' dev-two
169 169 |
170 170 o 8: 12b2bc666e20 'H'
171 171 |
172 172 | o 7: 549f007a9f5f 'G'
173 173 |/|
174 174 o | 6: 679f28760620 'F'
175 175 | |
176 176 @ | 5: 643fc9128048 'dev-one named branch' dev-one
177 177 | |
178 178 | o 4: 9520eea781bc 'E'
179 179 | |
180 180 o | 3: 32af7686d403 'D'
181 181 | |
182 182 o | 2: 5fddd98957c8 'C'
183 183 | |
184 184 o | 1: 42ccdea3bb16 'B'
185 185 |/
186 186 o 0: cd010b8cd998 'A'
187 187
188 188 $ hg rebase -s 'max(branch("dev-one"))' -d 0 --keepbranches
189 189 rebasing 5:643fc9128048 "dev-one named branch"
190 190 rebasing 6:679f28760620 "F"
191 191 rebasing 7:549f007a9f5f "G"
192 192 rebasing 8:12b2bc666e20 "H"
193 193 rebasing 9:71325f8bc082 tip "dev-two named branch"
194 194 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/643fc9128048-6cdd1a52-rebase.hg
195 195
196 196 $ hg tglog
197 197 o 9: 3944801ae4ea 'dev-two named branch' dev-two
198 198 |
199 199 o 8: 8e279d293175 'H'
200 200 |
201 201 | o 7: aeefee77ab01 'G'
202 202 |/|
203 203 o | 6: e908b85f3729 'F'
204 204 | |
205 205 @ | 5: bc8139ee757c 'dev-one named branch' dev-one
206 206 | |
207 207 | o 4: 9520eea781bc 'E'
208 208 |/
209 209 | o 3: 32af7686d403 'D'
210 210 | |
211 211 | o 2: 5fddd98957c8 'C'
212 212 | |
213 213 | o 1: 42ccdea3bb16 'B'
214 214 |/
215 215 o 0: cd010b8cd998 'A'
216 216
217 217 $ hg up -r 0 > /dev/null
218 218
219 219 Rebasing descendant onto ancestor across different named branches
220 220
221 221 $ hg rebase -s 1 -d 9 --keepbranches
222 222 rebasing 1:42ccdea3bb16 "B"
223 223 rebasing 2:5fddd98957c8 "C"
224 224 rebasing 3:32af7686d403 "D"
225 225 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
226 226
227 227 $ hg tglog
228 228 o 9: e9f862ce8bad 'D'
229 229 |
230 230 o 8: a0d543090fa4 'C'
231 231 |
232 232 o 7: 3bdb949809d9 'B'
233 233 |
234 234 o 6: 3944801ae4ea 'dev-two named branch' dev-two
235 235 |
236 236 o 5: 8e279d293175 'H'
237 237 |
238 238 | o 4: aeefee77ab01 'G'
239 239 |/|
240 240 o | 3: e908b85f3729 'F'
241 241 | |
242 242 o | 2: bc8139ee757c 'dev-one named branch' dev-one
243 243 | |
244 244 | o 1: 9520eea781bc 'E'
245 245 |/
246 246 @ 0: cd010b8cd998 'A'
247 247
248 248 $ hg rebase -s 5 -d 6
249 249 abort: source and destination form a cycle
250 [255]
250 [10]
251 251
252 252 $ hg rebase -s 6 -d 5
253 253 rebasing 6:3944801ae4ea "dev-two named branch"
254 254 rebasing 7:3bdb949809d9 "B"
255 255 rebasing 8:a0d543090fa4 "C"
256 256 rebasing 9:e9f862ce8bad tip "D"
257 257 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/3944801ae4ea-fb46ed74-rebase.hg
258 258
259 259 $ hg tglog
260 260 o 9: e522577ccdbd 'D'
261 261 |
262 262 o 8: 810110211f50 'C'
263 263 |
264 264 o 7: 160b0930ccc6 'B'
265 265 |
266 266 o 6: c57724c84928 'dev-two named branch'
267 267 |
268 268 o 5: 8e279d293175 'H'
269 269 |
270 270 | o 4: aeefee77ab01 'G'
271 271 |/|
272 272 o | 3: e908b85f3729 'F'
273 273 | |
274 274 o | 2: bc8139ee757c 'dev-one named branch' dev-one
275 275 | |
276 276 | o 1: 9520eea781bc 'E'
277 277 |/
278 278 @ 0: cd010b8cd998 'A'
279 279
280 280
281 281 Reopen branch by rebase
282 282
283 283 $ hg up -qr3
284 284 $ hg branch -q b
285 285 $ hg ci -m 'create b'
286 286 $ hg ci -m 'close b' --close
287 287 $ hg rebase -b 8 -d b
288 288 reopening closed branch head 2b586e70108d
289 289 rebasing 5:8e279d293175 "H"
290 290 rebasing 6:c57724c84928 "dev-two named branch"
291 291 rebasing 7:160b0930ccc6 "B"
292 292 rebasing 8:810110211f50 "C"
293 293 rebasing 9:e522577ccdbd "D"
294 294 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/8e279d293175-b023e27c-rebase.hg
295 295
296 296 $ hg log -G -Tcompact
297 297 o 11[tip] be1dea60f2a6 2011-04-30 15:24 +0200 nicdumz
298 298 | D
299 299 |
300 300 o 10 ac34ce92632a 2011-04-30 15:24 +0200 nicdumz
301 301 | C
302 302 |
303 303 o 9 7bd665b6ce12 2011-04-30 15:24 +0200 nicdumz
304 304 | B
305 305 |
306 306 o 8 58e7c36e77f7 1970-01-01 00:00 +0000 test
307 307 | dev-two named branch
308 308 |
309 309 o 7 8e5a320651f3 2011-04-30 15:24 +0200 nicdumz
310 310 | H
311 311 |
312 312 @ 6 2b586e70108d 1970-01-01 00:00 +0000 test
313 313 | close b
314 314 |
315 315 o 5:3 3f9d5df8a707 1970-01-01 00:00 +0000 test
316 316 | create b
317 317 |
318 318 | o 4:3,1 aeefee77ab01 2011-04-30 15:24 +0200 nicdumz
319 319 |/| G
320 320 | |
321 321 o | 3 e908b85f3729 2011-04-30 15:24 +0200 nicdumz
322 322 | | F
323 323 | |
324 324 o | 2:0 bc8139ee757c 1970-01-01 00:00 +0000 test
325 325 | | dev-one named branch
326 326 | |
327 327 | o 1 9520eea781bc 2011-04-30 15:24 +0200 nicdumz
328 328 |/ E
329 329 |
330 330 o 0 cd010b8cd998 2011-04-30 15:24 +0200 nicdumz
331 331 A
332 332
333 333 $ echo A-mod > A
334 334 $ hg diff
335 335 diff -r 2b586e70108d A
336 336 --- a/A Thu Jan 01 00:00:00 1970 +0000
337 337 +++ b/A Thu Jan 01 00:00:00 1970 +0000
338 338 @@ -1,1 +1,1 @@
339 339 -A
340 340 +A-mod
341 341
342 342 --dry-run doesn't affect a dirty working directory that is unrelated to the
343 343 source or destination.
344 344
345 345 $ hg rebase -s tip -d 4 --dry-run
346 346 starting dry-run rebase; repository will not be changed
347 347 rebasing 11:be1dea60f2a6 tip "D"
348 348 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
349 349 $ hg diff
350 350 diff -r 2b586e70108d A
351 351 --- a/A Thu Jan 01 00:00:00 1970 +0000
352 352 +++ b/A Thu Jan 01 00:00:00 1970 +0000
353 353 @@ -1,1 +1,1 @@
354 354 -A
355 355 +A-mod
356 356
357 357 Bailing out on --confirm doesn't affect a dirty working directory that is
358 358 unrelated to the source or destination.
359 359
360 360 $ echo A-mod > A
361 361 $ echo n | hg rebase -s tip -d 4 --confirm --config ui.interactive=True
362 362 starting in-memory rebase
363 363 rebasing 11:be1dea60f2a6 tip "D"
364 364 rebase completed successfully
365 365 apply changes (yn)? n
366 366 $ hg diff
367 367 diff -r 2b586e70108d A
368 368 --- a/A Thu Jan 01 00:00:00 1970 +0000
369 369 +++ b/A Thu Jan 01 00:00:00 1970 +0000
370 370 @@ -1,1 +1,1 @@
371 371 -A
372 372 +A-mod
373 373
374 374 $ echo A-mod > A
375 375 $ hg rebase -s tip -d 4 --confirm
376 376 starting in-memory rebase
377 377 rebasing 11:be1dea60f2a6 tip "D"
378 378 rebase completed successfully
379 379 apply changes (yn)? y
380 380 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/be1dea60f2a6-ca6d2dac-rebase.hg
381 381 $ hg diff
382 382 diff -r 2b586e70108d A
383 383 --- a/A Thu Jan 01 00:00:00 1970 +0000
384 384 +++ b/A Thu Jan 01 00:00:00 1970 +0000
385 385 @@ -1,1 +1,1 @@
386 386 -A
387 387 +A-mod
388 388
389 389 Attempting to rebase the parent of a dirty working directory will abort, without
390 390 mangling the working directory...
391 391
392 392 $ hg rebase -s 5 -d 4 --dry-run
393 393 starting dry-run rebase; repository will not be changed
394 394 abort: uncommitted changes
395 395 [20]
396 396 $ hg diff
397 397 diff -r 2b586e70108d A
398 398 --- a/A Thu Jan 01 00:00:00 1970 +0000
399 399 +++ b/A Thu Jan 01 00:00:00 1970 +0000
400 400 @@ -1,1 +1,1 @@
401 401 -A
402 402 +A-mod
403 403
404 404 ... ditto for --confirm
405 405
406 406 $ echo n | hg rebase -s 5 -d 4 --confirm --config ui.interactive=True
407 407 starting in-memory rebase
408 408 abort: uncommitted changes
409 409 [20]
410 410 $ hg diff
411 411 diff -r 2b586e70108d A
412 412 --- a/A Thu Jan 01 00:00:00 1970 +0000
413 413 +++ b/A Thu Jan 01 00:00:00 1970 +0000
414 414 @@ -1,1 +1,1 @@
415 415 -A
416 416 +A-mod
417 417 $ hg rebase -s 5 -d 4 --confirm
418 418 starting in-memory rebase
419 419 abort: uncommitted changes
420 420 [20]
421 421 $ hg diff
422 422 diff -r 2b586e70108d A
423 423 --- a/A Thu Jan 01 00:00:00 1970 +0000
424 424 +++ b/A Thu Jan 01 00:00:00 1970 +0000
425 425 @@ -1,1 +1,1 @@
426 426 -A
427 427 +A-mod
428 428
429 429 $ cd ..
430 430
431 431 Rebase to other head on branch
432 432
433 433 Set up a case:
434 434
435 435 $ hg init case1
436 436 $ cd case1
437 437 $ touch f
438 438 $ hg ci -qAm0
439 439 $ hg branch -q b
440 440 $ echo >> f
441 441 $ hg ci -qAm 'b1'
442 442 $ hg up -qr -2
443 443 $ hg branch -qf b
444 444 $ hg ci -qm 'b2'
445 445 $ hg up -qr -3
446 446 $ hg branch -q c
447 447 $ hg ci -m 'c1'
448 448
449 449 $ hg tglog
450 450 @ 3: c062e3ecd6c6 'c1' c
451 451 |
452 452 | o 2: 792845bb77ee 'b2' b
453 453 |/
454 454 | o 1: 40039acb7ca5 'b1' b
455 455 |/
456 456 o 0: d681519c3ea7 '0'
457 457
458 458 $ hg clone -q . ../case2
459 459
460 460 rebase 'b2' to another lower branch head
461 461
462 462 $ hg up -qr 2
463 463 $ hg rebase
464 464 rebasing 2:792845bb77ee "b2"
465 465 note: not rebasing 2:792845bb77ee "b2", its destination already has all its changes
466 466 saved backup bundle to $TESTTMP/case1/.hg/strip-backup/792845bb77ee-627120ee-rebase.hg
467 467 $ hg tglog
468 468 o 2: c062e3ecd6c6 'c1' c
469 469 |
470 470 | @ 1: 40039acb7ca5 'b1' b
471 471 |/
472 472 o 0: d681519c3ea7 '0'
473 473
474 474
475 475 rebase 'b1' on top of the tip of the branch ('b2') - ignoring the tip branch ('c1')
476 476
477 477 $ cd ../case2
478 478 $ hg up -qr 1
479 479 $ hg rebase
480 480 rebasing 1:40039acb7ca5 "b1"
481 481 saved backup bundle to $TESTTMP/case2/.hg/strip-backup/40039acb7ca5-342b72d1-rebase.hg
482 482 $ hg tglog
483 483 @ 3: 76abc1c6f8c7 'b1' b
484 484 |
485 485 | o 2: c062e3ecd6c6 'c1' c
486 486 | |
487 487 o | 1: 792845bb77ee 'b2' b
488 488 |/
489 489 o 0: d681519c3ea7 '0'
490 490
491 491
492 492 rebase 'c1' to the branch head 'c2' that is closed
493 493
494 494 $ hg branch -qf c
495 495 $ hg ci -qm 'c2 closed' --close
496 496 $ hg up -qr 2
497 497 $ hg tglog
498 498 _ 4: 8427af5d86f2 'c2 closed' c
499 499 |
500 500 o 3: 76abc1c6f8c7 'b1' b
501 501 |
502 502 | @ 2: c062e3ecd6c6 'c1' c
503 503 | |
504 504 o | 1: 792845bb77ee 'b2' b
505 505 |/
506 506 o 0: d681519c3ea7 '0'
507 507
508 508 $ hg rebase
509 509 abort: branch 'c' has one head - please rebase to an explicit rev
510 510 (run 'hg heads' to see all heads, specify destination with -d)
511 511 [255]
512 512 $ hg tglog
513 513 _ 4: 8427af5d86f2 'c2 closed' c
514 514 |
515 515 o 3: 76abc1c6f8c7 'b1' b
516 516 |
517 517 | @ 2: c062e3ecd6c6 'c1' c
518 518 | |
519 519 o | 1: 792845bb77ee 'b2' b
520 520 |/
521 521 o 0: d681519c3ea7 '0'
522 522
523 523
524 524 $ hg up -cr 1
525 525 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
526 526 $ hg branch x
527 527 marked working directory as branch x
528 528 $ hg rebase -r 3:: -d .
529 529 rebasing 3:76abc1c6f8c7 "b1"
530 530 rebasing 4:8427af5d86f2 tip "c2 closed"
531 531 note: not rebasing 4:8427af5d86f2 tip "c2 closed", its destination already has all its changes
532 532 saved backup bundle to $TESTTMP/case2/.hg/strip-backup/76abc1c6f8c7-cd698d13-rebase.hg
533 533 $ hg tglog
534 534 o 3: 117b0ed08075 'b1' x
535 535 |
536 536 | o 2: c062e3ecd6c6 'c1' c
537 537 | |
538 538 @ | 1: 792845bb77ee 'b2' b
539 539 |/
540 540 o 0: d681519c3ea7 '0'
541 541
542 542
543 543 $ cd ..
@@ -1,385 +1,385 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 > drawdag=$TESTDIR/drawdag.py
5 5 > [alias]
6 6 > tglog = log -G --template "{rev}: {node|short} '{desc}' {branches}\n"
7 7 > EOF
8 8
9 9 $ hg init repo
10 10 $ cd repo
11 11
12 12 $ echo A > a
13 13 $ echo >> a
14 14 $ hg ci -Am A
15 15 adding a
16 16
17 17 $ echo B > a
18 18 $ echo >> a
19 19 $ hg ci -m B
20 20
21 21 $ echo C > a
22 22 $ echo >> a
23 23 $ hg ci -m C
24 24
25 25 $ hg up -q -C 0
26 26
27 27 $ echo D >> a
28 28 $ hg ci -Am AD
29 29 created new head
30 30
31 31 $ hg tglog
32 32 @ 3: 3878212183bd 'AD'
33 33 |
34 34 | o 2: 30ae917c0e4f 'C'
35 35 | |
36 36 | o 1: 0f4f7cb4f549 'B'
37 37 |/
38 38 o 0: 1e635d440a73 'A'
39 39
40 40 $ hg rebase -s 1 -d 3
41 41 rebasing 1:0f4f7cb4f549 "B"
42 42 merging a
43 43 rebasing 2:30ae917c0e4f "C"
44 44 merging a
45 45 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0f4f7cb4f549-82b3b163-rebase.hg
46 46
47 47 $ hg tglog
48 48 o 3: 25773bc4b4b0 'C'
49 49 |
50 50 o 2: c09015405f75 'B'
51 51 |
52 52 @ 1: 3878212183bd 'AD'
53 53 |
54 54 o 0: 1e635d440a73 'A'
55 55
56 56
57 57 $ cd ..
58 58
59 59
60 60 Test rebasing of merges with ancestors of the rebase destination - a situation
61 61 that often happens when trying to recover from repeated merging with a mainline
62 62 branch.
63 63
64 64 The test case creates a dev branch that contains a couple of merges from the
65 65 default branch. When rebasing to the default branch, these merges would be
66 66 merges with ancestors on the same branch. The merges _could_ contain some
67 67 interesting conflict resolutions or additional changes in the merge commit, but
68 68 that is mixed up with the actual merge stuff and there is in general no way to
69 69 separate them.
70 70
71 71 $ hg init ancestor-merge
72 72 $ cd ancestor-merge
73 73
74 74 $ touch f-default
75 75 $ hg ci -Aqm 'default: create f-default'
76 76
77 77 $ hg branch -q dev
78 78 $ hg ci -qm 'dev: create branch'
79 79
80 80 $ echo stuff > f-dev
81 81 $ hg ci -Aqm 'dev: f-dev stuff'
82 82
83 83 $ hg up -q default
84 84 $ echo stuff > f-default
85 85 $ hg ci -m 'default: f-default stuff'
86 86
87 87 $ hg up -q dev
88 88 $ hg merge -q default
89 89 $ hg ci -m 'dev: merge default'
90 90
91 91 $ hg up -q default
92 92 $ hg rm f-default
93 93 $ hg ci -m 'default: remove f-default'
94 94
95 95 $ hg up -q dev
96 96 $ hg merge -q default
97 97 $ hg ci -m 'dev: merge default'
98 98
99 99 $ hg up -q default
100 100 $ echo stuff > f-other
101 101 $ hg ci -Aqm 'default: f-other stuff'
102 102
103 103 $ hg tglog
104 104 @ 7: e08089805d82 'default: f-other stuff'
105 105 |
106 106 | o 6: 010ced67e558 'dev: merge default' dev
107 107 |/|
108 108 o | 5: 462860db70a1 'default: remove f-default'
109 109 | |
110 110 | o 4: 4b019212aaf6 'dev: merge default' dev
111 111 |/|
112 112 o | 3: f157ecfd2b6b 'default: f-default stuff'
113 113 | |
114 114 | o 2: ec2c14fb2984 'dev: f-dev stuff' dev
115 115 | |
116 116 | o 1: 1d1a643d390e 'dev: create branch' dev
117 117 |/
118 118 o 0: e90e8eb90b6f 'default: create f-default'
119 119
120 120 $ hg clone -qU . ../ancestor-merge-2
121 121
122 122 Full rebase all the way back from branching point:
123 123
124 124 $ hg rebase -r 'only(dev,default)' -d default --config ui.interactive=True << EOF
125 125 > c
126 126 > EOF
127 127 rebasing 1:1d1a643d390e "dev: create branch"
128 128 note: not rebasing 1:1d1a643d390e "dev: create branch", its destination already has all its changes
129 129 rebasing 2:ec2c14fb2984 "dev: f-dev stuff"
130 130 rebasing 4:4b019212aaf6 "dev: merge default"
131 131 note: not rebasing 4:4b019212aaf6 "dev: merge default", its destination already has all its changes
132 132 rebasing 6:010ced67e558 "dev: merge default"
133 133 note: not rebasing 6:010ced67e558 "dev: merge default", its destination already has all its changes
134 134 saved backup bundle to $TESTTMP/ancestor-merge/.hg/strip-backup/1d1a643d390e-4a6f6d17-rebase.hg
135 135 $ hg tglog
136 136 o 4: 3e075b1c0a40 'dev: f-dev stuff'
137 137 |
138 138 @ 3: e08089805d82 'default: f-other stuff'
139 139 |
140 140 o 2: 462860db70a1 'default: remove f-default'
141 141 |
142 142 o 1: f157ecfd2b6b 'default: f-default stuff'
143 143 |
144 144 o 0: e90e8eb90b6f 'default: create f-default'
145 145
146 146 Grafty cherry picking rebasing:
147 147
148 148 $ cd ../ancestor-merge-2
149 149
150 150 $ hg phase -fdr0:
151 151 $ hg rebase -r 'children(only(dev,default))' -d default --config ui.interactive=True << EOF
152 152 > c
153 153 > EOF
154 154 rebasing 2:ec2c14fb2984 "dev: f-dev stuff"
155 155 rebasing 4:4b019212aaf6 "dev: merge default"
156 156 abort: rebasing 4:4b019212aaf6 will include unwanted changes from 1:1d1a643d390e
157 [255]
157 [10]
158 158 $ cd ..
159 159
160 160
161 161 Test order of parents of rebased merged with un-rebased changes as p1.
162 162
163 163 $ hg init parentorder
164 164 $ cd parentorder
165 165 $ touch f
166 166 $ hg ci -Aqm common
167 167 $ touch change
168 168 $ hg ci -Aqm change
169 169 $ touch target
170 170 $ hg ci -Aqm target
171 171 $ hg up -qr 0
172 172 $ touch outside
173 173 $ hg ci -Aqm outside
174 174 $ hg merge -qr 1
175 175 $ hg ci -m 'merge p1 3=outside p2 1=ancestor'
176 176 $ hg par
177 177 changeset: 4:6990226659be
178 178 tag: tip
179 179 parent: 3:f59da8fc0fcf
180 180 parent: 1:dd40c13f7a6f
181 181 user: test
182 182 date: Thu Jan 01 00:00:00 1970 +0000
183 183 summary: merge p1 3=outside p2 1=ancestor
184 184
185 185 $ hg up -qr 1
186 186 $ hg merge -qr 3
187 187 $ hg ci -qm 'merge p1 1=ancestor p2 3=outside'
188 188 $ hg par
189 189 changeset: 5:a57575f79074
190 190 tag: tip
191 191 parent: 1:dd40c13f7a6f
192 192 parent: 3:f59da8fc0fcf
193 193 user: test
194 194 date: Thu Jan 01 00:00:00 1970 +0000
195 195 summary: merge p1 1=ancestor p2 3=outside
196 196
197 197 $ hg tglog
198 198 @ 5: a57575f79074 'merge p1 1=ancestor p2 3=outside'
199 199 |\
200 200 +---o 4: 6990226659be 'merge p1 3=outside p2 1=ancestor'
201 201 | |/
202 202 | o 3: f59da8fc0fcf 'outside'
203 203 | |
204 204 +---o 2: a60552eb93fb 'target'
205 205 | |
206 206 o | 1: dd40c13f7a6f 'change'
207 207 |/
208 208 o 0: 02f0f58d5300 'common'
209 209
210 210 $ hg rebase -r 4 -d 2
211 211 rebasing 4:6990226659be "merge p1 3=outside p2 1=ancestor"
212 212 saved backup bundle to $TESTTMP/parentorder/.hg/strip-backup/6990226659be-4d67a0d3-rebase.hg
213 213 $ hg tip
214 214 changeset: 5:cca50676b1c5
215 215 tag: tip
216 216 parent: 2:a60552eb93fb
217 217 parent: 3:f59da8fc0fcf
218 218 user: test
219 219 date: Thu Jan 01 00:00:00 1970 +0000
220 220 summary: merge p1 3=outside p2 1=ancestor
221 221
222 222 $ hg rebase -r 4 -d 2
223 223 rebasing 4:a57575f79074 "merge p1 1=ancestor p2 3=outside"
224 224 saved backup bundle to $TESTTMP/parentorder/.hg/strip-backup/a57575f79074-385426e5-rebase.hg
225 225 $ hg tip
226 226 changeset: 5:f9daf77ffe76
227 227 tag: tip
228 228 parent: 2:a60552eb93fb
229 229 parent: 3:f59da8fc0fcf
230 230 user: test
231 231 date: Thu Jan 01 00:00:00 1970 +0000
232 232 summary: merge p1 1=ancestor p2 3=outside
233 233
234 234 $ hg tglog
235 235 @ 5: f9daf77ffe76 'merge p1 1=ancestor p2 3=outside'
236 236 |\
237 237 +---o 4: cca50676b1c5 'merge p1 3=outside p2 1=ancestor'
238 238 | |/
239 239 | o 3: f59da8fc0fcf 'outside'
240 240 | |
241 241 o | 2: a60552eb93fb 'target'
242 242 | |
243 243 o | 1: dd40c13f7a6f 'change'
244 244 |/
245 245 o 0: 02f0f58d5300 'common'
246 246
247 247 rebase of merge of ancestors
248 248
249 249 $ hg up -qr 2
250 250 $ hg merge -qr 3
251 251 $ echo 'other change while merging future "rebase ancestors"' > other
252 252 $ hg ci -Aqm 'merge rebase ancestors'
253 253 $ hg rebase -d 5 -v
254 254 rebasing 6:4c5f12f25ebe tip "merge rebase ancestors"
255 255 resolving manifests
256 256 removing other
257 257 resolving manifests
258 258 getting other
259 259 committing files:
260 260 other
261 261 committing manifest
262 262 committing changelog
263 263 rebase merging completed
264 264 1 changesets found
265 265 uncompressed size of bundle content:
266 266 199 (changelog)
267 267 216 (manifests)
268 268 182 other
269 269 saved backup bundle to $TESTTMP/parentorder/.hg/strip-backup/4c5f12f25ebe-f46990e5-rebase.hg
270 270 1 changesets found
271 271 uncompressed size of bundle content:
272 272 254 (changelog)
273 273 167 (manifests)
274 274 182 other
275 275 adding branch
276 276 adding changesets
277 277 adding manifests
278 278 adding file changes
279 279 added 1 changesets with 1 changes to 1 files
280 280 rebase completed
281 281 $ hg tglog
282 282 @ 6: 113755df812b 'merge rebase ancestors'
283 283 |
284 284 o 5: f9daf77ffe76 'merge p1 1=ancestor p2 3=outside'
285 285 |\
286 286 +---o 4: cca50676b1c5 'merge p1 3=outside p2 1=ancestor'
287 287 | |/
288 288 | o 3: f59da8fc0fcf 'outside'
289 289 | |
290 290 o | 2: a60552eb93fb 'target'
291 291 | |
292 292 o | 1: dd40c13f7a6f 'change'
293 293 |/
294 294 o 0: 02f0f58d5300 'common'
295 295
296 296 Due to the limitation of 3-way merge algorithm (1 merge base), rebasing a merge
297 297 may include unwanted content:
298 298
299 299 $ hg init $TESTTMP/dual-merge-base1
300 300 $ cd $TESTTMP/dual-merge-base1
301 301 $ hg debugdrawdag <<'EOS'
302 302 > F
303 303 > /|
304 304 > D E
305 305 > | |
306 306 > B C
307 307 > |/
308 308 > A Z
309 309 > |/
310 310 > R
311 311 > EOS
312 312 $ hg rebase -r D+E+F -d Z
313 313 rebasing 5:5f2c926dfecf D "D"
314 314 rebasing 6:b296604d9846 E "E"
315 315 rebasing 7:caa9781e507d F tip "F"
316 316 abort: rebasing 7:caa9781e507d will include unwanted changes from 4:d6003a550c2c or 3:c1e6b162678d
317 [255]
317 [10]
318 318
319 319 The warning does not get printed if there is no unwanted change detected:
320 320
321 321 $ hg init $TESTTMP/dual-merge-base2
322 322 $ cd $TESTTMP/dual-merge-base2
323 323 $ hg debugdrawdag <<'EOS'
324 324 > D
325 325 > /|
326 326 > B C
327 327 > |/
328 328 > A Z
329 329 > |/
330 330 > R
331 331 > EOS
332 332 $ hg rebase -r B+C+D -d Z
333 333 rebasing 3:c1e6b162678d B "B"
334 334 rebasing 4:d6003a550c2c C "C"
335 335 rebasing 5:c8f78076273e D tip "D"
336 336 saved backup bundle to $TESTTMP/dual-merge-base2/.hg/strip-backup/d6003a550c2c-6f1424b6-rebase.hg
337 337 $ hg manifest -r 'desc(D)'
338 338 B
339 339 C
340 340 R
341 341 Z
342 342
343 343 The merge base could be different from old p1 (changed parent becomes new p1):
344 344
345 345 $ hg init $TESTTMP/chosen-merge-base1
346 346 $ cd $TESTTMP/chosen-merge-base1
347 347 $ hg debugdrawdag <<'EOS'
348 348 > F
349 349 > /|
350 350 > D E
351 351 > | |
352 352 > B C Z
353 353 > EOS
354 354 $ hg rebase -r D+F -d Z
355 355 rebasing 3:004dc1679908 D "D"
356 356 rebasing 5:4be4cbf6f206 F tip "F"
357 357 saved backup bundle to $TESTTMP/chosen-merge-base1/.hg/strip-backup/004dc1679908-06a66a3c-rebase.hg
358 358 $ hg manifest -r 'desc(F)'
359 359 C
360 360 D
361 361 E
362 362 Z
363 363 $ hg log -r `hg log -r 'desc(F)' -T '{p1node}'` -T '{desc}\n'
364 364 D
365 365
366 366 $ hg init $TESTTMP/chosen-merge-base2
367 367 $ cd $TESTTMP/chosen-merge-base2
368 368 $ hg debugdrawdag <<'EOS'
369 369 > F
370 370 > /|
371 371 > D E
372 372 > | |
373 373 > B C Z
374 374 > EOS
375 375 $ hg rebase -r E+F -d Z
376 376 rebasing 4:974e4943c210 E "E"
377 377 rebasing 5:4be4cbf6f206 F tip "F"
378 378 saved backup bundle to $TESTTMP/chosen-merge-base2/.hg/strip-backup/974e4943c210-b2874da5-rebase.hg
379 379 $ hg manifest -r 'desc(F)'
380 380 B
381 381 D
382 382 E
383 383 Z
384 384 $ hg log -r `hg log -r 'desc(F)' -T '{p1node}'` -T '{desc}\n'
385 385 E
@@ -1,2140 +1,2140 b''
1 1 ==========================
2 2 Test rebase with obsolete
3 3 ==========================
4 4
5 5 Enable obsolete
6 6
7 7 $ cat >> $HGRCPATH << EOF
8 8 > [command-templates]
9 9 > log= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')}
10 10 > [experimental]
11 11 > evolution.createmarkers=True
12 12 > evolution.allowunstable=True
13 13 > [phases]
14 14 > publish=False
15 15 > [extensions]
16 16 > rebase=
17 17 > drawdag=$TESTDIR/drawdag.py
18 18 > strip=
19 19 > EOF
20 20
21 21 Setup rebase canonical repo
22 22
23 23 $ hg init base
24 24 $ cd base
25 25 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
26 26 adding changesets
27 27 adding manifests
28 28 adding file changes
29 29 added 8 changesets with 7 changes to 7 files (+2 heads)
30 30 new changesets cd010b8cd998:02de42196ebe (8 drafts)
31 31 (run 'hg heads' to see heads, 'hg merge' to merge)
32 32 $ hg up tip
33 33 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 $ hg log -G
35 35 @ 7:02de42196ebe H
36 36 |
37 37 | o 6:eea13746799a G
38 38 |/|
39 39 o | 5:24b6387c8c8c F
40 40 | |
41 41 | o 4:9520eea781bc E
42 42 |/
43 43 | o 3:32af7686d403 D
44 44 | |
45 45 | o 2:5fddd98957c8 C
46 46 | |
47 47 | o 1:42ccdea3bb16 B
48 48 |/
49 49 o 0:cd010b8cd998 A
50 50
51 51 $ cd ..
52 52
53 53 simple rebase
54 54 ---------------------------------
55 55
56 56 $ hg clone base simple
57 57 updating to branch default
58 58 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 59 $ cd simple
60 60 $ hg up 32af7686d403
61 61 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
62 62 $ hg rebase -d eea13746799a
63 63 rebasing 1:42ccdea3bb16 "B"
64 64 rebasing 2:5fddd98957c8 "C"
65 65 rebasing 3:32af7686d403 "D"
66 66 $ hg log -G
67 67 @ 10:8eeb3c33ad33 D
68 68 |
69 69 o 9:2327fea05063 C
70 70 |
71 71 o 8:e4e5be0395b2 B
72 72 |
73 73 | o 7:02de42196ebe H
74 74 | |
75 75 o | 6:eea13746799a G
76 76 |\|
77 77 | o 5:24b6387c8c8c F
78 78 | |
79 79 o | 4:9520eea781bc E
80 80 |/
81 81 o 0:cd010b8cd998 A
82 82
83 83 $ hg log --hidden -G
84 84 @ 10:8eeb3c33ad33 D
85 85 |
86 86 o 9:2327fea05063 C
87 87 |
88 88 o 8:e4e5be0395b2 B
89 89 |
90 90 | o 7:02de42196ebe H
91 91 | |
92 92 o | 6:eea13746799a G
93 93 |\|
94 94 | o 5:24b6387c8c8c F
95 95 | |
96 96 o | 4:9520eea781bc E
97 97 |/
98 98 | x 3:32af7686d403 D (rewritten using rebase as 10:8eeb3c33ad33)
99 99 | |
100 100 | x 2:5fddd98957c8 C (rewritten using rebase as 9:2327fea05063)
101 101 | |
102 102 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:e4e5be0395b2)
103 103 |/
104 104 o 0:cd010b8cd998 A
105 105
106 106 $ hg debugobsolete
107 107 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
108 108 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
109 109 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
110 110
111 111
112 112 $ cd ..
113 113
114 114 empty changeset
115 115 ---------------------------------
116 116
117 117 $ hg clone base empty
118 118 updating to branch default
119 119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 120 $ cd empty
121 121 $ hg up eea13746799a
122 122 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
123 123
124 124 We make a copy of both the first changeset in the rebased and some other in the
125 125 set.
126 126
127 127 $ hg graft 42ccdea3bb16 32af7686d403
128 128 grafting 1:42ccdea3bb16 "B"
129 129 grafting 3:32af7686d403 "D"
130 130 $ hg rebase -s 42ccdea3bb16 -d .
131 131 rebasing 1:42ccdea3bb16 "B"
132 132 note: not rebasing 1:42ccdea3bb16 "B", its destination already has all its changes
133 133 rebasing 2:5fddd98957c8 "C"
134 134 rebasing 3:32af7686d403 "D"
135 135 note: not rebasing 3:32af7686d403 "D", its destination already has all its changes
136 136 $ hg log -G
137 137 o 10:5ae4c968c6ac C
138 138 |
139 139 @ 9:08483444fef9 D
140 140 |
141 141 o 8:8877864f1edb B
142 142 |
143 143 | o 7:02de42196ebe H
144 144 | |
145 145 o | 6:eea13746799a G
146 146 |\|
147 147 | o 5:24b6387c8c8c F
148 148 | |
149 149 o | 4:9520eea781bc E
150 150 |/
151 151 o 0:cd010b8cd998 A
152 152
153 153 $ hg log --hidden -G
154 154 o 10:5ae4c968c6ac C
155 155 |
156 156 @ 9:08483444fef9 D
157 157 |
158 158 o 8:8877864f1edb B
159 159 |
160 160 | o 7:02de42196ebe H
161 161 | |
162 162 o | 6:eea13746799a G
163 163 |\|
164 164 | o 5:24b6387c8c8c F
165 165 | |
166 166 o | 4:9520eea781bc E
167 167 |/
168 168 | x 3:32af7686d403 D (pruned using rebase)
169 169 | |
170 170 | x 2:5fddd98957c8 C (rewritten using rebase as 10:5ae4c968c6ac)
171 171 | |
172 172 | x 1:42ccdea3bb16 B (pruned using rebase)
173 173 |/
174 174 o 0:cd010b8cd998 A
175 175
176 176 $ hg debugobsolete
177 177 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
178 178 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
179 179 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
180 180
181 181
182 182 More complex case where part of the rebase set were already rebased
183 183
184 184 $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
185 185 rebasing 9:08483444fef9 "D"
186 186 1 new orphan changesets
187 187 $ hg debugobsolete
188 188 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
189 189 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
190 190 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
191 191 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
192 192 $ hg log -G
193 193 @ 11:4596109a6a43 D
194 194 |
195 195 | * 10:5ae4c968c6ac C
196 196 | |
197 197 | x 9:08483444fef9 D (rewritten using rebase as 11:4596109a6a43)
198 198 | |
199 199 | o 8:8877864f1edb B
200 200 | |
201 201 o | 7:02de42196ebe H
202 202 | |
203 203 | o 6:eea13746799a G
204 204 |/|
205 205 o | 5:24b6387c8c8c F
206 206 | |
207 207 | o 4:9520eea781bc E
208 208 |/
209 209 o 0:cd010b8cd998 A
210 210
211 211 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
212 212 rebasing 8:8877864f1edb "B"
213 213 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 tip "D"
214 214 rebasing 10:5ae4c968c6ac "C"
215 215 $ hg debugobsolete
216 216 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
217 217 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
218 218 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
219 219 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
220 220 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
221 221 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
222 222 $ hg log --rev 'contentdivergent()'
223 223 $ hg log -G
224 224 o 13:98f6af4ee953 C
225 225 |
226 226 o 12:462a34d07e59 B
227 227 |
228 228 @ 11:4596109a6a43 D
229 229 |
230 230 o 7:02de42196ebe H
231 231 |
232 232 | o 6:eea13746799a G
233 233 |/|
234 234 o | 5:24b6387c8c8c F
235 235 | |
236 236 | o 4:9520eea781bc E
237 237 |/
238 238 o 0:cd010b8cd998 A
239 239
240 240 $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
241 241 changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
242 242 phase: draft
243 243 parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
244 244 parent: -1:0000000000000000000000000000000000000000
245 245 manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
246 246 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
247 247 date: Sat Apr 30 15:24:48 2011 +0200
248 248 files+: D
249 249 extra: branch=default
250 250 extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
251 251 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
252 252 description:
253 253 D
254 254
255 255
256 256 $ hg up -qr 'desc(G)'
257 257 $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
258 258 grafting 11:4596109a6a43 "D"
259 259 $ hg up -qr 'desc(E)'
260 260 $ hg rebase -s tip -d .
261 261 rebasing 14:9e36056a46e3 tip "D"
262 262 $ hg log --style default --debug -r tip
263 263 changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab
264 264 tag: tip
265 265 phase: draft
266 266 parent: 4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
267 267 parent: -1:0000000000000000000000000000000000000000
268 268 manifest: 15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
269 269 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
270 270 date: Sat Apr 30 15:24:48 2011 +0200
271 271 files+: D
272 272 extra: branch=default
273 273 extra: intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
274 274 extra: rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
275 275 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
276 276 description:
277 277 D
278 278
279 279
280 280 Start rebase from a commit that is obsolete but not hidden only because it's
281 281 a working copy parent. We should be moved back to the starting commit as usual
282 282 even though it is hidden (until we're moved there).
283 283
284 284 $ hg --hidden up -qr 'first(hidden())'
285 285 updated to hidden changeset 42ccdea3bb16
286 286 (hidden revision '42ccdea3bb16' is pruned)
287 287 $ hg rebase --rev 13 --dest 15
288 288 rebasing 13:98f6af4ee953 "C"
289 289 $ hg log -G
290 290 o 16:294a2b93eb4d C
291 291 |
292 292 o 15:627d46148090 D
293 293 |
294 294 | o 12:462a34d07e59 B
295 295 | |
296 296 | o 11:4596109a6a43 D
297 297 | |
298 298 | o 7:02de42196ebe H
299 299 | |
300 300 +---o 6:eea13746799a G
301 301 | |/
302 302 | o 5:24b6387c8c8c F
303 303 | |
304 304 o | 4:9520eea781bc E
305 305 |/
306 306 | @ 1:42ccdea3bb16 B (pruned using rebase)
307 307 |/
308 308 o 0:cd010b8cd998 A
309 309
310 310
311 311 $ cd ..
312 312
313 313 collapse rebase
314 314 ---------------------------------
315 315
316 316 $ hg clone base collapse
317 317 updating to branch default
318 318 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 319 $ cd collapse
320 320 $ hg rebase -s 42ccdea3bb16 -d eea13746799a --collapse
321 321 rebasing 1:42ccdea3bb16 "B"
322 322 rebasing 2:5fddd98957c8 "C"
323 323 rebasing 3:32af7686d403 "D"
324 324 $ hg log -G
325 325 o 8:4dc2197e807b Collapsed revision
326 326 |
327 327 | @ 7:02de42196ebe H
328 328 | |
329 329 o | 6:eea13746799a G
330 330 |\|
331 331 | o 5:24b6387c8c8c F
332 332 | |
333 333 o | 4:9520eea781bc E
334 334 |/
335 335 o 0:cd010b8cd998 A
336 336
337 337 $ hg log --hidden -G
338 338 o 8:4dc2197e807b Collapsed revision
339 339 |
340 340 | @ 7:02de42196ebe H
341 341 | |
342 342 o | 6:eea13746799a G
343 343 |\|
344 344 | o 5:24b6387c8c8c F
345 345 | |
346 346 o | 4:9520eea781bc E
347 347 |/
348 348 | x 3:32af7686d403 D (rewritten using rebase as 8:4dc2197e807b)
349 349 | |
350 350 | x 2:5fddd98957c8 C (rewritten using rebase as 8:4dc2197e807b)
351 351 | |
352 352 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:4dc2197e807b)
353 353 |/
354 354 o 0:cd010b8cd998 A
355 355
356 356 $ hg id --debug -r tip
357 357 4dc2197e807bae9817f09905b50ab288be2dbbcf tip
358 358 $ hg debugobsolete
359 359 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '1', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
360 360 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '2', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
361 361 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '3', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
362 362
363 363 $ cd ..
364 364
365 365 Rebase set has hidden descendants
366 366 ---------------------------------
367 367
368 368 We rebase a changeset which has hidden descendants. Hidden changesets must not
369 369 be rebased.
370 370
371 371 $ hg clone base hidden
372 372 updating to branch default
373 373 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 374 $ cd hidden
375 375 $ hg log -G
376 376 @ 7:02de42196ebe H
377 377 |
378 378 | o 6:eea13746799a G
379 379 |/|
380 380 o | 5:24b6387c8c8c F
381 381 | |
382 382 | o 4:9520eea781bc E
383 383 |/
384 384 | o 3:32af7686d403 D
385 385 | |
386 386 | o 2:5fddd98957c8 C
387 387 | |
388 388 | o 1:42ccdea3bb16 B
389 389 |/
390 390 o 0:cd010b8cd998 A
391 391
392 392 $ hg rebase -s 5fddd98957c8 -d eea13746799a
393 393 rebasing 2:5fddd98957c8 "C"
394 394 rebasing 3:32af7686d403 "D"
395 395 $ hg log -G
396 396 o 9:cf44d2f5a9f4 D
397 397 |
398 398 o 8:e273c5e7d2d2 C
399 399 |
400 400 | @ 7:02de42196ebe H
401 401 | |
402 402 o | 6:eea13746799a G
403 403 |\|
404 404 | o 5:24b6387c8c8c F
405 405 | |
406 406 o | 4:9520eea781bc E
407 407 |/
408 408 | o 1:42ccdea3bb16 B
409 409 |/
410 410 o 0:cd010b8cd998 A
411 411
412 412 $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
413 413 rebasing 1:42ccdea3bb16 "B"
414 414 $ hg log -G
415 415 o 10:7c6027df6a99 B
416 416 |
417 417 | o 9:cf44d2f5a9f4 D
418 418 | |
419 419 | o 8:e273c5e7d2d2 C
420 420 | |
421 421 @ | 7:02de42196ebe H
422 422 | |
423 423 | o 6:eea13746799a G
424 424 |/|
425 425 o | 5:24b6387c8c8c F
426 426 | |
427 427 | o 4:9520eea781bc E
428 428 |/
429 429 o 0:cd010b8cd998 A
430 430
431 431 $ hg log --hidden -G
432 432 o 10:7c6027df6a99 B
433 433 |
434 434 | o 9:cf44d2f5a9f4 D
435 435 | |
436 436 | o 8:e273c5e7d2d2 C
437 437 | |
438 438 @ | 7:02de42196ebe H
439 439 | |
440 440 | o 6:eea13746799a G
441 441 |/|
442 442 o | 5:24b6387c8c8c F
443 443 | |
444 444 | o 4:9520eea781bc E
445 445 |/
446 446 | x 3:32af7686d403 D (rewritten using rebase as 9:cf44d2f5a9f4)
447 447 | |
448 448 | x 2:5fddd98957c8 C (rewritten using rebase as 8:e273c5e7d2d2)
449 449 | |
450 450 | x 1:42ccdea3bb16 B (rewritten using rebase as 10:7c6027df6a99)
451 451 |/
452 452 o 0:cd010b8cd998 A
453 453
454 454 $ hg debugobsolete
455 455 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
456 456 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
457 457 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
458 458
459 459 Test that rewriting leaving instability behind is allowed
460 460 ---------------------------------------------------------------------
461 461
462 462 $ hg log -r 'children(8)'
463 463 9:cf44d2f5a9f4 D (no-eol)
464 464 $ hg rebase -r 8
465 465 rebasing 8:e273c5e7d2d2 "C"
466 466 1 new orphan changesets
467 467 $ hg log -G
468 468 o 11:0d8f238b634c C
469 469 |
470 470 o 10:7c6027df6a99 B
471 471 |
472 472 | * 9:cf44d2f5a9f4 D
473 473 | |
474 474 | x 8:e273c5e7d2d2 C (rewritten using rebase as 11:0d8f238b634c)
475 475 | |
476 476 @ | 7:02de42196ebe H
477 477 | |
478 478 | o 6:eea13746799a G
479 479 |/|
480 480 o | 5:24b6387c8c8c F
481 481 | |
482 482 | o 4:9520eea781bc E
483 483 |/
484 484 o 0:cd010b8cd998 A
485 485
486 486 $ cd ..
487 487 $ cp -R hidden stabilize
488 488 $ cd stabilize
489 489 $ hg rebase --auto-orphans '0::' -d 10
490 490 abort: cannot specify both --auto-orphans and --dest
491 491 [10]
492 492 $ hg rebase --auto-orphans '0::'
493 493 rebasing 9:cf44d2f5a9f4 "D"
494 494 $ hg log -G
495 495 o 12:7e3935feaa68 D
496 496 |
497 497 o 11:0d8f238b634c C
498 498 |
499 499 o 10:7c6027df6a99 B
500 500 |
501 501 @ 7:02de42196ebe H
502 502 |
503 503 | o 6:eea13746799a G
504 504 |/|
505 505 o | 5:24b6387c8c8c F
506 506 | |
507 507 | o 4:9520eea781bc E
508 508 |/
509 509 o 0:cd010b8cd998 A
510 510
511 511
512 512 $ cd ../hidden
513 513 $ rm -r ../stabilize
514 514
515 515 Test multiple root handling
516 516 ------------------------------------
517 517
518 518 $ hg rebase --dest 4 --rev '7+11+9'
519 519 rebasing 9:cf44d2f5a9f4 "D"
520 520 rebasing 7:02de42196ebe "H"
521 521 rebasing 11:0d8f238b634c tip "C"
522 522 $ hg log -G
523 523 o 14:1e8370e38cca C
524 524 |
525 525 @ 13:bfe264faf697 H
526 526 |
527 527 | o 12:102b4c1d889b D
528 528 |/
529 529 | * 10:7c6027df6a99 B
530 530 | |
531 531 | x 7:02de42196ebe H (rewritten using rebase as 13:bfe264faf697)
532 532 | |
533 533 +---o 6:eea13746799a G
534 534 | |/
535 535 | o 5:24b6387c8c8c F
536 536 | |
537 537 o | 4:9520eea781bc E
538 538 |/
539 539 o 0:cd010b8cd998 A
540 540
541 541 $ cd ..
542 542
543 543 Detach both parents
544 544
545 545 $ hg init double-detach
546 546 $ cd double-detach
547 547
548 548 $ hg debugdrawdag <<EOF
549 549 > F
550 550 > /|
551 551 > C E
552 552 > | |
553 553 > B D G
554 554 > \|/
555 555 > A
556 556 > EOF
557 557
558 558 $ hg rebase -d G -r 'B + D + F'
559 559 rebasing 1:112478962961 B "B"
560 560 rebasing 2:b18e25de2cf5 D "D"
561 561 rebasing 6:f15c3adaf214 F tip "F"
562 562 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
563 [255]
563 [10]
564 564
565 565 $ cd ..
566 566
567 567 test on rebase dropping a merge
568 568
569 569 (setup)
570 570
571 571 $ hg init dropmerge
572 572 $ cd dropmerge
573 573 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
574 574 adding changesets
575 575 adding manifests
576 576 adding file changes
577 577 added 8 changesets with 7 changes to 7 files (+2 heads)
578 578 new changesets cd010b8cd998:02de42196ebe (8 drafts)
579 579 (run 'hg heads' to see heads, 'hg merge' to merge)
580 580 $ hg up 3
581 581 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
582 582 $ hg merge 7
583 583 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 584 (branch merge, don't forget to commit)
585 585 $ hg ci -m 'M'
586 586 $ echo I > I
587 587 $ hg add I
588 588 $ hg ci -m I
589 589 $ hg log -G
590 590 @ 9:4bde274eefcf I
591 591 |
592 592 o 8:53a6a128b2b7 M
593 593 |\
594 594 | o 7:02de42196ebe H
595 595 | |
596 596 | | o 6:eea13746799a G
597 597 | |/|
598 598 | o | 5:24b6387c8c8c F
599 599 | | |
600 600 | | o 4:9520eea781bc E
601 601 | |/
602 602 o | 3:32af7686d403 D
603 603 | |
604 604 o | 2:5fddd98957c8 C
605 605 | |
606 606 o | 1:42ccdea3bb16 B
607 607 |/
608 608 o 0:cd010b8cd998 A
609 609
610 610 (actual test)
611 611
612 612 $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)'
613 613 rebasing 3:32af7686d403 "D"
614 614 rebasing 7:02de42196ebe "H"
615 615 rebasing 9:4bde274eefcf tip "I"
616 616 1 new orphan changesets
617 617 $ hg log -G
618 618 @ 12:acd174b7ab39 I
619 619 |
620 620 o 11:6c11a6218c97 H
621 621 |
622 622 | o 10:b5313c85b22e D
623 623 |/
624 624 | * 8:53a6a128b2b7 M
625 625 | |\
626 626 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
627 627 | | |
628 628 o---+ 6:eea13746799a G
629 629 | | |
630 630 | | o 5:24b6387c8c8c F
631 631 | | |
632 632 o---+ 4:9520eea781bc E
633 633 / /
634 634 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
635 635 | |
636 636 o | 2:5fddd98957c8 C
637 637 | |
638 638 o | 1:42ccdea3bb16 B
639 639 |/
640 640 o 0:cd010b8cd998 A
641 641
642 642
643 643 Test hidden changesets in the rebase set (issue4504)
644 644
645 645 $ hg up --hidden 9
646 646 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
647 647 updated to hidden changeset 4bde274eefcf
648 648 (hidden revision '4bde274eefcf' was rewritten as: acd174b7ab39)
649 649 $ echo J > J
650 650 $ hg add J
651 651 $ hg commit -m J
652 652 1 new orphan changesets
653 653 $ hg debugobsolete `hg log --rev . -T '{node}'`
654 654 1 new obsolescence markers
655 655 obsoleted 1 changesets
656 656
657 657 $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off
658 658 rebasing 9:4bde274eefcf "I"
659 659 rebasing 13:06edfc82198f tip "J"
660 660 2 new content-divergent changesets
661 661 $ hg log -G
662 662 @ 15:5ae8a643467b J
663 663 |
664 664 * 14:9ad579b4a5de I
665 665 |
666 666 | * 12:acd174b7ab39 I
667 667 | |
668 668 | o 11:6c11a6218c97 H
669 669 | |
670 670 o | 10:b5313c85b22e D
671 671 |/
672 672 | * 8:53a6a128b2b7 M
673 673 | |\
674 674 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
675 675 | | |
676 676 o---+ 6:eea13746799a G
677 677 | | |
678 678 | | o 5:24b6387c8c8c F
679 679 | | |
680 680 o---+ 4:9520eea781bc E
681 681 / /
682 682 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
683 683 | |
684 684 o | 2:5fddd98957c8 C
685 685 | |
686 686 o | 1:42ccdea3bb16 B
687 687 |/
688 688 o 0:cd010b8cd998 A
689 689
690 690 $ hg up 14 -C
691 691 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
692 692 $ echo "K" > K
693 693 $ hg add K
694 694 $ hg commit --amend -m "K"
695 695 1 new orphan changesets
696 696 $ echo "L" > L
697 697 $ hg add L
698 698 $ hg commit -m "L"
699 699 $ hg up '.^'
700 700 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
701 701 $ echo "M" > M
702 702 $ hg add M
703 703 $ hg commit --amend -m "M"
704 704 1 new orphan changesets
705 705 $ hg log -G
706 706 @ 18:bfaedf8eb73b M
707 707 |
708 708 | * 17:97219452e4bd L
709 709 | |
710 710 | x 16:fc37a630c901 K (rewritten using amend as 18:bfaedf8eb73b)
711 711 |/
712 712 | * 15:5ae8a643467b J
713 713 | |
714 714 | x 14:9ad579b4a5de I (rewritten using amend as 16:fc37a630c901)
715 715 |/
716 716 | * 12:acd174b7ab39 I
717 717 | |
718 718 | o 11:6c11a6218c97 H
719 719 | |
720 720 o | 10:b5313c85b22e D
721 721 |/
722 722 | * 8:53a6a128b2b7 M
723 723 | |\
724 724 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
725 725 | | |
726 726 o---+ 6:eea13746799a G
727 727 | | |
728 728 | | o 5:24b6387c8c8c F
729 729 | | |
730 730 o---+ 4:9520eea781bc E
731 731 / /
732 732 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
733 733 | |
734 734 o | 2:5fddd98957c8 C
735 735 | |
736 736 o | 1:42ccdea3bb16 B
737 737 |/
738 738 o 0:cd010b8cd998 A
739 739
740 740 $ hg rebase -s 14 -d 17 --config experimental.rebaseskipobsolete=True
741 741 note: not rebasing 14:9ad579b4a5de "I", already in destination as 16:fc37a630c901 "K"
742 742 rebasing 15:5ae8a643467b "J"
743 743 1 new orphan changesets
744 744
745 745 $ cd ..
746 746
747 747 Skip obsolete changeset even with multiple hops
748 748 -----------------------------------------------
749 749
750 750 setup
751 751
752 752 $ hg init obsskip
753 753 $ cd obsskip
754 754 $ cat << EOF >> .hg/hgrc
755 755 > [experimental]
756 756 > rebaseskipobsolete = True
757 757 > [extensions]
758 758 > strip =
759 759 > EOF
760 760 $ echo A > A
761 761 $ hg add A
762 762 $ hg commit -m A
763 763 $ echo B > B
764 764 $ hg add B
765 765 $ hg commit -m B0
766 766 $ hg commit --amend -m B1
767 767 $ hg commit --amend -m B2
768 768 $ hg up --hidden 'desc(B0)'
769 769 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
770 770 updated to hidden changeset a8b11f55fb19
771 771 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
772 772 $ echo C > C
773 773 $ hg add C
774 774 $ hg commit -m C
775 775 1 new orphan changesets
776 776 $ hg log -G
777 777 @ 4:212cb178bcbb C
778 778 |
779 779 | o 3:261e70097290 B2
780 780 | |
781 781 x | 1:a8b11f55fb19 B0 (rewritten using amend as 3:261e70097290)
782 782 |/
783 783 o 0:4a2df7238c3b A
784 784
785 785
786 786 Rebase finds its way in a chain of marker
787 787
788 788 $ hg rebase -d 'desc(B2)'
789 789 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2"
790 790 rebasing 4:212cb178bcbb tip "C"
791 791
792 792 Even when the chain include missing node
793 793
794 794 $ hg up --hidden 'desc(B0)'
795 795 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
796 796 updated to hidden changeset a8b11f55fb19
797 797 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
798 798 $ echo D > D
799 799 $ hg add D
800 800 $ hg commit -m D
801 801 1 new orphan changesets
802 802 $ hg --hidden strip -r 'desc(B1)'
803 803 saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg
804 804 1 new orphan changesets
805 805 $ hg log -G
806 806 @ 5:1a79b7535141 D
807 807 |
808 808 | o 4:ff2c4d47b71d C
809 809 | |
810 810 | o 2:261e70097290 B2
811 811 | |
812 812 x | 1:a8b11f55fb19 B0 (rewritten using amend as 2:261e70097290)
813 813 |/
814 814 o 0:4a2df7238c3b A
815 815
816 816
817 817 $ hg rebase -d 'desc(B2)'
818 818 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2"
819 819 rebasing 5:1a79b7535141 tip "D"
820 820 $ hg up 4
821 821 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
822 822 $ echo "O" > O
823 823 $ hg add O
824 824 $ hg commit -m O
825 825 $ echo "P" > P
826 826 $ hg add P
827 827 $ hg commit -m P
828 828 $ hg log -G
829 829 @ 8:8d47583e023f P
830 830 |
831 831 o 7:360bbaa7d3ce O
832 832 |
833 833 | o 6:9c48361117de D
834 834 | |
835 835 o | 4:ff2c4d47b71d C
836 836 |/
837 837 o 2:261e70097290 B2
838 838 |
839 839 o 0:4a2df7238c3b A
840 840
841 841 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.evolution=true
842 842 1 new obsolescence markers
843 843 obsoleted 1 changesets
844 844 1 new orphan changesets
845 845 $ hg rebase -d 6 -r "4::"
846 846 rebasing 4:ff2c4d47b71d "C"
847 847 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
848 848 rebasing 8:8d47583e023f tip "P"
849 849
850 850 If all the changeset to be rebased are obsolete and present in the destination, we
851 851 should display a friendly error message
852 852
853 853 $ hg log -G
854 854 @ 10:121d9e3bc4c6 P
855 855 |
856 856 o 9:4be60e099a77 C
857 857 |
858 858 o 6:9c48361117de D
859 859 |
860 860 o 2:261e70097290 B2
861 861 |
862 862 o 0:4a2df7238c3b A
863 863
864 864
865 865 $ hg up 9
866 866 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
867 867 $ echo "non-relevant change" > nonrelevant
868 868 $ hg add nonrelevant
869 869 $ hg commit -m nonrelevant
870 870 created new head
871 871 $ hg debugobsolete `hg log -r 11 -T '{node}\n'` --config experimental.evolution=true
872 872 1 new obsolescence markers
873 873 obsoleted 1 changesets
874 874 $ hg log -G
875 875 @ 11:f44da1f4954c nonrelevant (pruned)
876 876 |
877 877 | o 10:121d9e3bc4c6 P
878 878 |/
879 879 o 9:4be60e099a77 C
880 880 |
881 881 o 6:9c48361117de D
882 882 |
883 883 o 2:261e70097290 B2
884 884 |
885 885 o 0:4a2df7238c3b A
886 886
887 887 $ hg rebase -r . -d 10
888 888 note: not rebasing 11:f44da1f4954c tip "nonrelevant", it has no successor
889 889
890 890 If a rebase is going to create divergence, it should abort
891 891
892 892 $ hg log -G
893 893 @ 10:121d9e3bc4c6 P
894 894 |
895 895 o 9:4be60e099a77 C
896 896 |
897 897 o 6:9c48361117de D
898 898 |
899 899 o 2:261e70097290 B2
900 900 |
901 901 o 0:4a2df7238c3b A
902 902
903 903
904 904 $ hg up 9
905 905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
906 906 $ echo "john" > doe
907 907 $ hg add doe
908 908 $ hg commit -m "john doe"
909 909 created new head
910 910 $ hg up 10
911 911 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
912 912 $ echo "foo" > bar
913 913 $ hg add bar
914 914 $ hg commit --amend -m "10'"
915 915 $ hg up 10 --hidden
916 916 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
917 917 updated to hidden changeset 121d9e3bc4c6
918 918 (hidden revision '121d9e3bc4c6' was rewritten as: 77d874d096a2)
919 919 $ echo "bar" > foo
920 920 $ hg add foo
921 921 $ hg commit -m "bar foo"
922 922 1 new orphan changesets
923 923 $ hg log -G
924 924 @ 14:73568ab6879d bar foo
925 925 |
926 926 | o 13:77d874d096a2 10'
927 927 | |
928 928 | | o 12:3eb461388009 john doe
929 929 | |/
930 930 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
931 931 |/
932 932 o 9:4be60e099a77 C
933 933 |
934 934 o 6:9c48361117de D
935 935 |
936 936 o 2:261e70097290 B2
937 937 |
938 938 o 0:4a2df7238c3b A
939 939
940 940 $ hg summary
941 941 parent: 14:73568ab6879d tip (orphan)
942 942 bar foo
943 943 branch: default
944 944 commit: (clean)
945 945 update: 2 new changesets, 3 branch heads (merge)
946 946 phases: 8 draft
947 947 orphan: 1 changesets
948 948 $ hg rebase -s 10 -d 12
949 949 abort: this rebase will cause divergences from: 121d9e3bc4c6
950 950 (to force the rebase please set experimental.evolution.allowdivergence=True)
951 [255]
951 [20]
952 952 $ hg log -G
953 953 @ 14:73568ab6879d bar foo
954 954 |
955 955 | o 13:77d874d096a2 10'
956 956 | |
957 957 | | o 12:3eb461388009 john doe
958 958 | |/
959 959 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
960 960 |/
961 961 o 9:4be60e099a77 C
962 962 |
963 963 o 6:9c48361117de D
964 964 |
965 965 o 2:261e70097290 B2
966 966 |
967 967 o 0:4a2df7238c3b A
968 968
969 969 With experimental.evolution.allowdivergence=True, rebase can create divergence
970 970
971 971 $ hg rebase -s 10 -d 12 --config experimental.evolution.allowdivergence=True
972 972 rebasing 10:121d9e3bc4c6 "P"
973 973 rebasing 14:73568ab6879d tip "bar foo"
974 974 2 new content-divergent changesets
975 975 $ hg summary
976 976 parent: 16:61bd55f69bc4 tip
977 977 bar foo
978 978 branch: default
979 979 commit: (clean)
980 980 update: 1 new changesets, 2 branch heads (merge)
981 981 phases: 8 draft
982 982 content-divergent: 2 changesets
983 983
984 984 rebase --continue + skipped rev because their successors are in destination
985 985 we make a change in trunk and work on conflicting changes to make rebase abort.
986 986
987 987 $ hg log -G -r 16::
988 988 @ 16:61bd55f69bc4 bar foo
989 989 |
990 990 ~
991 991
992 992 Create the two changes in trunk
993 993 $ printf "a" > willconflict
994 994 $ hg add willconflict
995 995 $ hg commit -m "willconflict first version"
996 996
997 997 $ printf "dummy" > C
998 998 $ hg commit -m "dummy change successor"
999 999
1000 1000 Create the changes that we will rebase
1001 1001 $ hg update -C 16 -q
1002 1002 $ printf "b" > willconflict
1003 1003 $ hg add willconflict
1004 1004 $ hg commit -m "willconflict second version"
1005 1005 created new head
1006 1006 $ printf "dummy" > K
1007 1007 $ hg add K
1008 1008 $ hg commit -m "dummy change"
1009 1009 $ printf "dummy" > L
1010 1010 $ hg add L
1011 1011 $ hg commit -m "dummy change"
1012 1012 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 18 -T '{node}'` --config experimental.evolution=true
1013 1013 1 new obsolescence markers
1014 1014 obsoleted 1 changesets
1015 1015 1 new orphan changesets
1016 1016
1017 1017 $ hg log -G -r 16::
1018 1018 @ 21:7bdc8a87673d dummy change
1019 1019 |
1020 1020 x 20:8b31da3c4919 dummy change (rewritten as 18:601db7a18f51)
1021 1021 |
1022 1022 o 19:b82fb57ea638 willconflict second version
1023 1023 |
1024 1024 | o 18:601db7a18f51 dummy change successor
1025 1025 | |
1026 1026 | o 17:357ddf1602d5 willconflict first version
1027 1027 |/
1028 1028 o 16:61bd55f69bc4 bar foo
1029 1029 |
1030 1030 ~
1031 1031 $ hg rebase -r ".^^ + .^ + ." -d 18
1032 1032 rebasing 19:b82fb57ea638 "willconflict second version"
1033 1033 merging willconflict
1034 1034 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
1035 1035 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1036 1036 [240]
1037 1037
1038 1038 $ hg resolve --mark willconflict
1039 1039 (no more unresolved files)
1040 1040 continue: hg rebase --continue
1041 1041 $ hg rebase --continue
1042 1042 rebasing 19:b82fb57ea638 "willconflict second version"
1043 1043 note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor"
1044 1044 rebasing 21:7bdc8a87673d tip "dummy change"
1045 1045 $ cd ..
1046 1046
1047 1047 Divergence cases due to obsolete changesets
1048 1048 -------------------------------------------
1049 1049
1050 1050 We should ignore branches with unstable changesets when they are based on an
1051 1051 obsolete changeset which successor is in rebase set.
1052 1052
1053 1053 $ hg init divergence
1054 1054 $ cd divergence
1055 1055 $ cat >> .hg/hgrc << EOF
1056 1056 > [extensions]
1057 1057 > strip =
1058 1058 > [alias]
1059 1059 > strip = strip --no-backup --quiet
1060 1060 > [templates]
1061 1061 > instabilities = '{rev}:{node|short} {desc|firstline}{if(instabilities," ({instabilities})")}\n'
1062 1062 > EOF
1063 1063
1064 1064 $ hg debugdrawdag <<EOF
1065 1065 > e f
1066 1066 > | |
1067 1067 > d' d # replace: d -> d'
1068 1068 > \ /
1069 1069 > c
1070 1070 > |
1071 1071 > x b
1072 1072 > \|
1073 1073 > a
1074 1074 > EOF
1075 1075 1 new orphan changesets
1076 1076 $ hg log -G -r 'a'::
1077 1077 * 7:1143e9adc121 f
1078 1078 |
1079 1079 | o 6:d60ebfa0f1cb e
1080 1080 | |
1081 1081 | o 5:027ad6c5830d d'
1082 1082 | |
1083 1083 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1084 1084 |/
1085 1085 o 3:a82ac2b38757 c
1086 1086 |
1087 1087 | o 2:630d7c95eff7 x
1088 1088 | |
1089 1089 o | 1:488e1b7e7341 b
1090 1090 |/
1091 1091 o 0:b173517d0057 a
1092 1092
1093 1093
1094 1094 Changeset d and its descendants are excluded to avoid divergence of d, which
1095 1095 would occur because the successor of d (d') is also in rebaseset. As a
1096 1096 consequence f (descendant of d) is left behind.
1097 1097
1098 1098 $ hg rebase -b 'e' -d 'x'
1099 1099 rebasing 1:488e1b7e7341 b "b"
1100 1100 rebasing 3:a82ac2b38757 c "c"
1101 1101 rebasing 5:027ad6c5830d d' "d'"
1102 1102 rebasing 6:d60ebfa0f1cb e "e"
1103 1103 note: not rebasing 4:76be324c128b d "d" and its descendants as this would cause divergence
1104 1104 $ hg log -G -r 'a'::
1105 1105 o 11:eb6d63fc4ed5 e
1106 1106 |
1107 1107 o 10:44d8c724a70c d'
1108 1108 |
1109 1109 o 9:d008e6b4d3fd c
1110 1110 |
1111 1111 o 8:67e8f4a16c49 b
1112 1112 |
1113 1113 | * 7:1143e9adc121 f
1114 1114 | |
1115 1115 | | x 6:d60ebfa0f1cb e (rewritten using rebase as 11:eb6d63fc4ed5)
1116 1116 | | |
1117 1117 | | x 5:027ad6c5830d d' (rewritten using rebase as 10:44d8c724a70c)
1118 1118 | | |
1119 1119 | x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1120 1120 | |/
1121 1121 | x 3:a82ac2b38757 c (rewritten using rebase as 9:d008e6b4d3fd)
1122 1122 | |
1123 1123 o | 2:630d7c95eff7 x
1124 1124 | |
1125 1125 | x 1:488e1b7e7341 b (rewritten using rebase as 8:67e8f4a16c49)
1126 1126 |/
1127 1127 o 0:b173517d0057 a
1128 1128
1129 1129 $ hg strip -r 8:
1130 1130 $ hg log -G -r 'a'::
1131 1131 * 7:1143e9adc121 f
1132 1132 |
1133 1133 | o 6:d60ebfa0f1cb e
1134 1134 | |
1135 1135 | o 5:027ad6c5830d d'
1136 1136 | |
1137 1137 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1138 1138 |/
1139 1139 o 3:a82ac2b38757 c
1140 1140 |
1141 1141 | o 2:630d7c95eff7 x
1142 1142 | |
1143 1143 o | 1:488e1b7e7341 b
1144 1144 |/
1145 1145 o 0:b173517d0057 a
1146 1146
1147 1147
1148 1148 If the rebase set has an obsolete (d) with a successor (d') outside the rebase
1149 1149 set and none in destination, we still get the divergence warning.
1150 1150 By allowing divergence, we can perform the rebase.
1151 1151
1152 1152 $ hg rebase -r 'c'::'f' -d 'x'
1153 1153 abort: this rebase will cause divergences from: 76be324c128b
1154 1154 (to force the rebase please set experimental.evolution.allowdivergence=True)
1155 [255]
1155 [20]
1156 1156 $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x'
1157 1157 rebasing 3:a82ac2b38757 c "c"
1158 1158 rebasing 4:76be324c128b d "d"
1159 1159 rebasing 7:1143e9adc121 f tip "f"
1160 1160 1 new orphan changesets
1161 1161 2 new content-divergent changesets
1162 1162 $ hg log -G -r 'a':: -T instabilities
1163 1163 o 10:e1744ea07510 f
1164 1164 |
1165 1165 * 9:e2b36ea9a0a0 d (content-divergent)
1166 1166 |
1167 1167 o 8:6a0376de376e c
1168 1168 |
1169 1169 | x 7:1143e9adc121 f
1170 1170 | |
1171 1171 | | * 6:d60ebfa0f1cb e (orphan)
1172 1172 | | |
1173 1173 | | * 5:027ad6c5830d d' (orphan content-divergent)
1174 1174 | | |
1175 1175 | x | 4:76be324c128b d
1176 1176 | |/
1177 1177 | x 3:a82ac2b38757 c
1178 1178 | |
1179 1179 o | 2:630d7c95eff7 x
1180 1180 | |
1181 1181 | o 1:488e1b7e7341 b
1182 1182 |/
1183 1183 o 0:b173517d0057 a
1184 1184
1185 1185 $ hg strip -r 8:
1186 1186
1187 1187 (Not skipping obsoletes means that divergence is allowed.)
1188 1188
1189 1189 $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x'
1190 1190 rebasing 3:a82ac2b38757 c "c"
1191 1191 rebasing 4:76be324c128b d "d"
1192 1192 rebasing 7:1143e9adc121 f tip "f"
1193 1193 1 new orphan changesets
1194 1194 2 new content-divergent changesets
1195 1195
1196 1196 $ hg strip -r 0:
1197 1197
1198 1198 Similar test on a more complex graph
1199 1199
1200 1200 $ hg debugdrawdag <<EOF
1201 1201 > g
1202 1202 > |
1203 1203 > f e
1204 1204 > | |
1205 1205 > e' d # replace: e -> e'
1206 1206 > \ /
1207 1207 > c
1208 1208 > |
1209 1209 > x b
1210 1210 > \|
1211 1211 > a
1212 1212 > EOF
1213 1213 1 new orphan changesets
1214 1214 $ hg log -G -r 'a':
1215 1215 * 8:2876ce66c6eb g
1216 1216 |
1217 1217 | o 7:3ffec603ab53 f
1218 1218 | |
1219 1219 x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1220 1220 | |
1221 1221 | o 5:63324dc512ea e'
1222 1222 | |
1223 1223 o | 4:76be324c128b d
1224 1224 |/
1225 1225 o 3:a82ac2b38757 c
1226 1226 |
1227 1227 | o 2:630d7c95eff7 x
1228 1228 | |
1229 1229 o | 1:488e1b7e7341 b
1230 1230 |/
1231 1231 o 0:b173517d0057 a
1232 1232
1233 1233 $ hg rebase -b 'f' -d 'x'
1234 1234 rebasing 1:488e1b7e7341 b "b"
1235 1235 rebasing 3:a82ac2b38757 c "c"
1236 1236 rebasing 5:63324dc512ea e' "e'"
1237 1237 rebasing 7:3ffec603ab53 f "f"
1238 1238 rebasing 4:76be324c128b d "d"
1239 1239 note: not rebasing 6:e36fae928aec e "e" and its descendants as this would cause divergence
1240 1240 $ hg log -G -r 'a':
1241 1241 o 13:a1707a5b7c2c d
1242 1242 |
1243 1243 | o 12:ef6251596616 f
1244 1244 | |
1245 1245 | o 11:b6f172e64af9 e'
1246 1246 |/
1247 1247 o 10:d008e6b4d3fd c
1248 1248 |
1249 1249 o 9:67e8f4a16c49 b
1250 1250 |
1251 1251 | * 8:2876ce66c6eb g
1252 1252 | |
1253 1253 | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
1254 1254 | | |
1255 1255 | x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1256 1256 | | |
1257 1257 | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
1258 1258 | | |
1259 1259 | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
1260 1260 | |/
1261 1261 | x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
1262 1262 | |
1263 1263 o | 2:630d7c95eff7 x
1264 1264 | |
1265 1265 | x 1:488e1b7e7341 b (rewritten using rebase as 9:67e8f4a16c49)
1266 1266 |/
1267 1267 o 0:b173517d0057 a
1268 1268
1269 1269
1270 1270 issue5782
1271 1271 $ hg strip -r 0:
1272 1272 $ hg debugdrawdag <<EOF
1273 1273 > d
1274 1274 > |
1275 1275 > c1 c # replace: c -> c1
1276 1276 > \ /
1277 1277 > b
1278 1278 > |
1279 1279 > a
1280 1280 > EOF
1281 1281 1 new orphan changesets
1282 1282 $ hg debugobsolete `hg log -T "{node}" --hidden -r 'desc("c1")'`
1283 1283 1 new obsolescence markers
1284 1284 obsoleted 1 changesets
1285 1285 $ hg log -G -r 'a': --hidden
1286 1286 * 4:76be324c128b d
1287 1287 |
1288 1288 | x 3:ef8a456de8fa c1 (pruned)
1289 1289 | |
1290 1290 x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa)
1291 1291 |/
1292 1292 o 1:488e1b7e7341 b
1293 1293 |
1294 1294 o 0:b173517d0057 a
1295 1295
1296 1296 $ hg rebase -d 0 -r 2
1297 1297 rebasing 2:a82ac2b38757 c "c"
1298 1298 $ hg log -G -r 'a': --hidden
1299 1299 o 5:69ad416a4a26 c
1300 1300 |
1301 1301 | * 4:76be324c128b d
1302 1302 | |
1303 1303 | | x 3:ef8a456de8fa c1 (pruned)
1304 1304 | | |
1305 1305 | x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa rewritten using rebase as 5:69ad416a4a26)
1306 1306 | |/
1307 1307 | o 1:488e1b7e7341 b
1308 1308 |/
1309 1309 o 0:b173517d0057 a
1310 1310
1311 1311 $ cd ..
1312 1312
1313 1313 Rebase merge where successor of one parent is equal to destination (issue5198)
1314 1314
1315 1315 $ hg init p1-succ-is-dest
1316 1316 $ cd p1-succ-is-dest
1317 1317
1318 1318 $ hg debugdrawdag <<EOF
1319 1319 > F
1320 1320 > /|
1321 1321 > E D B # replace: D -> B
1322 1322 > \|/
1323 1323 > A
1324 1324 > EOF
1325 1325 1 new orphan changesets
1326 1326
1327 1327 $ hg rebase -d B -s D
1328 1328 note: not rebasing 2:b18e25de2cf5 D "D", already in destination as 1:112478962961 B "B"
1329 1329 rebasing 4:66f1a38021c9 F tip "F"
1330 1330 $ hg log -G
1331 1331 o 5:50e9d60b99c6 F
1332 1332 |\
1333 1333 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:50e9d60b99c6)
1334 1334 | |/|
1335 1335 | o | 3:7fb047a69f22 E
1336 1336 | | |
1337 1337 | | x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1338 1338 | |/
1339 1339 o | 1:112478962961 B
1340 1340 |/
1341 1341 o 0:426bada5c675 A
1342 1342
1343 1343 $ cd ..
1344 1344
1345 1345 Rebase merge where successor of other parent is equal to destination
1346 1346
1347 1347 $ hg init p2-succ-is-dest
1348 1348 $ cd p2-succ-is-dest
1349 1349
1350 1350 $ hg debugdrawdag <<EOF
1351 1351 > F
1352 1352 > /|
1353 1353 > E D B # replace: E -> B
1354 1354 > \|/
1355 1355 > A
1356 1356 > EOF
1357 1357 1 new orphan changesets
1358 1358
1359 1359 $ hg rebase -d B -s E
1360 1360 note: not rebasing 3:7fb047a69f22 E "E", already in destination as 1:112478962961 B "B"
1361 1361 rebasing 4:66f1a38021c9 F tip "F"
1362 1362 $ hg log -G
1363 1363 o 5:aae1787dacee F
1364 1364 |\
1365 1365 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:aae1787dacee)
1366 1366 | |/|
1367 1367 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1368 1368 | | |
1369 1369 | o | 2:b18e25de2cf5 D
1370 1370 | |/
1371 1371 o / 1:112478962961 B
1372 1372 |/
1373 1373 o 0:426bada5c675 A
1374 1374
1375 1375 $ cd ..
1376 1376
1377 1377 Rebase merge where successor of one parent is ancestor of destination
1378 1378
1379 1379 $ hg init p1-succ-in-dest
1380 1380 $ cd p1-succ-in-dest
1381 1381
1382 1382 $ hg debugdrawdag <<EOF
1383 1383 > F C
1384 1384 > /| |
1385 1385 > E D B # replace: D -> B
1386 1386 > \|/
1387 1387 > A
1388 1388 > EOF
1389 1389 1 new orphan changesets
1390 1390
1391 1391 $ hg rebase -d C -s D
1392 1392 note: not rebasing 2:b18e25de2cf5 D "D", already in destination as 1:112478962961 B "B"
1393 1393 rebasing 5:66f1a38021c9 F tip "F"
1394 1394
1395 1395 $ hg log -G
1396 1396 o 6:0913febf6439 F
1397 1397 |\
1398 1398 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:0913febf6439)
1399 1399 | | |
1400 1400 | o | 4:26805aba1e60 C
1401 1401 | | |
1402 1402 o | | 3:7fb047a69f22 E
1403 1403 | | |
1404 1404 +---x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1405 1405 | |
1406 1406 | o 1:112478962961 B
1407 1407 |/
1408 1408 o 0:426bada5c675 A
1409 1409
1410 1410 $ cd ..
1411 1411
1412 1412 Rebase merge where successor of other parent is ancestor of destination
1413 1413
1414 1414 $ hg init p2-succ-in-dest
1415 1415 $ cd p2-succ-in-dest
1416 1416
1417 1417 $ hg debugdrawdag <<EOF
1418 1418 > F C
1419 1419 > /| |
1420 1420 > E D B # replace: E -> B
1421 1421 > \|/
1422 1422 > A
1423 1423 > EOF
1424 1424 1 new orphan changesets
1425 1425
1426 1426 $ hg rebase -d C -s E
1427 1427 note: not rebasing 3:7fb047a69f22 E "E", already in destination as 1:112478962961 B "B"
1428 1428 rebasing 5:66f1a38021c9 F tip "F"
1429 1429 $ hg log -G
1430 1430 o 6:c6ab0cc6d220 F
1431 1431 |\
1432 1432 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:c6ab0cc6d220)
1433 1433 | | |
1434 1434 | o | 4:26805aba1e60 C
1435 1435 | | |
1436 1436 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1437 1437 | | |
1438 1438 o---+ 2:b18e25de2cf5 D
1439 1439 / /
1440 1440 o / 1:112478962961 B
1441 1441 |/
1442 1442 o 0:426bada5c675 A
1443 1443
1444 1444 $ cd ..
1445 1445
1446 1446 Rebase merge where successor of one parent is ancestor of destination
1447 1447
1448 1448 $ hg init p1-succ-in-dest-b
1449 1449 $ cd p1-succ-in-dest-b
1450 1450
1451 1451 $ hg debugdrawdag <<EOF
1452 1452 > F C
1453 1453 > /| |
1454 1454 > E D B # replace: E -> B
1455 1455 > \|/
1456 1456 > A
1457 1457 > EOF
1458 1458 1 new orphan changesets
1459 1459
1460 1460 $ hg rebase -d C -b F
1461 1461 rebasing 2:b18e25de2cf5 D "D"
1462 1462 note: not rebasing 3:7fb047a69f22 E "E", already in destination as 1:112478962961 B "B"
1463 1463 rebasing 5:66f1a38021c9 F tip "F"
1464 1464 note: not rebasing 5:66f1a38021c9 F tip "F", its destination already has all its changes
1465 1465 $ hg log -G
1466 1466 o 6:8f47515dda15 D
1467 1467 |
1468 1468 | x 5:66f1a38021c9 F (pruned using rebase)
1469 1469 | |\
1470 1470 o | | 4:26805aba1e60 C
1471 1471 | | |
1472 1472 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1473 1473 | | |
1474 1474 | x | 2:b18e25de2cf5 D (rewritten using rebase as 6:8f47515dda15)
1475 1475 | |/
1476 1476 o / 1:112478962961 B
1477 1477 |/
1478 1478 o 0:426bada5c675 A
1479 1479
1480 1480 $ cd ..
1481 1481
1482 1482 Rebase merge where successor of other parent is ancestor of destination
1483 1483
1484 1484 $ hg init p2-succ-in-dest-b
1485 1485 $ cd p2-succ-in-dest-b
1486 1486
1487 1487 $ hg debugdrawdag <<EOF
1488 1488 > F C
1489 1489 > /| |
1490 1490 > E D B # replace: D -> B
1491 1491 > \|/
1492 1492 > A
1493 1493 > EOF
1494 1494 1 new orphan changesets
1495 1495
1496 1496 $ hg rebase -d C -b F
1497 1497 note: not rebasing 2:b18e25de2cf5 D "D", already in destination as 1:112478962961 B "B"
1498 1498 rebasing 3:7fb047a69f22 E "E"
1499 1499 rebasing 5:66f1a38021c9 F tip "F"
1500 1500 note: not rebasing 5:66f1a38021c9 F tip "F", its destination already has all its changes
1501 1501
1502 1502 $ hg log -G
1503 1503 o 6:533690786a86 E
1504 1504 |
1505 1505 | x 5:66f1a38021c9 F (pruned using rebase)
1506 1506 | |\
1507 1507 o | | 4:26805aba1e60 C
1508 1508 | | |
1509 1509 | | x 3:7fb047a69f22 E (rewritten using rebase as 6:533690786a86)
1510 1510 | | |
1511 1511 | x | 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1512 1512 | |/
1513 1513 o / 1:112478962961 B
1514 1514 |/
1515 1515 o 0:426bada5c675 A
1516 1516
1517 1517 $ cd ..
1518 1518
1519 1519 Rebase merge where extinct node has successor that is not an ancestor of
1520 1520 destination
1521 1521
1522 1522 $ hg init extinct-with-succ-not-in-dest
1523 1523 $ cd extinct-with-succ-not-in-dest
1524 1524
1525 1525 $ hg debugdrawdag <<EOF
1526 1526 > E C # replace: C -> E
1527 1527 > | |
1528 1528 > D B
1529 1529 > |/
1530 1530 > A
1531 1531 > EOF
1532 1532
1533 1533 $ hg rebase -d D -s B
1534 1534 rebasing 1:112478962961 B "B"
1535 1535 note: not rebasing 3:26805aba1e60 C "C" and its descendants as this would cause divergence
1536 1536
1537 1537 $ cd ..
1538 1538
1539 1539 $ hg init p2-succ-in-dest-c
1540 1540 $ cd p2-succ-in-dest-c
1541 1541
1542 1542 The scenario here was that B::D were developed on default. B was queued on
1543 1543 stable, but amended before being push to hg-committed. C was queued on default,
1544 1544 along with unrelated J.
1545 1545
1546 1546 $ hg debugdrawdag <<EOF
1547 1547 > J
1548 1548 > |
1549 1549 > F
1550 1550 > |
1551 1551 > E
1552 1552 > | D
1553 1553 > | |
1554 1554 > | C # replace: C -> F
1555 1555 > | | H I # replace: B -> H -> I
1556 1556 > | B |/
1557 1557 > |/ G
1558 1558 > A
1559 1559 > EOF
1560 1560 1 new orphan changesets
1561 1561
1562 1562 This strip seems to be the key to avoid an early divergence warning.
1563 1563 $ hg --config extensions.strip= --hidden strip -qr H
1564 1564 1 new orphan changesets
1565 1565
1566 1566 $ hg rebase -b 'desc("D")' -d 'desc("J")'
1567 1567 abort: this rebase will cause divergences from: 112478962961
1568 1568 (to force the rebase please set experimental.evolution.allowdivergence=True)
1569 [255]
1569 [20]
1570 1570
1571 1571 Rebase merge where both parents have successors in destination
1572 1572
1573 1573 $ hg init p12-succ-in-dest
1574 1574 $ cd p12-succ-in-dest
1575 1575 $ hg debugdrawdag <<'EOS'
1576 1576 > E F
1577 1577 > /| /| # replace: A -> C
1578 1578 > A B C D # replace: B -> D
1579 1579 > | |
1580 1580 > X Y
1581 1581 > EOS
1582 1582 1 new orphan changesets
1583 1583 $ hg rebase -r A+B+E -d F
1584 1584 note: not rebasing 4:a3d17304151f A "A", already in destination as 0:96cc3511f894 C "C"
1585 1585 note: not rebasing 5:b23a2cc00842 B "B", already in destination as 1:058c1e1fb10a D "D"
1586 1586 rebasing 7:dac5d11c5a7d E tip "E"
1587 1587 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1588 [255]
1588 [10]
1589 1589 $ cd ..
1590 1590
1591 1591 Rebase a non-clean merge. One parent has successor in destination, the other
1592 1592 parent moves as requested.
1593 1593
1594 1594 $ hg init p1-succ-p2-move
1595 1595 $ cd p1-succ-p2-move
1596 1596 $ hg debugdrawdag <<'EOS'
1597 1597 > D Z
1598 1598 > /| | # replace: A -> C
1599 1599 > A B C # D/D = D
1600 1600 > EOS
1601 1601 1 new orphan changesets
1602 1602 $ hg rebase -r A+B+D -d Z
1603 1603 note: not rebasing 0:426bada5c675 A "A", already in destination as 2:96cc3511f894 C "C"
1604 1604 rebasing 1:fc2b737bb2e5 B "B"
1605 1605 rebasing 3:b8ed089c80ad D "D"
1606 1606
1607 1607 $ rm .hg/localtags
1608 1608 $ hg log -G
1609 1609 o 6:e4f78693cc88 D
1610 1610 |
1611 1611 o 5:76840d832e98 B
1612 1612 |
1613 1613 o 4:50e41c1f3950 Z
1614 1614 |
1615 1615 o 2:96cc3511f894 C
1616 1616
1617 1617 $ hg files -r tip
1618 1618 B
1619 1619 C
1620 1620 D
1621 1621 Z
1622 1622
1623 1623 $ cd ..
1624 1624
1625 1625 $ hg init p1-move-p2-succ
1626 1626 $ cd p1-move-p2-succ
1627 1627 $ hg debugdrawdag <<'EOS'
1628 1628 > D Z
1629 1629 > /| | # replace: B -> C
1630 1630 > A B C # D/D = D
1631 1631 > EOS
1632 1632 1 new orphan changesets
1633 1633 $ hg rebase -r B+A+D -d Z
1634 1634 rebasing 0:426bada5c675 A "A"
1635 1635 note: not rebasing 1:fc2b737bb2e5 B "B", already in destination as 2:96cc3511f894 C "C"
1636 1636 rebasing 3:b8ed089c80ad D "D"
1637 1637
1638 1638 $ rm .hg/localtags
1639 1639 $ hg log -G
1640 1640 o 6:1b355ed94d82 D
1641 1641 |
1642 1642 o 5:a81a74d764a6 A
1643 1643 |
1644 1644 o 4:50e41c1f3950 Z
1645 1645 |
1646 1646 o 2:96cc3511f894 C
1647 1647
1648 1648 $ hg files -r tip
1649 1649 A
1650 1650 C
1651 1651 D
1652 1652 Z
1653 1653
1654 1654 $ cd ..
1655 1655
1656 1656 Test that bookmark is moved and working dir is updated when all changesets have
1657 1657 equivalents in destination
1658 1658 $ hg init rbsrepo && cd rbsrepo
1659 1659 $ echo "[experimental]" > .hg/hgrc
1660 1660 $ echo "evolution=true" >> .hg/hgrc
1661 1661 $ echo "rebaseskipobsolete=on" >> .hg/hgrc
1662 1662 $ echo root > root && hg ci -Am root
1663 1663 adding root
1664 1664 $ echo a > a && hg ci -Am a
1665 1665 adding a
1666 1666 $ hg up 0
1667 1667 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1668 1668 $ echo b > b && hg ci -Am b
1669 1669 adding b
1670 1670 created new head
1671 1671 $ hg rebase -r 2 -d 1
1672 1672 rebasing 2:1e9a3c00cbe9 tip "b"
1673 1673 $ hg log -r . # working dir is at rev 3 (successor of 2)
1674 1674 3:be1832deae9a b (no-eol)
1675 1675 $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now
1676 1676 bookmarking hidden changeset 1e9a3c00cbe9
1677 1677 (hidden revision '1e9a3c00cbe9' was rewritten as: be1832deae9a)
1678 1678 $ hg up 2 && hg log -r . # working dir is at rev 2 again
1679 1679 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1680 1680 2:1e9a3c00cbe9 b (rewritten using rebase as 3:be1832deae9a) (no-eol)
1681 1681 $ hg rebase -r 2 -d 3 --config experimental.evolution.track-operation=1
1682 1682 note: not rebasing 2:1e9a3c00cbe9 mybook "b", already in destination as 3:be1832deae9a tip "b"
1683 1683 Check that working directory and bookmark was updated to rev 3 although rev 2
1684 1684 was skipped
1685 1685 $ hg log -r .
1686 1686 3:be1832deae9a b (no-eol)
1687 1687 $ hg bookmarks
1688 1688 mybook 3:be1832deae9a
1689 1689 $ hg debugobsolete --rev tip
1690 1690 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
1691 1691
1692 1692 Obsoleted working parent and bookmark could be moved if an ancestor of working
1693 1693 parent gets moved:
1694 1694
1695 1695 $ hg init $TESTTMP/ancestor-wd-move
1696 1696 $ cd $TESTTMP/ancestor-wd-move
1697 1697 $ hg debugdrawdag <<'EOS'
1698 1698 > E D1 # rebase: D1 -> D2
1699 1699 > | |
1700 1700 > | C
1701 1701 > D2 |
1702 1702 > | B
1703 1703 > |/
1704 1704 > A
1705 1705 > EOS
1706 1706 $ hg update D1 -q
1707 1707 $ hg bookmark book -i
1708 1708 $ hg rebase -r B+D1 -d E
1709 1709 rebasing 1:112478962961 B "B"
1710 1710 note: not rebasing 5:15ecf15e0114 book D1 tip "D1", already in destination as 2:0807738e0be9 D2 "D2"
1711 1711 1 new orphan changesets
1712 1712 $ hg log -G -T '{desc} {bookmarks}'
1713 1713 @ B book
1714 1714 |
1715 1715 | x D1
1716 1716 | |
1717 1717 o | E
1718 1718 | |
1719 1719 | * C
1720 1720 | |
1721 1721 o | D2
1722 1722 | |
1723 1723 | x B
1724 1724 |/
1725 1725 o A
1726 1726
1727 1727 Rebasing a merge with one of its parent having a hidden successor
1728 1728
1729 1729 $ hg init $TESTTMP/merge-p1-hidden-successor
1730 1730 $ cd $TESTTMP/merge-p1-hidden-successor
1731 1731
1732 1732 $ hg debugdrawdag <<'EOS'
1733 1733 > E
1734 1734 > |
1735 1735 > B3 B2 # amend: B1 -> B2 -> B3
1736 1736 > |/ # B2 is hidden
1737 1737 > | D
1738 1738 > | |\
1739 1739 > | B1 C
1740 1740 > |/
1741 1741 > A
1742 1742 > EOS
1743 1743 1 new orphan changesets
1744 1744
1745 1745 $ eval `hg tags -T '{tag}={node}\n'`
1746 1746 $ rm .hg/localtags
1747 1747
1748 1748 $ hg rebase -r $D -d $E
1749 1749 rebasing 5:9e62094e4d94 "D"
1750 1750
1751 1751 $ hg log -G
1752 1752 o 7:a699d059adcf D
1753 1753 |\
1754 1754 | o 6:ecc93090a95c E
1755 1755 | |
1756 1756 | o 4:0dc878468a23 B3
1757 1757 | |
1758 1758 o | 1:96cc3511f894 C
1759 1759 /
1760 1760 o 0:426bada5c675 A
1761 1761
1762 1762 For some reasons (--hidden, rebaseskipobsolete=0, directaccess, etc.),
1763 1763 rebasestate may contain hidden hashes. "rebase --abort" should work regardless.
1764 1764
1765 1765 $ hg init $TESTTMP/hidden-state1
1766 1766 $ cd $TESTTMP/hidden-state1
1767 1767 $ cat >> .hg/hgrc <<EOF
1768 1768 > [experimental]
1769 1769 > rebaseskipobsolete=0
1770 1770 > EOF
1771 1771
1772 1772 $ hg debugdrawdag <<'EOS'
1773 1773 > C
1774 1774 > |
1775 1775 > D B # prune: B, C
1776 1776 > |/ # B/D=B
1777 1777 > A
1778 1778 > EOS
1779 1779
1780 1780 $ eval `hg tags -T '{tag}={node}\n'`
1781 1781 $ rm .hg/localtags
1782 1782
1783 1783 $ hg update -q $C --hidden
1784 1784 updated to hidden changeset 7829726be4dc
1785 1785 (hidden revision '7829726be4dc' is pruned)
1786 1786 $ hg rebase -s $B -d $D
1787 1787 rebasing 1:2ec65233581b "B"
1788 1788 merging D
1789 1789 warning: conflicts while merging D! (edit, then use 'hg resolve --mark')
1790 1790 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1791 1791 [240]
1792 1792
1793 1793 $ cp -R . $TESTTMP/hidden-state2
1794 1794
1795 1795 $ hg log -G
1796 1796 @ 2:b18e25de2cf5 D
1797 1797 |
1798 1798 | % 1:2ec65233581b B (pruned using prune)
1799 1799 |/
1800 1800 o 0:426bada5c675 A
1801 1801
1802 1802 $ hg summary
1803 1803 parent: 2:b18e25de2cf5 tip
1804 1804 D
1805 1805 branch: default
1806 1806 commit: 1 modified, 1 added, 1 unknown, 1 unresolved
1807 1807 update: 1 new changesets, 2 branch heads (merge)
1808 1808 phases: 3 draft
1809 1809 rebase: 0 rebased, 2 remaining (rebase --continue)
1810 1810
1811 1811 $ hg rebase --abort
1812 1812 rebase aborted
1813 1813
1814 1814 Also test --continue for the above case
1815 1815
1816 1816 $ cd $TESTTMP/hidden-state2
1817 1817 $ hg resolve -m
1818 1818 (no more unresolved files)
1819 1819 continue: hg rebase --continue
1820 1820 $ hg rebase --continue
1821 1821 rebasing 1:2ec65233581b "B"
1822 1822 rebasing 3:7829726be4dc tip "C"
1823 1823 $ hg log -G
1824 1824 @ 5:1964d5d5b547 C
1825 1825 |
1826 1826 o 4:68deb90c12a2 B
1827 1827 |
1828 1828 o 2:b18e25de2cf5 D
1829 1829 |
1830 1830 o 0:426bada5c675 A
1831 1831
1832 1832 ====================
1833 1833 Test --stop option |
1834 1834 ====================
1835 1835 $ cd ..
1836 1836 $ hg init rbstop
1837 1837 $ cd rbstop
1838 1838 $ echo a>a
1839 1839 $ hg ci -Aqma
1840 1840 $ echo b>b
1841 1841 $ hg ci -Aqmb
1842 1842 $ echo c>c
1843 1843 $ hg ci -Aqmc
1844 1844 $ echo d>d
1845 1845 $ hg ci -Aqmd
1846 1846 $ hg up 0 -q
1847 1847 $ echo f>f
1848 1848 $ hg ci -Aqmf
1849 1849 $ echo D>d
1850 1850 $ hg ci -Aqm "conflict with d"
1851 1851 $ hg up 3 -q
1852 1852 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1853 1853 o 5:00bfc9898aeb test
1854 1854 | conflict with d
1855 1855 |
1856 1856 o 4:dafd40200f93 test
1857 1857 | f
1858 1858 |
1859 1859 | @ 3:055a42cdd887 test
1860 1860 | | d
1861 1861 | |
1862 1862 | o 2:177f92b77385 test
1863 1863 | | c
1864 1864 | |
1865 1865 | o 1:d2ae7f538514 test
1866 1866 |/ b
1867 1867 |
1868 1868 o 0:cb9a9f314b8b test
1869 1869 a
1870 1870
1871 1871 $ hg rebase -s 1 -d 5
1872 1872 rebasing 1:d2ae7f538514 "b"
1873 1873 rebasing 2:177f92b77385 "c"
1874 1874 rebasing 3:055a42cdd887 "d"
1875 1875 merging d
1876 1876 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1877 1877 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1878 1878 [240]
1879 1879 $ hg rebase --stop
1880 1880 1 new orphan changesets
1881 1881 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1882 1882 o 7:7fffad344617 test
1883 1883 | c
1884 1884 |
1885 1885 o 6:b15528633407 test
1886 1886 | b
1887 1887 |
1888 1888 o 5:00bfc9898aeb test
1889 1889 | conflict with d
1890 1890 |
1891 1891 o 4:dafd40200f93 test
1892 1892 | f
1893 1893 |
1894 1894 | @ 3:055a42cdd887 test
1895 1895 | | d
1896 1896 | |
1897 1897 | x 2:177f92b77385 test
1898 1898 | | c
1899 1899 | |
1900 1900 | x 1:d2ae7f538514 test
1901 1901 |/ b
1902 1902 |
1903 1903 o 0:cb9a9f314b8b test
1904 1904 a
1905 1905
1906 1906 Test it aborts if unstable csets is not allowed:
1907 1907 ===============================================
1908 1908 $ cat >> $HGRCPATH << EOF
1909 1909 > [experimental]
1910 1910 > evolution.allowunstable=False
1911 1911 > EOF
1912 1912
1913 1913 $ hg strip 6 --no-backup -q
1914 1914 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1915 1915 o 5:00bfc9898aeb test
1916 1916 | conflict with d
1917 1917 |
1918 1918 o 4:dafd40200f93 test
1919 1919 | f
1920 1920 |
1921 1921 | @ 3:055a42cdd887 test
1922 1922 | | d
1923 1923 | |
1924 1924 | o 2:177f92b77385 test
1925 1925 | | c
1926 1926 | |
1927 1927 | o 1:d2ae7f538514 test
1928 1928 |/ b
1929 1929 |
1930 1930 o 0:cb9a9f314b8b test
1931 1931 a
1932 1932
1933 1933 $ hg rebase -s 1 -d 5
1934 1934 rebasing 1:d2ae7f538514 "b"
1935 1935 rebasing 2:177f92b77385 "c"
1936 1936 rebasing 3:055a42cdd887 "d"
1937 1937 merging d
1938 1938 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1939 1939 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1940 1940 [240]
1941 1941 $ hg rebase --stop
1942 1942 abort: cannot remove original changesets with unrebased descendants
1943 1943 (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets)
1944 [255]
1944 [20]
1945 1945 $ hg rebase --abort
1946 1946 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1947 1947 rebase aborted
1948 1948
1949 1949 Test --stop when --keep is passed:
1950 1950 ==================================
1951 1951 $ hg rebase -s 1 -d 5 --keep
1952 1952 rebasing 1:d2ae7f538514 "b"
1953 1953 rebasing 2:177f92b77385 "c"
1954 1954 rebasing 3:055a42cdd887 "d"
1955 1955 merging d
1956 1956 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1957 1957 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
1958 1958 [240]
1959 1959 $ hg rebase --stop
1960 1960 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1961 1961 o 7:7fffad344617 test
1962 1962 | c
1963 1963 |
1964 1964 o 6:b15528633407 test
1965 1965 | b
1966 1966 |
1967 1967 o 5:00bfc9898aeb test
1968 1968 | conflict with d
1969 1969 |
1970 1970 o 4:dafd40200f93 test
1971 1971 | f
1972 1972 |
1973 1973 | @ 3:055a42cdd887 test
1974 1974 | | d
1975 1975 | |
1976 1976 | o 2:177f92b77385 test
1977 1977 | | c
1978 1978 | |
1979 1979 | o 1:d2ae7f538514 test
1980 1980 |/ b
1981 1981 |
1982 1982 o 0:cb9a9f314b8b test
1983 1983 a
1984 1984
1985 1985 Test --stop aborts when --collapse was passed:
1986 1986 =============================================
1987 1987 $ cat >> $HGRCPATH << EOF
1988 1988 > [experimental]
1989 1989 > evolution.allowunstable=True
1990 1990 > EOF
1991 1991
1992 1992 $ hg strip 6
1993 1993 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1994 1994 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1995 1995 o 5:00bfc9898aeb test
1996 1996 | conflict with d
1997 1997 |
1998 1998 o 4:dafd40200f93 test
1999 1999 | f
2000 2000 |
2001 2001 | @ 3:055a42cdd887 test
2002 2002 | | d
2003 2003 | |
2004 2004 | o 2:177f92b77385 test
2005 2005 | | c
2006 2006 | |
2007 2007 | o 1:d2ae7f538514 test
2008 2008 |/ b
2009 2009 |
2010 2010 o 0:cb9a9f314b8b test
2011 2011 a
2012 2012
2013 2013 $ hg rebase -s 1 -d 5 --collapse -m "collapsed b c d"
2014 2014 rebasing 1:d2ae7f538514 "b"
2015 2015 rebasing 2:177f92b77385 "c"
2016 2016 rebasing 3:055a42cdd887 "d"
2017 2017 merging d
2018 2018 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2019 2019 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2020 2020 [240]
2021 2021 $ hg rebase --stop
2022 2022 abort: cannot stop in --collapse session
2023 [255]
2023 [20]
2024 2024 $ hg rebase --abort
2025 2025 rebase aborted
2026 2026 $ hg diff
2027 2027 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
2028 2028 o 5:00bfc9898aeb test
2029 2029 | conflict with d
2030 2030 |
2031 2031 o 4:dafd40200f93 test
2032 2032 | f
2033 2033 |
2034 2034 | @ 3:055a42cdd887 test
2035 2035 | | d
2036 2036 | |
2037 2037 | o 2:177f92b77385 test
2038 2038 | | c
2039 2039 | |
2040 2040 | o 1:d2ae7f538514 test
2041 2041 |/ b
2042 2042 |
2043 2043 o 0:cb9a9f314b8b test
2044 2044 a
2045 2045
2046 2046 Test --stop raise errors with conflicting options:
2047 2047 =================================================
2048 2048 $ hg rebase -s 3 -d 5
2049 2049 rebasing 3:055a42cdd887 "d"
2050 2050 merging d
2051 2051 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2052 2052 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2053 2053 [240]
2054 2054 $ hg rebase --stop --dry-run
2055 2055 abort: cannot specify both --stop and --dry-run
2056 2056 [10]
2057 2057
2058 2058 $ hg rebase -s 3 -d 5
2059 2059 abort: rebase in progress
2060 2060 (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop')
2061 2061 [20]
2062 2062 $ hg rebase --stop --continue
2063 2063 abort: cannot specify both --stop and --continue
2064 2064 [10]
2065 2065
2066 2066 Test --stop moves bookmarks of original revisions to new rebased nodes:
2067 2067 ======================================================================
2068 2068 $ cd ..
2069 2069 $ hg init repo
2070 2070 $ cd repo
2071 2071
2072 2072 $ echo a > a
2073 2073 $ hg ci -Am A
2074 2074 adding a
2075 2075
2076 2076 $ echo b > b
2077 2077 $ hg ci -Am B
2078 2078 adding b
2079 2079 $ hg book X
2080 2080 $ hg book Y
2081 2081
2082 2082 $ echo c > c
2083 2083 $ hg ci -Am C
2084 2084 adding c
2085 2085 $ hg book Z
2086 2086
2087 2087 $ echo d > d
2088 2088 $ hg ci -Am D
2089 2089 adding d
2090 2090
2091 2091 $ hg up 0 -q
2092 2092 $ echo e > e
2093 2093 $ hg ci -Am E
2094 2094 adding e
2095 2095 created new head
2096 2096
2097 2097 $ echo doubt > d
2098 2098 $ hg ci -Am "conflict with d"
2099 2099 adding d
2100 2100
2101 2101 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2102 2102 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2103 2103 |
2104 2104 o 4: 9c1e55f411b6 'E' bookmarks:
2105 2105 |
2106 2106 | o 3: 67a385d4e6f2 'D' bookmarks: Z
2107 2107 | |
2108 2108 | o 2: 49cb3485fa0c 'C' bookmarks: Y
2109 2109 | |
2110 2110 | o 1: 6c81ed0049f8 'B' bookmarks: X
2111 2111 |/
2112 2112 o 0: 1994f17a630e 'A' bookmarks:
2113 2113
2114 2114 $ hg rebase -s 1 -d 5
2115 2115 rebasing 1:6c81ed0049f8 X "B"
2116 2116 rebasing 2:49cb3485fa0c Y "C"
2117 2117 rebasing 3:67a385d4e6f2 Z "D"
2118 2118 merging d
2119 2119 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2120 2120 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
2121 2121 [240]
2122 2122 $ hg rebase --stop
2123 2123 1 new orphan changesets
2124 2124 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2125 2125 o 7: 9c86c650b686 'C' bookmarks: Y
2126 2126 |
2127 2127 o 6: 9b87b54e5fd8 'B' bookmarks: X
2128 2128 |
2129 2129 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2130 2130 |
2131 2131 o 4: 9c1e55f411b6 'E' bookmarks:
2132 2132 |
2133 2133 | * 3: 67a385d4e6f2 'D' bookmarks: Z
2134 2134 | |
2135 2135 | x 2: 49cb3485fa0c 'C' bookmarks:
2136 2136 | |
2137 2137 | x 1: 6c81ed0049f8 'B' bookmarks:
2138 2138 |/
2139 2139 o 0: 1994f17a630e 'A' bookmarks:
2140 2140
@@ -1,531 +1,531 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 >
5 5 > [phases]
6 6 > publish=False
7 7 >
8 8 > [alias]
9 9 > tglog = log -G --template "{rev}: {node|short} '{desc}' {branches}\n"
10 10 > EOF
11 11
12 12
13 13 $ hg init a
14 14 $ cd a
15 15 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
16 16 adding changesets
17 17 adding manifests
18 18 adding file changes
19 19 added 8 changesets with 7 changes to 7 files (+2 heads)
20 20 new changesets cd010b8cd998:02de42196ebe (8 drafts)
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: e7ec4e813ba6 'I'
31 31 |
32 32 o 7: 02de42196ebe 'H'
33 33 |
34 34 | o 6: eea13746799a 'G'
35 35 |/|
36 36 o | 5: 24b6387c8c8c 'F'
37 37 | |
38 38 | o 4: 9520eea781bc 'E'
39 39 |/
40 40 | o 3: 32af7686d403 'D'
41 41 | |
42 42 | o 2: 5fddd98957c8 'C'
43 43 | |
44 44 | o 1: 42ccdea3bb16 'B'
45 45 |/
46 46 o 0: cd010b8cd998 'A'
47 47
48 48 $ cd ..
49 49
50 50 Version with only two heads (to allow default destination to work)
51 51
52 52 $ hg clone -q -u . a a2heads -r 3 -r 8
53 53
54 54 These fail:
55 55
56 56 $ hg clone -q -u . a a0
57 57 $ cd a0
58 58
59 59 $ hg rebase -s 8 -d 7
60 60 nothing to rebase
61 61 [1]
62 62
63 63 $ hg rebase --continue --abort
64 64 abort: cannot specify both --abort and --continue
65 65 [10]
66 66
67 67 $ hg rebase --continue --collapse
68 68 abort: cannot use collapse with continue or abort
69 [255]
69 [10]
70 70
71 71 $ hg rebase --continue --dest 4
72 72 abort: cannot specify both --continue and --dest
73 73 [10]
74 74
75 75 $ hg rebase --base 5 --source 4
76 76 abort: cannot specify both --source and --base
77 77 [10]
78 78
79 79 $ hg rebase --rev 5 --source 4
80 80 abort: cannot specify both --rev and --source
81 81 [10]
82 82 $ hg rebase --base 5 --rev 4
83 83 abort: cannot specify both --rev and --base
84 84 [10]
85 85
86 86 $ hg rebase --base 6
87 87 abort: branch 'default' has 3 heads - please rebase to an explicit rev
88 88 (run 'hg heads .' to see heads, specify destination with -d)
89 89 [255]
90 90
91 91 $ hg rebase --rev '1 & !1' --dest 8
92 92 empty "rev" revision set - nothing to rebase
93 93 [1]
94 94
95 95 $ hg rebase --rev 'wdir()' --dest 6
96 96 abort: cannot rebase the working copy
97 [255]
97 [10]
98 98
99 99 $ hg rebase --source 'wdir()' --dest 6
100 100 abort: cannot rebase the working copy
101 [255]
101 [10]
102 102
103 103 $ hg rebase --source 1 --source 'wdir()' --dest 6
104 104 abort: cannot rebase the working copy
105 [255]
105 [10]
106 106
107 107 $ hg rebase --source '1 & !1' --dest 8
108 108 empty "source" revision set - nothing to rebase
109 109 [1]
110 110
111 111 $ hg rebase --base '1 & !1' --dest 8
112 112 empty "base" revision set - can't compute rebase set
113 113 [1]
114 114
115 115 $ hg rebase --dest 8
116 116 nothing to rebase - working directory parent is also destination
117 117 [1]
118 118
119 119 $ hg rebase -b . --dest 8
120 120 nothing to rebase - e7ec4e813ba6 is both "base" and destination
121 121 [1]
122 122
123 123 $ hg up -q 7
124 124
125 125 $ hg rebase --dest 8 --traceback
126 126 nothing to rebase - working directory parent is already an ancestor of destination e7ec4e813ba6
127 127 [1]
128 128
129 129 $ hg rebase --dest 8 -b.
130 130 nothing to rebase - "base" 02de42196ebe is already an ancestor of destination e7ec4e813ba6
131 131 [1]
132 132
133 133 $ hg rebase --dest '1 & !1'
134 134 abort: empty revision set
135 135 [255]
136 136
137 137 These work:
138 138
139 139 Rebase with no arguments (from 3 onto 8):
140 140
141 141 $ cd ..
142 142 $ hg clone -q -u . a2heads a1
143 143 $ cd a1
144 144 $ hg up -q -C 3
145 145
146 146 $ hg rebase
147 147 rebasing 1:42ccdea3bb16 "B"
148 148 rebasing 2:5fddd98957c8 "C"
149 149 rebasing 3:32af7686d403 "D"
150 150 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
151 151
152 152 $ hg tglog
153 153 @ 6: ed65089c18f8 'D'
154 154 |
155 155 o 5: 7621bf1a2f17 'C'
156 156 |
157 157 o 4: 9430a62369c6 'B'
158 158 |
159 159 o 3: e7ec4e813ba6 'I'
160 160 |
161 161 o 2: 02de42196ebe 'H'
162 162 |
163 163 o 1: 24b6387c8c8c 'F'
164 164 |
165 165 o 0: cd010b8cd998 'A'
166 166
167 167 Try to rollback after a rebase (fail):
168 168
169 169 $ hg rollback
170 170 no rollback information available
171 171 [1]
172 172
173 173 $ cd ..
174 174
175 175 Rebase with base == '.' => same as no arguments (from 3 onto 8):
176 176
177 177 $ hg clone -q -u 3 a2heads a2
178 178 $ cd a2
179 179
180 180 $ hg rebase --base .
181 181 rebasing 1:42ccdea3bb16 "B"
182 182 rebasing 2:5fddd98957c8 "C"
183 183 rebasing 3:32af7686d403 "D"
184 184 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
185 185
186 186 $ hg tglog
187 187 @ 6: ed65089c18f8 'D'
188 188 |
189 189 o 5: 7621bf1a2f17 'C'
190 190 |
191 191 o 4: 9430a62369c6 'B'
192 192 |
193 193 o 3: e7ec4e813ba6 'I'
194 194 |
195 195 o 2: 02de42196ebe 'H'
196 196 |
197 197 o 1: 24b6387c8c8c 'F'
198 198 |
199 199 o 0: cd010b8cd998 'A'
200 200
201 201 $ cd ..
202 202
203 203
204 204 Rebase with dest == branch(.) => same as no arguments (from 3 onto 8):
205 205
206 206 $ hg clone -q -u 3 a a3
207 207 $ cd a3
208 208
209 209 $ hg rebase --dest 'branch(.)'
210 210 rebasing 1:42ccdea3bb16 "B"
211 211 rebasing 2:5fddd98957c8 "C"
212 212 rebasing 3:32af7686d403 "D"
213 213 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
214 214
215 215 $ hg tglog
216 216 @ 8: ed65089c18f8 'D'
217 217 |
218 218 o 7: 7621bf1a2f17 'C'
219 219 |
220 220 o 6: 9430a62369c6 'B'
221 221 |
222 222 o 5: e7ec4e813ba6 'I'
223 223 |
224 224 o 4: 02de42196ebe 'H'
225 225 |
226 226 | o 3: eea13746799a 'G'
227 227 |/|
228 228 o | 2: 24b6387c8c8c 'F'
229 229 | |
230 230 | o 1: 9520eea781bc 'E'
231 231 |/
232 232 o 0: cd010b8cd998 'A'
233 233
234 234 $ cd ..
235 235
236 236
237 237 Specify only source (from 2 onto 8):
238 238
239 239 $ hg clone -q -u . a2heads a4
240 240 $ cd a4
241 241
242 242 $ hg rebase --source 'desc("C")'
243 243 rebasing 2:5fddd98957c8 "C"
244 244 rebasing 3:32af7686d403 "D"
245 245 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
246 246
247 247 $ hg tglog
248 248 o 6: 7726e9fd58f7 'D'
249 249 |
250 250 o 5: 72c8333623d0 'C'
251 251 |
252 252 @ 4: e7ec4e813ba6 'I'
253 253 |
254 254 o 3: 02de42196ebe 'H'
255 255 |
256 256 o 2: 24b6387c8c8c 'F'
257 257 |
258 258 | o 1: 42ccdea3bb16 'B'
259 259 |/
260 260 o 0: cd010b8cd998 'A'
261 261
262 262 $ cd ..
263 263
264 264
265 265 Specify only dest (from 3 onto 6):
266 266
267 267 $ hg clone -q -u 3 a a5
268 268 $ cd a5
269 269
270 270 $ hg rebase --dest 6
271 271 rebasing 1:42ccdea3bb16 "B"
272 272 rebasing 2:5fddd98957c8 "C"
273 273 rebasing 3:32af7686d403 "D"
274 274 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
275 275
276 276 $ hg tglog
277 277 @ 8: 8eeb3c33ad33 'D'
278 278 |
279 279 o 7: 2327fea05063 'C'
280 280 |
281 281 o 6: e4e5be0395b2 'B'
282 282 |
283 283 | o 5: e7ec4e813ba6 'I'
284 284 | |
285 285 | o 4: 02de42196ebe 'H'
286 286 | |
287 287 o | 3: eea13746799a 'G'
288 288 |\|
289 289 | o 2: 24b6387c8c8c 'F'
290 290 | |
291 291 o | 1: 9520eea781bc 'E'
292 292 |/
293 293 o 0: cd010b8cd998 'A'
294 294
295 295 $ cd ..
296 296
297 297
298 298 Specify only base (from 1 onto 8):
299 299
300 300 $ hg clone -q -u . a2heads a6
301 301 $ cd a6
302 302
303 303 $ hg rebase --base 'desc("D")'
304 304 rebasing 1:42ccdea3bb16 "B"
305 305 rebasing 2:5fddd98957c8 "C"
306 306 rebasing 3:32af7686d403 "D"
307 307 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
308 308
309 309 $ hg tglog
310 310 o 6: ed65089c18f8 'D'
311 311 |
312 312 o 5: 7621bf1a2f17 'C'
313 313 |
314 314 o 4: 9430a62369c6 'B'
315 315 |
316 316 @ 3: e7ec4e813ba6 'I'
317 317 |
318 318 o 2: 02de42196ebe 'H'
319 319 |
320 320 o 1: 24b6387c8c8c 'F'
321 321 |
322 322 o 0: cd010b8cd998 'A'
323 323
324 324 $ cd ..
325 325
326 326
327 327 Specify source and dest (from 2 onto 7):
328 328
329 329 $ hg clone -q -u . a a7
330 330 $ cd a7
331 331
332 332 $ hg rebase --source 2 --dest 7
333 333 rebasing 2:5fddd98957c8 "C"
334 334 rebasing 3:32af7686d403 "D"
335 335 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
336 336
337 337 $ hg tglog
338 338 o 8: 668acadedd30 'D'
339 339 |
340 340 o 7: 09eb682ba906 'C'
341 341 |
342 342 | @ 6: e7ec4e813ba6 'I'
343 343 |/
344 344 o 5: 02de42196ebe 'H'
345 345 |
346 346 | o 4: eea13746799a 'G'
347 347 |/|
348 348 o | 3: 24b6387c8c8c 'F'
349 349 | |
350 350 | o 2: 9520eea781bc 'E'
351 351 |/
352 352 | o 1: 42ccdea3bb16 'B'
353 353 |/
354 354 o 0: cd010b8cd998 'A'
355 355
356 356 $ cd ..
357 357
358 358
359 359 Specify base and dest (from 1 onto 7):
360 360
361 361 $ hg clone -q -u . a a8
362 362 $ cd a8
363 363
364 364 $ hg rebase --base 3 --dest 7
365 365 rebasing 1:42ccdea3bb16 "B"
366 366 rebasing 2:5fddd98957c8 "C"
367 367 rebasing 3:32af7686d403 "D"
368 368 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
369 369
370 370 $ hg tglog
371 371 o 8: 287cc92ba5a4 'D'
372 372 |
373 373 o 7: 6824f610a250 'C'
374 374 |
375 375 o 6: 7c6027df6a99 'B'
376 376 |
377 377 | @ 5: e7ec4e813ba6 'I'
378 378 |/
379 379 o 4: 02de42196ebe 'H'
380 380 |
381 381 | o 3: eea13746799a 'G'
382 382 |/|
383 383 o | 2: 24b6387c8c8c 'F'
384 384 | |
385 385 | o 1: 9520eea781bc 'E'
386 386 |/
387 387 o 0: cd010b8cd998 'A'
388 388
389 389 $ cd ..
390 390
391 391
392 392 Specify only revs (from 2 onto 8)
393 393
394 394 $ hg clone -q -u . a2heads a9
395 395 $ cd a9
396 396
397 397 $ hg rebase --rev 'desc("C")::'
398 398 rebasing 2:5fddd98957c8 "C"
399 399 rebasing 3:32af7686d403 "D"
400 400 saved backup bundle to $TESTTMP/a9/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
401 401
402 402 $ hg tglog
403 403 o 6: 7726e9fd58f7 'D'
404 404 |
405 405 o 5: 72c8333623d0 'C'
406 406 |
407 407 @ 4: e7ec4e813ba6 'I'
408 408 |
409 409 o 3: 02de42196ebe 'H'
410 410 |
411 411 o 2: 24b6387c8c8c 'F'
412 412 |
413 413 | o 1: 42ccdea3bb16 'B'
414 414 |/
415 415 o 0: cd010b8cd998 'A'
416 416
417 417 $ cd ..
418 418
419 419 Rebasing both a single revision and a merge in one command
420 420
421 421 $ hg clone -q -u . a aX
422 422 $ cd aX
423 423 $ hg rebase -r 3 -r 6 --dest 8
424 424 rebasing 3:32af7686d403 "D"
425 425 rebasing 6:eea13746799a "G"
426 426 saved backup bundle to $TESTTMP/aX/.hg/strip-backup/eea13746799a-ad273fd6-rebase.hg
427 427 $ cd ..
428 428
429 429 Test --tool parameter:
430 430
431 431 $ hg init b
432 432 $ cd b
433 433
434 434 $ echo c1 > c1
435 435 $ hg ci -Am c1
436 436 adding c1
437 437
438 438 $ echo c2 > c2
439 439 $ hg ci -Am c2
440 440 adding c2
441 441
442 442 $ hg up -q 0
443 443 $ echo c2b > c2
444 444 $ hg ci -Am c2b
445 445 adding c2
446 446 created new head
447 447
448 448 $ cd ..
449 449
450 450 $ hg clone -q -u . b b1
451 451 $ cd b1
452 452
453 453 $ hg rebase -s 2 -d 1 --tool internal:local
454 454 rebasing 2:e4e3f3546619 tip "c2b"
455 455 note: not rebasing 2:e4e3f3546619 tip "c2b", its destination already has all its changes
456 456 saved backup bundle to $TESTTMP/b1/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg
457 457
458 458 $ hg cat c2
459 459 c2
460 460
461 461 $ cd ..
462 462
463 463
464 464 $ hg clone -q -u . b b2
465 465 $ cd b2
466 466
467 467 $ hg rebase -s 2 -d 1 --tool internal:other
468 468 rebasing 2:e4e3f3546619 tip "c2b"
469 469 saved backup bundle to $TESTTMP/b2/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg
470 470
471 471 $ hg cat c2
472 472 c2b
473 473
474 474 $ cd ..
475 475
476 476
477 477 $ hg clone -q -u . b b3
478 478 $ cd b3
479 479
480 480 $ hg rebase -s 2 -d 1 --tool internal:fail
481 481 rebasing 2:e4e3f3546619 tip "c2b"
482 482 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
483 483 [240]
484 484
485 485 $ hg summary
486 486 parent: 1:56daeba07f4b
487 487 c2
488 488 branch: default
489 489 commit: 1 unresolved (clean)
490 490 update: 1 new changesets, 2 branch heads (merge)
491 491 phases: 3 draft
492 492 rebase: 0 rebased, 1 remaining (rebase --continue)
493 493
494 494 $ hg resolve -l
495 495 U c2
496 496
497 497 $ hg resolve -m c2
498 498 (no more unresolved files)
499 499 continue: hg rebase --continue
500 500 $ hg graft --continue
501 501 abort: no graft in progress
502 502 (continue: hg rebase --continue)
503 503 [20]
504 504 $ hg rebase -c --tool internal:fail
505 505 rebasing 2:e4e3f3546619 tip "c2b"
506 506 note: not rebasing 2:e4e3f3546619 tip "c2b", its destination already has all its changes
507 507 saved backup bundle to $TESTTMP/b3/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg
508 508
509 509 $ hg rebase -i
510 510 abort: interactive history editing is supported by the 'histedit' extension (see "hg --config extensions.histedit= help -e histedit")
511 [255]
511 [10]
512 512
513 513 $ hg rebase --interactive
514 514 abort: interactive history editing is supported by the 'histedit' extension (see "hg --config extensions.histedit= help -e histedit")
515 [255]
515 [10]
516 516
517 517 $ cd ..
518 518
519 519 No common ancestor
520 520
521 521 $ hg init separaterepo
522 522 $ cd separaterepo
523 523 $ touch a
524 524 $ hg commit -Aqm a
525 525 $ hg up -q null
526 526 $ touch b
527 527 $ hg commit -Aqm b
528 528 $ hg rebase -d 0
529 529 nothing to rebase from d7486e00c6f1 to 3903775176ed
530 530 [1]
531 531 $ cd ..
@@ -1,985 +1,985 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 > drawdag=$TESTDIR/drawdag.py
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: {node|short} '{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 new changesets cd010b8cd998:02de42196ebe (8 drafts)
22 22 (run 'hg heads' to see heads, 'hg merge' to merge)
23 23 $ hg up tip
24 24 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
25 25 $ cd ..
26 26
27 27
28 28 Rebasing
29 29 D onto H - simple rebase:
30 30 (this also tests that editor is invoked if '--edit' is specified, and that we
31 31 can abort or warn for colliding untracked files)
32 32
33 33 $ hg clone -q -u . a a1
34 34 $ cd a1
35 35
36 36 $ hg tglog
37 37 @ 7: 02de42196ebe 'H'
38 38 |
39 39 | o 6: eea13746799a 'G'
40 40 |/|
41 41 o | 5: 24b6387c8c8c 'F'
42 42 | |
43 43 | o 4: 9520eea781bc 'E'
44 44 |/
45 45 | o 3: 32af7686d403 'D'
46 46 | |
47 47 | o 2: 5fddd98957c8 'C'
48 48 | |
49 49 | o 1: 42ccdea3bb16 'B'
50 50 |/
51 51 o 0: cd010b8cd998 'A'
52 52
53 53
54 54 $ hg status --rev "3^1" --rev 3
55 55 A D
56 56 $ echo collide > D
57 57 $ HGEDITOR=cat hg rebase -s 3 -d 7 --edit --config merge.checkunknown=warn
58 58 rebasing 3:32af7686d403 "D"
59 59 D: replacing untracked file
60 60 D
61 61
62 62
63 63 HG: Enter commit message. Lines beginning with 'HG:' are removed.
64 64 HG: Leave message empty to abort commit.
65 65 HG: --
66 66 HG: user: Nicolas Dumazet <nicdumz.commits@gmail.com>
67 67 HG: branch 'default'
68 68 HG: added D
69 69 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/32af7686d403-6f7dface-rebase.hg
70 70 $ cat D.orig
71 71 collide
72 72 $ rm D.orig
73 73
74 74 $ hg tglog
75 75 o 7: 1619f02ff7dd 'D'
76 76 |
77 77 @ 6: 02de42196ebe 'H'
78 78 |
79 79 | o 5: eea13746799a 'G'
80 80 |/|
81 81 o | 4: 24b6387c8c8c 'F'
82 82 | |
83 83 | o 3: 9520eea781bc 'E'
84 84 |/
85 85 | o 2: 5fddd98957c8 'C'
86 86 | |
87 87 | o 1: 42ccdea3bb16 'B'
88 88 |/
89 89 o 0: cd010b8cd998 'A'
90 90
91 91 $ cd ..
92 92
93 93
94 94 D onto F - intermediate point:
95 95 (this also tests that editor is not invoked if '--edit' is not specified, and
96 96 that we can ignore for colliding untracked files)
97 97
98 98 $ hg clone -q -u . a a2
99 99 $ cd a2
100 100 $ echo collide > D
101 101
102 102 $ HGEDITOR=cat hg rebase -s 3 -d 5 --config merge.checkunknown=ignore
103 103 rebasing 3:32af7686d403 "D"
104 104 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/32af7686d403-6f7dface-rebase.hg
105 105 $ cat D.orig
106 106 collide
107 107 $ rm D.orig
108 108
109 109 $ hg tglog
110 110 o 7: 2107530e74ab 'D'
111 111 |
112 112 | @ 6: 02de42196ebe 'H'
113 113 |/
114 114 | o 5: eea13746799a 'G'
115 115 |/|
116 116 o | 4: 24b6387c8c8c 'F'
117 117 | |
118 118 | o 3: 9520eea781bc 'E'
119 119 |/
120 120 | o 2: 5fddd98957c8 'C'
121 121 | |
122 122 | o 1: 42ccdea3bb16 'B'
123 123 |/
124 124 o 0: cd010b8cd998 'A'
125 125
126 126 $ cd ..
127 127
128 128
129 129 E onto H - skip of G:
130 130 (this also tests that we can overwrite untracked files and don't create backups
131 131 if they have the same contents)
132 132
133 133 $ hg clone -q -u . a a3
134 134 $ cd a3
135 135 $ hg cat -r 4 E | tee E
136 136 E
137 137
138 138 $ hg rebase -s 4 -d 7
139 139 rebasing 4:9520eea781bc "E"
140 140 rebasing 6:eea13746799a "G"
141 141 note: not rebasing 6:eea13746799a "G", its destination already has all its changes
142 142 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/9520eea781bc-fcd8edd4-rebase.hg
143 143 $ f E.orig
144 144 E.orig: file not found
145 145
146 146 $ hg tglog
147 147 o 6: 9f8b8ec77260 'E'
148 148 |
149 149 @ 5: 02de42196ebe 'H'
150 150 |
151 151 o 4: 24b6387c8c8c 'F'
152 152 |
153 153 | o 3: 32af7686d403 'D'
154 154 | |
155 155 | o 2: 5fddd98957c8 'C'
156 156 | |
157 157 | o 1: 42ccdea3bb16 'B'
158 158 |/
159 159 o 0: cd010b8cd998 'A'
160 160
161 161 $ cd ..
162 162
163 163
164 164 F onto E - rebase of a branching point (skip G):
165 165
166 166 $ hg clone -q -u . a a4
167 167 $ cd a4
168 168
169 169 $ hg rebase -s 5 -d 4
170 170 rebasing 5:24b6387c8c8c "F"
171 171 rebasing 6:eea13746799a "G"
172 172 note: not rebasing 6:eea13746799a "G", its destination already has all its changes
173 173 rebasing 7:02de42196ebe tip "H"
174 174 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/24b6387c8c8c-c3fe765d-rebase.hg
175 175
176 176 $ hg tglog
177 177 @ 6: e9240aeaa6ad 'H'
178 178 |
179 179 o 5: 5d0ccadb6e3e 'F'
180 180 |
181 181 o 4: 9520eea781bc 'E'
182 182 |
183 183 | o 3: 32af7686d403 'D'
184 184 | |
185 185 | o 2: 5fddd98957c8 'C'
186 186 | |
187 187 | o 1: 42ccdea3bb16 'B'
188 188 |/
189 189 o 0: cd010b8cd998 'A'
190 190
191 191 $ cd ..
192 192
193 193
194 194 G onto H - merged revision having a parent in ancestors of target:
195 195
196 196 $ hg clone -q -u . a a5
197 197 $ cd a5
198 198
199 199 $ hg rebase -s 6 -d 7
200 200 rebasing 6:eea13746799a "G"
201 201 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/eea13746799a-883828ed-rebase.hg
202 202
203 203 $ hg tglog
204 204 o 7: 397834907a90 'G'
205 205 |\
206 206 | @ 6: 02de42196ebe 'H'
207 207 | |
208 208 | o 5: 24b6387c8c8c 'F'
209 209 | |
210 210 o | 4: 9520eea781bc 'E'
211 211 |/
212 212 | o 3: 32af7686d403 'D'
213 213 | |
214 214 | o 2: 5fddd98957c8 'C'
215 215 | |
216 216 | o 1: 42ccdea3bb16 'B'
217 217 |/
218 218 o 0: cd010b8cd998 'A'
219 219
220 220 $ cd ..
221 221
222 222
223 223 F onto B - G maintains E as parent:
224 224
225 225 $ hg clone -q -u . a a6
226 226 $ cd a6
227 227
228 228 $ hg rebase -s 5 -d 1
229 229 rebasing 5:24b6387c8c8c "F"
230 230 rebasing 6:eea13746799a "G"
231 231 rebasing 7:02de42196ebe tip "H"
232 232 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/24b6387c8c8c-c3fe765d-rebase.hg
233 233
234 234 $ hg tglog
235 235 @ 7: c87be72f9641 'H'
236 236 |
237 237 | o 6: 17badd73d4f1 'G'
238 238 |/|
239 239 o | 5: 74fb9ed646c4 'F'
240 240 | |
241 241 | o 4: 9520eea781bc 'E'
242 242 | |
243 243 | | o 3: 32af7686d403 'D'
244 244 | | |
245 245 +---o 2: 5fddd98957c8 'C'
246 246 | |
247 247 o | 1: 42ccdea3bb16 'B'
248 248 |/
249 249 o 0: cd010b8cd998 'A'
250 250
251 251 $ cd ..
252 252
253 253
254 254 These will fail (using --source):
255 255
256 256 G onto F - rebase onto an ancestor:
257 257
258 258 $ hg clone -q -u . a a7
259 259 $ cd a7
260 260
261 261 $ hg rebase -s 6 -d 5
262 262 nothing to rebase
263 263 [1]
264 264
265 265 F onto G - rebase onto a descendant:
266 266
267 267 $ hg rebase -s 5 -d 6
268 268 abort: source and destination form a cycle
269 [255]
269 [10]
270 270
271 271 G onto B - merge revision with both parents not in ancestors of target:
272 272
273 273 $ hg rebase -s 6 -d 1
274 274 rebasing 6:eea13746799a "G"
275 275 abort: cannot rebase 6:eea13746799a without moving at least one of its parents
276 [255]
276 [10]
277 277 $ hg rebase --abort
278 278 rebase aborted
279 279
280 280 These will abort gracefully (using --base):
281 281
282 282 G onto G - rebase onto same changeset:
283 283
284 284 $ hg rebase -b 6 -d 6
285 285 nothing to rebase - eea13746799a is both "base" and destination
286 286 [1]
287 287
288 288 G onto F - rebase onto an ancestor:
289 289
290 290 $ hg rebase -b 6 -d 5
291 291 nothing to rebase
292 292 [1]
293 293
294 294 F onto G - rebase onto a descendant:
295 295
296 296 $ hg rebase -b 5 -d 6
297 297 nothing to rebase - "base" 24b6387c8c8c is already an ancestor of destination eea13746799a
298 298 [1]
299 299
300 300 C onto A - rebase onto an ancestor:
301 301
302 302 $ hg rebase -d 0 -s 2
303 303 rebasing 2:5fddd98957c8 "C"
304 304 rebasing 3:32af7686d403 "D"
305 305 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
306 306 $ hg tglog
307 307 o 7: c9659aac0000 'D'
308 308 |
309 309 o 6: e1c4361dd923 'C'
310 310 |
311 311 | @ 5: 02de42196ebe 'H'
312 312 | |
313 313 | | o 4: eea13746799a 'G'
314 314 | |/|
315 315 | o | 3: 24b6387c8c8c 'F'
316 316 |/ /
317 317 | o 2: 9520eea781bc 'E'
318 318 |/
319 319 | o 1: 42ccdea3bb16 'B'
320 320 |/
321 321 o 0: cd010b8cd998 'A'
322 322
323 323
324 324 Check rebasing public changeset
325 325
326 326 $ hg pull --config phases.publish=True -q -r 6 . # update phase of 6
327 327 $ hg rebase -d 0 -b 6
328 328 abort: cannot rebase public changesets
329 329 (see 'hg help phases' for details)
330 330 [10]
331 331 $ hg rebase -d 5 -b 6
332 332 abort: cannot rebase public changesets
333 333 (see 'hg help phases' for details)
334 334 [10]
335 335 $ hg rebase -d 5 -r '1 + (6::)'
336 336 abort: cannot rebase public changesets
337 337 (see 'hg help phases' for details)
338 338 [10]
339 339
340 340 $ hg rebase -d 5 -b 6 --keep
341 341 rebasing 6:e1c4361dd923 "C"
342 342 rebasing 7:c9659aac0000 tip "D"
343 343
344 344 Check rebasing mutable changeset
345 345 Source phase greater or equal to destination phase: new changeset get the phase of source:
346 346 $ hg id -n
347 347 5
348 348 $ hg rebase -s9 -d0
349 349 rebasing 9:2b23e52411f4 tip "D"
350 350 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2b23e52411f4-f942decf-rebase.hg
351 351 $ hg id -n # check we updated back to parent
352 352 5
353 353 $ hg log --template "{phase}\n" -r 9
354 354 draft
355 355 $ hg rebase -s9 -d1
356 356 rebasing 9:2cb10d0cfc6c tip "D"
357 357 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2cb10d0cfc6c-ddb0f256-rebase.hg
358 358 $ hg log --template "{phase}\n" -r 9
359 359 draft
360 360 $ hg phase --force --secret 9
361 361 $ hg rebase -s9 -d0
362 362 rebasing 9:c5b12b67163a tip "D"
363 363 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/c5b12b67163a-4e372053-rebase.hg
364 364 $ hg log --template "{phase}\n" -r 9
365 365 secret
366 366 $ hg rebase -s9 -d1
367 367 rebasing 9:2a0524f868ac tip "D"
368 368 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2a0524f868ac-cefd8574-rebase.hg
369 369 $ hg log --template "{phase}\n" -r 9
370 370 secret
371 371 Source phase lower than destination phase: new changeset get the phase of destination:
372 372 $ hg rebase -s8 -d9
373 373 rebasing 8:6d4f22462821 "C"
374 374 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/6d4f22462821-3441f70b-rebase.hg
375 375 $ hg log --template "{phase}\n" -r 'rev(9)'
376 376 secret
377 377
378 378 $ cd ..
379 379
380 380 Check that temporary bundle doesn't lose phase when not using generaldelta
381 381
382 382 $ hg --config format.usegeneraldelta=no init issue5678
383 383 $ cd issue5678
384 384 $ grep generaldelta .hg/requires
385 385 [1]
386 386 $ echo a > a
387 387 $ hg ci -Aqm a
388 388 $ echo b > b
389 389 $ hg ci -Aqm b
390 390 $ hg co -q '.^'
391 391 $ echo c > c
392 392 $ hg ci -Aqm c
393 393 $ hg phase --public
394 394 $ hg log -G -T '{rev}:{node|shortest} {phase} {desc}\n'
395 395 @ 2:d36c public c
396 396 |
397 397 | o 1:d2ae draft b
398 398 |/
399 399 o 0:cb9a public a
400 400
401 401 $ hg rebase -s 1 -d 2
402 402 rebasing 1:d2ae7f538514 "b"
403 403 saved backup bundle to $TESTTMP/issue5678/.hg/strip-backup/d2ae7f538514-2953539b-rebase.hg
404 404 $ hg log -G -T '{rev}:{node|shortest} {phase} {desc}\n'
405 405 o 2:c882 draft b
406 406 |
407 407 @ 1:d36c public c
408 408 |
409 409 o 0:cb9a public a
410 410
411 411 $ cd ..
412 412
413 413 Test for revset
414 414
415 415 We need a bit different graph
416 416 All destination are B
417 417
418 418 $ hg init ah
419 419 $ cd ah
420 420 $ hg unbundle "$TESTDIR/bundles/rebase-revset.hg"
421 421 adding changesets
422 422 adding manifests
423 423 adding file changes
424 424 added 9 changesets with 9 changes to 9 files (+2 heads)
425 425 new changesets 9ae2ed22e576:479ddb54a924 (9 drafts)
426 426 (run 'hg heads' to see heads, 'hg merge' to merge)
427 427 $ hg tglog
428 428 o 8: 479ddb54a924 'I'
429 429 |
430 430 o 7: 72434a4e60b0 'H'
431 431 |
432 432 o 6: 3d8a618087a7 'G'
433 433 |
434 434 | o 5: 41bfcc75ed73 'F'
435 435 | |
436 436 | o 4: c01897464e7f 'E'
437 437 |/
438 438 o 3: ffd453c31098 'D'
439 439 |
440 440 o 2: c9e50f6cdc55 'C'
441 441 |
442 442 | o 1: 8fd0f7e49f53 'B'
443 443 |/
444 444 o 0: 9ae2ed22e576 'A'
445 445
446 446 $ cd ..
447 447
448 448
449 449 Simple case with keep:
450 450
451 451 Source on have two descendant heads but ask for one
452 452
453 453 $ hg clone -q -u . ah ah1
454 454 $ cd ah1
455 455 $ hg rebase -r '2::8' -d 1
456 456 abort: cannot rebase changeset with children
457 457 (use --keep to keep original changesets)
458 458 [10]
459 459 $ hg rebase -r '2::8' -d 1 -k
460 460 rebasing 2:c9e50f6cdc55 "C"
461 461 rebasing 3:ffd453c31098 "D"
462 462 rebasing 6:3d8a618087a7 "G"
463 463 rebasing 7:72434a4e60b0 "H"
464 464 rebasing 8:479ddb54a924 tip "I"
465 465 $ hg tglog
466 466 o 13: 9bf1d9358a90 'I'
467 467 |
468 468 o 12: 274623a778d4 'H'
469 469 |
470 470 o 11: ab8c8617c8e8 'G'
471 471 |
472 472 o 10: c8cbf59f70da 'D'
473 473 |
474 474 o 9: 563e4faab485 'C'
475 475 |
476 476 | o 8: 479ddb54a924 'I'
477 477 | |
478 478 | o 7: 72434a4e60b0 'H'
479 479 | |
480 480 | o 6: 3d8a618087a7 'G'
481 481 | |
482 482 | | o 5: 41bfcc75ed73 'F'
483 483 | | |
484 484 | | o 4: c01897464e7f 'E'
485 485 | |/
486 486 | o 3: ffd453c31098 'D'
487 487 | |
488 488 | o 2: c9e50f6cdc55 'C'
489 489 | |
490 490 o | 1: 8fd0f7e49f53 'B'
491 491 |/
492 492 o 0: 9ae2ed22e576 'A'
493 493
494 494
495 495 $ cd ..
496 496
497 497 Base on have one descendant heads we ask for but common ancestor have two
498 498
499 499 $ hg clone -q -u . ah ah2
500 500 $ cd ah2
501 501 $ hg rebase -r '3::8' -d 1
502 502 abort: cannot rebase changeset with children
503 503 (use --keep to keep original changesets)
504 504 [10]
505 505 $ hg rebase -r '3::8' -d 1 --keep
506 506 rebasing 3:ffd453c31098 "D"
507 507 rebasing 6:3d8a618087a7 "G"
508 508 rebasing 7:72434a4e60b0 "H"
509 509 rebasing 8:479ddb54a924 tip "I"
510 510 $ hg tglog
511 511 o 12: 9d7da0053b1c 'I'
512 512 |
513 513 o 11: 8fbd00952cbc 'H'
514 514 |
515 515 o 10: 51d434a615ee 'G'
516 516 |
517 517 o 9: a9c125634b0b 'D'
518 518 |
519 519 | o 8: 479ddb54a924 'I'
520 520 | |
521 521 | o 7: 72434a4e60b0 'H'
522 522 | |
523 523 | o 6: 3d8a618087a7 'G'
524 524 | |
525 525 | | o 5: 41bfcc75ed73 'F'
526 526 | | |
527 527 | | o 4: c01897464e7f 'E'
528 528 | |/
529 529 | o 3: ffd453c31098 'D'
530 530 | |
531 531 | o 2: c9e50f6cdc55 'C'
532 532 | |
533 533 o | 1: 8fd0f7e49f53 'B'
534 534 |/
535 535 o 0: 9ae2ed22e576 'A'
536 536
537 537
538 538 $ cd ..
539 539
540 540 rebase subset
541 541
542 542 $ hg clone -q -u . ah ah3
543 543 $ cd ah3
544 544 $ hg rebase -r '3::7' -d 1
545 545 abort: cannot rebase changeset with children
546 546 (use --keep to keep original changesets)
547 547 [10]
548 548 $ hg rebase -r '3::7' -d 1 --keep
549 549 rebasing 3:ffd453c31098 "D"
550 550 rebasing 6:3d8a618087a7 "G"
551 551 rebasing 7:72434a4e60b0 "H"
552 552 $ hg tglog
553 553 o 11: 8fbd00952cbc 'H'
554 554 |
555 555 o 10: 51d434a615ee 'G'
556 556 |
557 557 o 9: a9c125634b0b 'D'
558 558 |
559 559 | o 8: 479ddb54a924 'I'
560 560 | |
561 561 | o 7: 72434a4e60b0 'H'
562 562 | |
563 563 | o 6: 3d8a618087a7 'G'
564 564 | |
565 565 | | o 5: 41bfcc75ed73 'F'
566 566 | | |
567 567 | | o 4: c01897464e7f 'E'
568 568 | |/
569 569 | o 3: ffd453c31098 'D'
570 570 | |
571 571 | o 2: c9e50f6cdc55 'C'
572 572 | |
573 573 o | 1: 8fd0f7e49f53 'B'
574 574 |/
575 575 o 0: 9ae2ed22e576 'A'
576 576
577 577
578 578 $ cd ..
579 579
580 580 rebase subset with multiple head
581 581
582 582 $ hg clone -q -u . ah ah4
583 583 $ cd ah4
584 584 $ hg rebase -r '3::(7+5)' -d 1
585 585 abort: cannot rebase changeset with children
586 586 (use --keep to keep original changesets)
587 587 [10]
588 588 $ hg rebase -r '3::(7+5)' -d 1 --keep
589 589 rebasing 3:ffd453c31098 "D"
590 590 rebasing 4:c01897464e7f "E"
591 591 rebasing 5:41bfcc75ed73 "F"
592 592 rebasing 6:3d8a618087a7 "G"
593 593 rebasing 7:72434a4e60b0 "H"
594 594 $ hg tglog
595 595 o 13: 8fbd00952cbc 'H'
596 596 |
597 597 o 12: 51d434a615ee 'G'
598 598 |
599 599 | o 11: df23d8bda0b7 'F'
600 600 | |
601 601 | o 10: 47b7889448ff 'E'
602 602 |/
603 603 o 9: a9c125634b0b 'D'
604 604 |
605 605 | o 8: 479ddb54a924 'I'
606 606 | |
607 607 | o 7: 72434a4e60b0 'H'
608 608 | |
609 609 | o 6: 3d8a618087a7 'G'
610 610 | |
611 611 | | o 5: 41bfcc75ed73 'F'
612 612 | | |
613 613 | | o 4: c01897464e7f 'E'
614 614 | |/
615 615 | o 3: ffd453c31098 'D'
616 616 | |
617 617 | o 2: c9e50f6cdc55 'C'
618 618 | |
619 619 o | 1: 8fd0f7e49f53 'B'
620 620 |/
621 621 o 0: 9ae2ed22e576 'A'
622 622
623 623
624 624 $ cd ..
625 625
626 626 More advanced tests
627 627
628 628 rebase on ancestor with revset
629 629
630 630 $ hg clone -q -u . ah ah5
631 631 $ cd ah5
632 632 $ hg rebase -r '6::' -d 2
633 633 rebasing 6:3d8a618087a7 "G"
634 634 rebasing 7:72434a4e60b0 "H"
635 635 rebasing 8:479ddb54a924 tip "I"
636 636 saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-b4f73f31-rebase.hg
637 637 $ hg tglog
638 638 o 8: fcb52e68a694 'I'
639 639 |
640 640 o 7: 77bd65cd7600 'H'
641 641 |
642 642 o 6: 12d0e738fb18 'G'
643 643 |
644 644 | o 5: 41bfcc75ed73 'F'
645 645 | |
646 646 | o 4: c01897464e7f 'E'
647 647 | |
648 648 | o 3: ffd453c31098 'D'
649 649 |/
650 650 o 2: c9e50f6cdc55 'C'
651 651 |
652 652 | o 1: 8fd0f7e49f53 'B'
653 653 |/
654 654 o 0: 9ae2ed22e576 'A'
655 655
656 656 $ cd ..
657 657
658 658
659 659 rebase with multiple root.
660 660 We rebase E and G on B
661 661 We would expect heads are I, F if it was supported
662 662
663 663 $ hg clone -q -u . ah ah6
664 664 $ cd ah6
665 665 $ hg rebase -r '(4+6)::' -d 1
666 666 rebasing 4:c01897464e7f "E"
667 667 rebasing 5:41bfcc75ed73 "F"
668 668 rebasing 6:3d8a618087a7 "G"
669 669 rebasing 7:72434a4e60b0 "H"
670 670 rebasing 8:479ddb54a924 tip "I"
671 671 saved backup bundle to $TESTTMP/ah6/.hg/strip-backup/3d8a618087a7-aae93a24-rebase.hg
672 672 $ hg tglog
673 673 o 8: 9136df9a87cf 'I'
674 674 |
675 675 o 7: 23e8f30da832 'H'
676 676 |
677 677 o 6: b0efe8534e8b 'G'
678 678 |
679 679 | o 5: 6eb5b496ab79 'F'
680 680 | |
681 681 | o 4: d15eade9b0b1 'E'
682 682 |/
683 683 | o 3: ffd453c31098 'D'
684 684 | |
685 685 | o 2: c9e50f6cdc55 'C'
686 686 | |
687 687 o | 1: 8fd0f7e49f53 'B'
688 688 |/
689 689 o 0: 9ae2ed22e576 'A'
690 690
691 691 $ cd ..
692 692
693 693 More complex rebase with multiple roots
694 694 each root have a different common ancestor with the destination and this is a detach
695 695
696 696 (setup)
697 697
698 698 $ hg clone -q -u . a a8
699 699 $ cd a8
700 700 $ echo I > I
701 701 $ hg add I
702 702 $ hg commit -m I
703 703 $ hg up 4
704 704 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
705 705 $ echo I > J
706 706 $ hg add J
707 707 $ hg commit -m J
708 708 created new head
709 709 $ echo I > K
710 710 $ hg add K
711 711 $ hg commit -m K
712 712 $ hg tglog
713 713 @ 10: 23a4ace37988 'K'
714 714 |
715 715 o 9: 1301922eeb0c 'J'
716 716 |
717 717 | o 8: e7ec4e813ba6 'I'
718 718 | |
719 719 | o 7: 02de42196ebe 'H'
720 720 | |
721 721 +---o 6: eea13746799a 'G'
722 722 | |/
723 723 | o 5: 24b6387c8c8c 'F'
724 724 | |
725 725 o | 4: 9520eea781bc 'E'
726 726 |/
727 727 | o 3: 32af7686d403 'D'
728 728 | |
729 729 | o 2: 5fddd98957c8 'C'
730 730 | |
731 731 | o 1: 42ccdea3bb16 'B'
732 732 |/
733 733 o 0: cd010b8cd998 'A'
734 734
735 735 (actual test)
736 736
737 737 $ hg rebase --dest 'desc(G)' --rev 'desc(K) + desc(I)'
738 738 rebasing 8:e7ec4e813ba6 "I"
739 739 rebasing 10:23a4ace37988 tip "K"
740 740 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/23a4ace37988-b06984b3-rebase.hg
741 741 $ hg log --rev 'children(desc(G))'
742 742 changeset: 9:adb617877056
743 743 parent: 6:eea13746799a
744 744 user: test
745 745 date: Thu Jan 01 00:00:00 1970 +0000
746 746 summary: I
747 747
748 748 changeset: 10:882431a34a0e
749 749 tag: tip
750 750 parent: 6:eea13746799a
751 751 user: test
752 752 date: Thu Jan 01 00:00:00 1970 +0000
753 753 summary: K
754 754
755 755 $ hg tglog
756 756 @ 10: 882431a34a0e 'K'
757 757 |
758 758 | o 9: adb617877056 'I'
759 759 |/
760 760 | o 8: 1301922eeb0c 'J'
761 761 | |
762 762 | | o 7: 02de42196ebe 'H'
763 763 | | |
764 764 o---+ 6: eea13746799a 'G'
765 765 |/ /
766 766 | o 5: 24b6387c8c8c 'F'
767 767 | |
768 768 o | 4: 9520eea781bc 'E'
769 769 |/
770 770 | o 3: 32af7686d403 'D'
771 771 | |
772 772 | o 2: 5fddd98957c8 'C'
773 773 | |
774 774 | o 1: 42ccdea3bb16 'B'
775 775 |/
776 776 o 0: cd010b8cd998 'A'
777 777
778 778
779 779 Test that rebase is not confused by $CWD disappearing during rebase (issue4121)
780 780
781 781 $ cd ..
782 782 $ hg init cwd-vanish
783 783 $ cd cwd-vanish
784 784 $ touch initial-file
785 785 $ hg add initial-file
786 786 $ hg commit -m 'initial commit'
787 787 $ touch dest-file
788 788 $ hg add dest-file
789 789 $ hg commit -m 'dest commit'
790 790 $ hg up 0
791 791 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
792 792 $ touch other-file
793 793 $ hg add other-file
794 794 $ hg commit -m 'first source commit'
795 795 created new head
796 796 $ mkdir subdir
797 797 $ cd subdir
798 798 $ touch subfile
799 799 $ hg add subfile
800 800 $ hg commit -m 'second source with subdir'
801 801
802 802 $ hg rebase -b . -d 1 --traceback
803 803 rebasing 2:779a07b1b7a0 "first source commit"
804 804 current directory was removed (rmcwd !)
805 805 (consider changing to repo root: $TESTTMP/cwd-vanish) (rmcwd !)
806 806 rebasing 3:a7d6f3a00bf3 tip "second source with subdir"
807 807 saved backup bundle to $TESTTMP/cwd-vanish/.hg/strip-backup/779a07b1b7a0-853e0073-rebase.hg
808 808
809 809 Get back to the root of cwd-vanish. Note that even though `cd ..`
810 810 works on most systems, it does not work on FreeBSD 10, so we use an
811 811 absolute path to get back to the repository.
812 812 $ cd $TESTTMP
813 813
814 814 Test that rebase is done in topo order (issue5370)
815 815
816 816 $ hg init order
817 817 $ cd order
818 818 $ touch a && hg add a && hg ci -m A
819 819 $ touch b && hg add b && hg ci -m B
820 820 $ touch c && hg add c && hg ci -m C
821 821 $ hg up 1
822 822 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
823 823 $ touch d && hg add d && hg ci -m D
824 824 created new head
825 825 $ hg up 2
826 826 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
827 827 $ touch e && hg add e && hg ci -m E
828 828 $ hg up 3
829 829 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
830 830 $ touch f && hg add f && hg ci -m F
831 831 $ hg up 0
832 832 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
833 833 $ touch g && hg add g && hg ci -m G
834 834 created new head
835 835
836 836 $ hg tglog
837 837 @ 6: 124bb27b6f28 'G'
838 838 |
839 839 | o 5: 412b391de760 'F'
840 840 | |
841 841 | | o 4: 82ae8dc7a9b7 'E'
842 842 | | |
843 843 | o | 3: ab709c9f7171 'D'
844 844 | | |
845 845 | | o 2: d84f5cfaaf14 'C'
846 846 | |/
847 847 | o 1: 76035bbd54bd 'B'
848 848 |/
849 849 o 0: 216878401574 'A'
850 850
851 851
852 852 $ hg rebase -s 1 -d 6
853 853 rebasing 1:76035bbd54bd "B"
854 854 rebasing 2:d84f5cfaaf14 "C"
855 855 rebasing 4:82ae8dc7a9b7 "E"
856 856 rebasing 3:ab709c9f7171 "D"
857 857 rebasing 5:412b391de760 "F"
858 858 saved backup bundle to $TESTTMP/order/.hg/strip-backup/76035bbd54bd-e341bc99-rebase.hg
859 859
860 860 $ hg tglog
861 861 o 6: 31884cfb735e 'F'
862 862 |
863 863 o 5: 6d89fa5b0909 'D'
864 864 |
865 865 | o 4: de64d97c697b 'E'
866 866 | |
867 867 | o 3: b18e4d2d0aa1 'C'
868 868 |/
869 869 o 2: 0983daf9ff6a 'B'
870 870 |
871 871 @ 1: 124bb27b6f28 'G'
872 872 |
873 873 o 0: 216878401574 'A'
874 874
875 875
876 876 Test experimental revset
877 877 ========================
878 878
879 879 $ cd ../cwd-vanish
880 880
881 881 Make the repo a bit more interesting
882 882
883 883 $ hg up 1
884 884 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
885 885 $ echo aaa > aaa
886 886 $ hg add aaa
887 887 $ hg commit -m aaa
888 888 created new head
889 889 $ hg log -G
890 890 @ changeset: 4:5f7bc9025ed2
891 891 | tag: tip
892 892 | parent: 1:58d79cc1cf43
893 893 | user: test
894 894 | date: Thu Jan 01 00:00:00 1970 +0000
895 895 | summary: aaa
896 896 |
897 897 | o changeset: 3:1910d5ff34ea
898 898 | | user: test
899 899 | | date: Thu Jan 01 00:00:00 1970 +0000
900 900 | | summary: second source with subdir
901 901 | |
902 902 | o changeset: 2:82901330b6ef
903 903 |/ user: test
904 904 | date: Thu Jan 01 00:00:00 1970 +0000
905 905 | summary: first source commit
906 906 |
907 907 o changeset: 1:58d79cc1cf43
908 908 | user: test
909 909 | date: Thu Jan 01 00:00:00 1970 +0000
910 910 | summary: dest commit
911 911 |
912 912 o changeset: 0:e94b687f7da3
913 913 user: test
914 914 date: Thu Jan 01 00:00:00 1970 +0000
915 915 summary: initial commit
916 916
917 917
918 918 Testing from lower head
919 919
920 920 $ hg up 3
921 921 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
922 922 $ hg log -r '_destrebase()'
923 923 changeset: 4:5f7bc9025ed2
924 924 tag: tip
925 925 parent: 1:58d79cc1cf43
926 926 user: test
927 927 date: Thu Jan 01 00:00:00 1970 +0000
928 928 summary: aaa
929 929
930 930
931 931 Testing from upper head
932 932
933 933 $ hg log -r '_destrebase(4)'
934 934 changeset: 3:1910d5ff34ea
935 935 user: test
936 936 date: Thu Jan 01 00:00:00 1970 +0000
937 937 summary: second source with subdir
938 938
939 939 $ hg up 4
940 940 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
941 941 $ hg log -r '_destrebase()'
942 942 changeset: 3:1910d5ff34ea
943 943 user: test
944 944 date: Thu Jan 01 00:00:00 1970 +0000
945 945 summary: second source with subdir
946 946
947 947 Testing rebase being called inside another transaction
948 948
949 949 $ cd $TESTTMP
950 950 $ hg init tr-state
951 951 $ cd tr-state
952 952 $ cat > $TESTTMP/wraprebase.py <<EOF
953 953 > from __future__ import absolute_import
954 954 > from mercurial import extensions
955 955 > def _rebase(orig, ui, repo, *args, **kwargs):
956 956 > with repo.wlock():
957 957 > with repo.lock():
958 958 > with repo.transaction(b'wrappedrebase'):
959 959 > return orig(ui, repo, *args, **kwargs)
960 960 > def wraprebase(loaded):
961 961 > assert loaded
962 962 > rebasemod = extensions.find(b'rebase')
963 963 > extensions.wrapcommand(rebasemod.cmdtable, b'rebase', _rebase)
964 964 > def extsetup(ui):
965 965 > extensions.afterloaded(b'rebase', wraprebase)
966 966 > EOF
967 967
968 968 $ cat >> .hg/hgrc <<EOF
969 969 > [extensions]
970 970 > wraprebase=$TESTTMP/wraprebase.py
971 971 > [experimental]
972 972 > evolution=true
973 973 > EOF
974 974
975 975 $ hg debugdrawdag <<'EOS'
976 976 > B C
977 977 > |/
978 978 > A
979 979 > EOS
980 980
981 981 $ hg rebase -s C -d B
982 982 rebasing 2:dc0947a82db8 C tip "C"
983 983
984 984 $ [ -f .hg/rebasestate ] && echo 'WRONG: rebasestate should not exist'
985 985 [1]
General Comments 0
You need to be logged in to leave comments. Login now