##// END OF EJS Templates
rebase: don't use rebased node as dirstate p2 (BC)...
Martin von Zweigbergk -
r45206:9c9cfecd default
parent child Browse files
Show More
@@ -1,2251 +1,2249 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 )
27 27 from mercurial.pycompat import open
28 28 from mercurial import (
29 29 bookmarks,
30 30 cmdutil,
31 31 commands,
32 32 copies,
33 33 destutil,
34 34 dirstateguard,
35 35 error,
36 36 extensions,
37 37 hg,
38 38 merge as mergemod,
39 39 mergeutil,
40 40 node as nodemod,
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 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
71 71 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
72 72 # be specifying the version(s) of Mercurial they are tested with, or
73 73 # leave the attribute unspecified.
74 74 testedwith = b'ships-with-hg-core'
75 75
76 76
77 77 def _nothingtorebase():
78 78 return 1
79 79
80 80
81 81 def _savegraft(ctx, extra):
82 82 s = ctx.extra().get(b'source', None)
83 83 if s is not None:
84 84 extra[b'source'] = s
85 85 s = ctx.extra().get(b'intermediate-source', None)
86 86 if s is not None:
87 87 extra[b'intermediate-source'] = s
88 88
89 89
90 90 def _savebranch(ctx, extra):
91 91 extra[b'branch'] = ctx.branch()
92 92
93 93
94 94 def _destrebase(repo, sourceset, destspace=None):
95 95 """small wrapper around destmerge to pass the right extra args
96 96
97 97 Please wrap destutil.destmerge instead."""
98 98 return destutil.destmerge(
99 99 repo,
100 100 action=b'rebase',
101 101 sourceset=sourceset,
102 102 onheadcheck=False,
103 103 destspace=destspace,
104 104 )
105 105
106 106
107 107 revsetpredicate = registrar.revsetpredicate()
108 108
109 109
110 110 @revsetpredicate(b'_destrebase')
111 111 def _revsetdestrebase(repo, subset, x):
112 112 # ``_rebasedefaultdest()``
113 113
114 114 # default destination for rebase.
115 115 # # XXX: Currently private because I expect the signature to change.
116 116 # # XXX: - bailing out in case of ambiguity vs returning all data.
117 117 # i18n: "_rebasedefaultdest" is a keyword
118 118 sourceset = None
119 119 if x is not None:
120 120 sourceset = revset.getset(repo, smartset.fullreposet(repo), x)
121 121 return subset & smartset.baseset([_destrebase(repo, sourceset)])
122 122
123 123
124 124 @revsetpredicate(b'_destautoorphanrebase')
125 125 def _revsetdestautoorphanrebase(repo, subset, x):
126 126 # ``_destautoorphanrebase()``
127 127
128 128 # automatic rebase destination for a single orphan revision.
129 129 unfi = repo.unfiltered()
130 130 obsoleted = unfi.revs(b'obsolete()')
131 131
132 132 src = revset.getset(repo, subset, x).first()
133 133
134 134 # Empty src or already obsoleted - Do not return a destination
135 135 if not src or src in obsoleted:
136 136 return smartset.baseset()
137 137 dests = destutil.orphanpossibledestination(repo, src)
138 138 if len(dests) > 1:
139 139 raise error.Abort(
140 140 _(b"ambiguous automatic rebase: %r could end up on any of %r")
141 141 % (src, dests)
142 142 )
143 143 # We have zero or one destination, so we can just return here.
144 144 return smartset.baseset(dests)
145 145
146 146
147 147 def _ctxdesc(ctx):
148 148 """short description for a context"""
149 149 desc = b'%d:%s "%s"' % (
150 150 ctx.rev(),
151 151 ctx,
152 152 ctx.description().split(b'\n', 1)[0],
153 153 )
154 154 repo = ctx.repo()
155 155 names = []
156 156 for nsname, ns in pycompat.iteritems(repo.names):
157 157 if nsname == b'branches':
158 158 continue
159 159 names.extend(ns.names(repo, ctx.node()))
160 160 if names:
161 161 desc += b' (%s)' % b' '.join(names)
162 162 return desc
163 163
164 164
165 165 class rebaseruntime(object):
166 166 """This class is a container for rebase runtime state"""
167 167
168 168 def __init__(self, repo, ui, inmemory=False, opts=None):
169 169 if opts is None:
170 170 opts = {}
171 171
172 172 # prepared: whether we have rebasestate prepared or not. Currently it
173 173 # decides whether "self.repo" is unfiltered or not.
174 174 # The rebasestate has explicit hash to hash instructions not depending
175 175 # on visibility. If rebasestate exists (in-memory or on-disk), use
176 176 # unfiltered repo to avoid visibility issues.
177 177 # Before knowing rebasestate (i.e. when starting a new rebase (not
178 178 # --continue or --abort)), the original repo should be used so
179 179 # visibility-dependent revsets are correct.
180 180 self.prepared = False
181 181 self.resume = False
182 182 self._repo = repo
183 183
184 184 self.ui = ui
185 185 self.opts = opts
186 186 self.originalwd = None
187 187 self.external = nullrev
188 188 # Mapping between the old revision id and either what is the new rebased
189 189 # revision or what needs to be done with the old revision. The state
190 190 # dict will be what contains most of the rebase progress state.
191 191 self.state = {}
192 192 self.activebookmark = None
193 193 self.destmap = {}
194 194 self.skipped = set()
195 195
196 196 self.collapsef = opts.get(b'collapse', False)
197 197 self.collapsemsg = cmdutil.logmessage(ui, opts)
198 198 self.date = opts.get(b'date', None)
199 199
200 200 e = opts.get(b'extrafn') # internal, used by e.g. hgsubversion
201 201 self.extrafns = [_savegraft]
202 202 if e:
203 203 self.extrafns = [e]
204 204
205 205 self.backupf = ui.configbool(b'rewrite', b'backup-bundle')
206 206 self.keepf = opts.get(b'keep', False)
207 207 self.keepbranchesf = opts.get(b'keepbranches', False)
208 208 self.obsoletenotrebased = {}
209 209 self.obsoletewithoutsuccessorindestination = set()
210 210 self.inmemory = inmemory
211 211 self.stateobj = statemod.cmdstate(repo, b'rebasestate')
212 212
213 213 @property
214 214 def repo(self):
215 215 if self.prepared:
216 216 return self._repo.unfiltered()
217 217 else:
218 218 return self._repo
219 219
220 220 def storestatus(self, tr=None):
221 221 """Store the current status to allow recovery"""
222 222 if tr:
223 223 tr.addfilegenerator(
224 224 b'rebasestate',
225 225 (b'rebasestate',),
226 226 self._writestatus,
227 227 location=b'plain',
228 228 )
229 229 else:
230 230 with self.repo.vfs(b"rebasestate", b"w") as f:
231 231 self._writestatus(f)
232 232
233 233 def _writestatus(self, f):
234 234 repo = self.repo
235 235 assert repo.filtername is None
236 236 f.write(repo[self.originalwd].hex() + b'\n')
237 237 # was "dest". we now write dest per src root below.
238 238 f.write(b'\n')
239 239 f.write(repo[self.external].hex() + b'\n')
240 240 f.write(b'%d\n' % int(self.collapsef))
241 241 f.write(b'%d\n' % int(self.keepf))
242 242 f.write(b'%d\n' % int(self.keepbranchesf))
243 243 f.write(b'%s\n' % (self.activebookmark or b''))
244 244 destmap = self.destmap
245 245 for d, v in pycompat.iteritems(self.state):
246 246 oldrev = repo[d].hex()
247 247 if v >= 0:
248 248 newrev = repo[v].hex()
249 249 else:
250 250 newrev = b"%d" % v
251 251 destnode = repo[destmap[d]].hex()
252 252 f.write(b"%s:%s:%s\n" % (oldrev, newrev, destnode))
253 253 repo.ui.debug(b'rebase status stored\n')
254 254
255 255 def restorestatus(self):
256 256 """Restore a previously stored status"""
257 257 if not self.stateobj.exists():
258 258 cmdutil.wrongtooltocontinue(self.repo, _(b'rebase'))
259 259
260 260 data = self._read()
261 261 self.repo.ui.debug(b'rebase status resumed\n')
262 262
263 263 self.originalwd = data[b'originalwd']
264 264 self.destmap = data[b'destmap']
265 265 self.state = data[b'state']
266 266 self.skipped = data[b'skipped']
267 267 self.collapsef = data[b'collapse']
268 268 self.keepf = data[b'keep']
269 269 self.keepbranchesf = data[b'keepbranches']
270 270 self.external = data[b'external']
271 271 self.activebookmark = data[b'activebookmark']
272 272
273 273 def _read(self):
274 274 self.prepared = True
275 275 repo = self.repo
276 276 assert repo.filtername is None
277 277 data = {
278 278 b'keepbranches': None,
279 279 b'collapse': None,
280 280 b'activebookmark': None,
281 281 b'external': nullrev,
282 282 b'keep': None,
283 283 b'originalwd': None,
284 284 }
285 285 legacydest = None
286 286 state = {}
287 287 destmap = {}
288 288
289 289 if True:
290 290 f = repo.vfs(b"rebasestate")
291 291 for i, l in enumerate(f.read().splitlines()):
292 292 if i == 0:
293 293 data[b'originalwd'] = repo[l].rev()
294 294 elif i == 1:
295 295 # this line should be empty in newer version. but legacy
296 296 # clients may still use it
297 297 if l:
298 298 legacydest = repo[l].rev()
299 299 elif i == 2:
300 300 data[b'external'] = repo[l].rev()
301 301 elif i == 3:
302 302 data[b'collapse'] = bool(int(l))
303 303 elif i == 4:
304 304 data[b'keep'] = bool(int(l))
305 305 elif i == 5:
306 306 data[b'keepbranches'] = bool(int(l))
307 307 elif i == 6 and not (len(l) == 81 and b':' in l):
308 308 # line 6 is a recent addition, so for backwards
309 309 # compatibility check that the line doesn't look like the
310 310 # oldrev:newrev lines
311 311 data[b'activebookmark'] = l
312 312 else:
313 313 args = l.split(b':')
314 314 oldrev = repo[args[0]].rev()
315 315 newrev = args[1]
316 316 if newrev in legacystates:
317 317 continue
318 318 if len(args) > 2:
319 319 destrev = repo[args[2]].rev()
320 320 else:
321 321 destrev = legacydest
322 322 destmap[oldrev] = destrev
323 323 if newrev == revtodostr:
324 324 state[oldrev] = revtodo
325 325 # Legacy compat special case
326 326 else:
327 327 state[oldrev] = repo[newrev].rev()
328 328
329 329 if data[b'keepbranches'] is None:
330 330 raise error.Abort(_(b'.hg/rebasestate is incomplete'))
331 331
332 332 data[b'destmap'] = destmap
333 333 data[b'state'] = state
334 334 skipped = set()
335 335 # recompute the set of skipped revs
336 336 if not data[b'collapse']:
337 337 seen = set(destmap.values())
338 338 for old, new in sorted(state.items()):
339 339 if new != revtodo and new in seen:
340 340 skipped.add(old)
341 341 seen.add(new)
342 342 data[b'skipped'] = skipped
343 343 repo.ui.debug(
344 344 b'computed skipped revs: %s\n'
345 345 % (b' '.join(b'%d' % r for r in sorted(skipped)) or b'')
346 346 )
347 347
348 348 return data
349 349
350 350 def _handleskippingobsolete(self, obsoleterevs, destmap):
351 351 """Compute structures necessary for skipping obsolete revisions
352 352
353 353 obsoleterevs: iterable of all obsolete revisions in rebaseset
354 354 destmap: {srcrev: destrev} destination revisions
355 355 """
356 356 self.obsoletenotrebased = {}
357 357 if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
358 358 return
359 359 obsoleteset = set(obsoleterevs)
360 360 (
361 361 self.obsoletenotrebased,
362 362 self.obsoletewithoutsuccessorindestination,
363 363 obsoleteextinctsuccessors,
364 364 ) = _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
365 365 skippedset = set(self.obsoletenotrebased)
366 366 skippedset.update(self.obsoletewithoutsuccessorindestination)
367 367 skippedset.update(obsoleteextinctsuccessors)
368 368 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
369 369
370 370 def _prepareabortorcontinue(self, isabort, backup=True, suppwarns=False):
371 371 self.resume = True
372 372 try:
373 373 self.restorestatus()
374 374 self.collapsemsg = restorecollapsemsg(self.repo, isabort)
375 375 except error.RepoLookupError:
376 376 if isabort:
377 377 clearstatus(self.repo)
378 378 clearcollapsemsg(self.repo)
379 379 self.repo.ui.warn(
380 380 _(
381 381 b'rebase aborted (no revision is removed,'
382 382 b' only broken state is cleared)\n'
383 383 )
384 384 )
385 385 return 0
386 386 else:
387 387 msg = _(b'cannot continue inconsistent rebase')
388 388 hint = _(b'use "hg rebase --abort" to clear broken state')
389 389 raise error.Abort(msg, hint=hint)
390 390
391 391 if isabort:
392 392 backup = backup and self.backupf
393 393 return self._abort(backup=backup, suppwarns=suppwarns)
394 394
395 395 def _preparenewrebase(self, destmap):
396 396 if not destmap:
397 397 return _nothingtorebase()
398 398
399 399 rebaseset = destmap.keys()
400 400 if not self.keepf:
401 401 try:
402 402 rewriteutil.precheck(self.repo, rebaseset, action=b'rebase')
403 403 except error.Abort as e:
404 404 if e.hint is None:
405 405 e.hint = _(b'use --keep to keep original changesets')
406 406 raise e
407 407
408 408 result = buildstate(self.repo, destmap, self.collapsef)
409 409
410 410 if not result:
411 411 # Empty state built, nothing to rebase
412 412 self.ui.status(_(b'nothing to rebase\n'))
413 413 return _nothingtorebase()
414 414
415 415 (self.originalwd, self.destmap, self.state) = result
416 416 if self.collapsef:
417 417 dests = set(self.destmap.values())
418 418 if len(dests) != 1:
419 419 raise error.Abort(
420 420 _(b'--collapse does not work with multiple destinations')
421 421 )
422 422 destrev = next(iter(dests))
423 423 destancestors = self.repo.changelog.ancestors(
424 424 [destrev], inclusive=True
425 425 )
426 426 self.external = externalparent(self.repo, self.state, destancestors)
427 427
428 428 for destrev in sorted(set(destmap.values())):
429 429 dest = self.repo[destrev]
430 430 if dest.closesbranch() and not self.keepbranchesf:
431 431 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
432 432
433 433 self.prepared = True
434 434
435 435 def _assignworkingcopy(self):
436 436 if self.inmemory:
437 437 from mercurial.context import overlayworkingctx
438 438
439 439 self.wctx = overlayworkingctx(self.repo)
440 440 self.repo.ui.debug(b"rebasing in-memory\n")
441 441 else:
442 442 self.wctx = self.repo[None]
443 443 self.repo.ui.debug(b"rebasing on disk\n")
444 444 self.repo.ui.log(
445 445 b"rebase",
446 446 b"using in-memory rebase: %r\n",
447 447 self.inmemory,
448 448 rebase_imm_used=self.inmemory,
449 449 )
450 450
451 451 def _performrebase(self, tr):
452 452 self._assignworkingcopy()
453 453 repo, ui = self.repo, self.ui
454 454 if self.keepbranchesf:
455 455 # insert _savebranch at the start of extrafns so if
456 456 # there's a user-provided extrafn it can clobber branch if
457 457 # desired
458 458 self.extrafns.insert(0, _savebranch)
459 459 if self.collapsef:
460 460 branches = set()
461 461 for rev in self.state:
462 462 branches.add(repo[rev].branch())
463 463 if len(branches) > 1:
464 464 raise error.Abort(
465 465 _(b'cannot collapse multiple named branches')
466 466 )
467 467
468 468 # Calculate self.obsoletenotrebased
469 469 obsrevs = _filterobsoleterevs(self.repo, self.state)
470 470 self._handleskippingobsolete(obsrevs, self.destmap)
471 471
472 472 # Keep track of the active bookmarks in order to reset them later
473 473 self.activebookmark = self.activebookmark or repo._activebookmark
474 474 if self.activebookmark:
475 475 bookmarks.deactivate(repo)
476 476
477 477 # Store the state before we begin so users can run 'hg rebase --abort'
478 478 # if we fail before the transaction closes.
479 479 self.storestatus()
480 480 if tr:
481 481 # When using single transaction, store state when transaction
482 482 # commits.
483 483 self.storestatus(tr)
484 484
485 485 cands = [k for k, v in pycompat.iteritems(self.state) if v == revtodo]
486 486 p = repo.ui.makeprogress(
487 487 _(b"rebasing"), unit=_(b'changesets'), total=len(cands)
488 488 )
489 489
490 490 def progress(ctx):
491 491 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx)))
492 492
493 493 allowdivergence = self.ui.configbool(
494 494 b'experimental', b'evolution.allowdivergence'
495 495 )
496 496 for subset in sortsource(self.destmap):
497 497 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
498 498 if not allowdivergence:
499 499 sortedrevs -= self.repo.revs(
500 500 b'descendants(%ld) and not %ld',
501 501 self.obsoletewithoutsuccessorindestination,
502 502 self.obsoletewithoutsuccessorindestination,
503 503 )
504 504 for rev in sortedrevs:
505 505 self._rebasenode(tr, rev, allowdivergence, progress)
506 506 p.complete()
507 507 ui.note(_(b'rebase merging completed\n'))
508 508
509 509 def _concludenode(self, rev, p1, p2, editor, commitmsg=None):
510 510 '''Commit the wd changes with parents p1 and p2.
511 511
512 512 Reuse commit info from rev but also store useful information in extra.
513 513 Return node of committed revision.'''
514 514 repo = self.repo
515 515 ctx = repo[rev]
516 516 if commitmsg is None:
517 517 commitmsg = ctx.description()
518 518 date = self.date
519 519 if date is None:
520 520 date = ctx.date()
521 521 extra = {b'rebase_source': ctx.hex()}
522 522 for c in self.extrafns:
523 523 c(ctx, extra)
524 524 keepbranch = self.keepbranchesf and repo[p1].branch() != ctx.branch()
525 525 destphase = max(ctx.phase(), phases.draft)
526 526 overrides = {(b'phases', b'new-commit'): destphase}
527 527 if keepbranch:
528 528 overrides[(b'ui', b'allowemptycommit')] = True
529 529 with repo.ui.configoverride(overrides, b'rebase'):
530 530 if self.inmemory:
531 531 newnode = commitmemorynode(
532 532 repo,
533 533 p1,
534 534 p2,
535 535 wctx=self.wctx,
536 536 extra=extra,
537 537 commitmsg=commitmsg,
538 538 editor=editor,
539 539 user=ctx.user(),
540 540 date=date,
541 541 )
542 542 mergemod.mergestate.clean(repo)
543 543 else:
544 544 newnode = commitnode(
545 545 repo,
546 546 p1,
547 547 p2,
548 548 extra=extra,
549 549 commitmsg=commitmsg,
550 550 editor=editor,
551 551 user=ctx.user(),
552 552 date=date,
553 553 )
554 554
555 555 if newnode is None:
556 556 # If it ended up being a no-op commit, then the normal
557 557 # merge state clean-up path doesn't happen, so do it
558 558 # here. Fix issue5494
559 559 mergemod.mergestate.clean(repo)
560 560 return newnode
561 561
562 562 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
563 563 repo, ui, opts = self.repo, self.ui, self.opts
564 564 dest = self.destmap[rev]
565 565 ctx = repo[rev]
566 566 desc = _ctxdesc(ctx)
567 567 if self.state[rev] == rev:
568 568 ui.status(_(b'already rebased %s\n') % desc)
569 569 elif (
570 570 not allowdivergence
571 571 and rev in self.obsoletewithoutsuccessorindestination
572 572 ):
573 573 msg = (
574 574 _(
575 575 b'note: not rebasing %s and its descendants as '
576 576 b'this would cause divergence\n'
577 577 )
578 578 % desc
579 579 )
580 580 repo.ui.status(msg)
581 581 self.skipped.add(rev)
582 582 elif rev in self.obsoletenotrebased:
583 583 succ = self.obsoletenotrebased[rev]
584 584 if succ is None:
585 585 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
586 586 else:
587 587 succdesc = _ctxdesc(repo[succ])
588 588 msg = _(
589 589 b'note: not rebasing %s, already in destination as %s\n'
590 590 ) % (desc, succdesc)
591 591 repo.ui.status(msg)
592 592 # Make clearrebased aware state[rev] is not a true successor
593 593 self.skipped.add(rev)
594 594 # Record rev as moved to its desired destination in self.state.
595 595 # This helps bookmark and working parent movement.
596 596 dest = max(
597 597 adjustdest(repo, rev, self.destmap, self.state, self.skipped)
598 598 )
599 599 self.state[rev] = dest
600 600 elif self.state[rev] == revtodo:
601 601 ui.status(_(b'rebasing %s\n') % desc)
602 602 progressfn(ctx)
603 603 p1, p2, base = defineparents(
604 604 repo,
605 605 rev,
606 606 self.destmap,
607 607 self.state,
608 608 self.skipped,
609 609 self.obsoletenotrebased,
610 610 )
611 611 if self.resume and self.wctx.p1().rev() == p1:
612 612 repo.ui.debug(b'resuming interrupted rebase\n')
613 613 self.resume = False
614 614 else:
615 615 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
616 616 with ui.configoverride(overrides, b'rebase'):
617 617 stats = rebasenode(
618 618 repo,
619 619 rev,
620 620 p1,
621 p2,
621 622 base,
622 623 self.collapsef,
623 624 dest,
624 625 wctx=self.wctx,
625 626 )
626 627 if stats.unresolvedcount > 0:
627 628 if self.inmemory:
628 629 raise error.InMemoryMergeConflictsError()
629 630 else:
630 631 raise error.InterventionRequired(
631 632 _(
632 633 b'unresolved conflicts (see hg '
633 634 b'resolve, then hg rebase --continue)'
634 635 )
635 636 )
636 637 if not self.collapsef:
637 638 merging = p2 != nullrev
638 639 editform = cmdutil.mergeeditform(merging, b'rebase')
639 640 editor = cmdutil.getcommiteditor(
640 641 editform=editform, **pycompat.strkwargs(opts)
641 642 )
642 643 newnode = self._concludenode(rev, p1, p2, editor)
643 644 else:
644 645 # Skip commit if we are collapsing
645 if self.inmemory:
646 self.wctx.setbase(repo[p1])
647 else:
648 repo.setparents(repo[p1].node())
649 646 newnode = None
650 647 # Update the state
651 648 if newnode is not None:
652 649 self.state[rev] = repo[newnode].rev()
653 650 ui.debug(b'rebased as %s\n' % short(newnode))
654 651 else:
655 652 if not self.collapsef:
656 653 ui.warn(
657 654 _(
658 655 b'note: not rebasing %s, its destination already '
659 656 b'has all its changes\n'
660 657 )
661 658 % desc
662 659 )
663 660 self.skipped.add(rev)
664 661 self.state[rev] = p1
665 662 ui.debug(b'next revision set to %d\n' % p1)
666 663 else:
667 664 ui.status(
668 665 _(b'already rebased %s as %s\n') % (desc, repo[self.state[rev]])
669 666 )
670 667 if not tr:
671 668 # When not using single transaction, store state after each
672 669 # commit is completely done. On InterventionRequired, we thus
673 670 # won't store the status. Instead, we'll hit the "len(parents) == 2"
674 671 # case and realize that the commit was in progress.
675 672 self.storestatus()
676 673
677 674 def _finishrebase(self):
678 675 repo, ui, opts = self.repo, self.ui, self.opts
679 676 fm = ui.formatter(b'rebase', opts)
680 677 fm.startitem()
681 678 if self.collapsef:
682 679 p1, p2, _base = defineparents(
683 680 repo,
684 681 min(self.state),
685 682 self.destmap,
686 683 self.state,
687 684 self.skipped,
688 685 self.obsoletenotrebased,
689 686 )
690 687 editopt = opts.get(b'edit')
691 688 editform = b'rebase.collapse'
692 689 if self.collapsemsg:
693 690 commitmsg = self.collapsemsg
694 691 else:
695 692 commitmsg = b'Collapsed revision'
696 693 for rebased in sorted(self.state):
697 694 if rebased not in self.skipped:
698 695 commitmsg += b'\n* %s' % repo[rebased].description()
699 696 editopt = True
700 697 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
701 698 revtoreuse = max(self.state)
702 699
703 700 newnode = self._concludenode(
704 701 revtoreuse, p1, self.external, editor, commitmsg=commitmsg
705 702 )
706 703
707 704 if newnode is not None:
708 705 newrev = repo[newnode].rev()
709 706 for oldrev in self.state:
710 707 self.state[oldrev] = newrev
711 708
712 709 if b'qtip' in repo.tags():
713 710 updatemq(repo, self.state, self.skipped, **pycompat.strkwargs(opts))
714 711
715 712 # restore original working directory
716 713 # (we do this before stripping)
717 714 newwd = self.state.get(self.originalwd, self.originalwd)
718 715 if newwd < 0:
719 716 # original directory is a parent of rebase set root or ignored
720 717 newwd = self.originalwd
721 718 if newwd not in [c.rev() for c in repo[None].parents()]:
722 719 ui.note(_(b"update back to initial working directory parent\n"))
723 720 hg.updaterepo(repo, newwd, overwrite=False)
724 721
725 722 collapsedas = None
726 723 if self.collapsef and not self.keepf:
727 724 collapsedas = newnode
728 725 clearrebased(
729 726 ui,
730 727 repo,
731 728 self.destmap,
732 729 self.state,
733 730 self.skipped,
734 731 collapsedas,
735 732 self.keepf,
736 733 fm=fm,
737 734 backup=self.backupf,
738 735 )
739 736
740 737 clearstatus(repo)
741 738 clearcollapsemsg(repo)
742 739
743 740 ui.note(_(b"rebase completed\n"))
744 741 util.unlinkpath(repo.sjoin(b'undo'), ignoremissing=True)
745 742 if self.skipped:
746 743 skippedlen = len(self.skipped)
747 744 ui.note(_(b"%d revisions have been skipped\n") % skippedlen)
748 745 fm.end()
749 746
750 747 if (
751 748 self.activebookmark
752 749 and self.activebookmark in repo._bookmarks
753 750 and repo[b'.'].node() == repo._bookmarks[self.activebookmark]
754 751 ):
755 752 bookmarks.activate(repo, self.activebookmark)
756 753
757 754 def _abort(self, backup=True, suppwarns=False):
758 755 '''Restore the repository to its original state.'''
759 756
760 757 repo = self.repo
761 758 try:
762 759 # If the first commits in the rebased set get skipped during the
763 760 # rebase, their values within the state mapping will be the dest
764 761 # rev id. The rebased list must must not contain the dest rev
765 762 # (issue4896)
766 763 rebased = [
767 764 s
768 765 for r, s in self.state.items()
769 766 if s >= 0 and s != r and s != self.destmap[r]
770 767 ]
771 768 immutable = [d for d in rebased if not repo[d].mutable()]
772 769 cleanup = True
773 770 if immutable:
774 771 repo.ui.warn(
775 772 _(b"warning: can't clean up public changesets %s\n")
776 773 % b', '.join(bytes(repo[r]) for r in immutable),
777 774 hint=_(b"see 'hg help phases' for details"),
778 775 )
779 776 cleanup = False
780 777
781 778 descendants = set()
782 779 if rebased:
783 780 descendants = set(repo.changelog.descendants(rebased))
784 781 if descendants - set(rebased):
785 782 repo.ui.warn(
786 783 _(
787 784 b"warning: new changesets detected on "
788 785 b"destination branch, can't strip\n"
789 786 )
790 787 )
791 788 cleanup = False
792 789
793 790 if cleanup:
794 791 if rebased:
795 792 strippoints = [
796 793 c.node() for c in repo.set(b'roots(%ld)', rebased)
797 794 ]
798 795
799 796 updateifonnodes = set(rebased)
800 797 updateifonnodes.update(self.destmap.values())
801 798 updateifonnodes.add(self.originalwd)
802 799 shouldupdate = repo[b'.'].rev() in updateifonnodes
803 800
804 801 # Update away from the rebase if necessary
805 802 if shouldupdate:
806 803 mergemod.clean_update(repo[self.originalwd])
807 804
808 805 # Strip from the first rebased revision
809 806 if rebased:
810 807 repair.strip(repo.ui, repo, strippoints, backup=backup)
811 808
812 809 if self.activebookmark and self.activebookmark in repo._bookmarks:
813 810 bookmarks.activate(repo, self.activebookmark)
814 811
815 812 finally:
816 813 clearstatus(repo)
817 814 clearcollapsemsg(repo)
818 815 if not suppwarns:
819 816 repo.ui.warn(_(b'rebase aborted\n'))
820 817 return 0
821 818
822 819
823 820 @command(
824 821 b'rebase',
825 822 [
826 823 (
827 824 b's',
828 825 b'source',
829 826 b'',
830 827 _(b'rebase the specified changeset and descendants'),
831 828 _(b'REV'),
832 829 ),
833 830 (
834 831 b'b',
835 832 b'base',
836 833 b'',
837 834 _(b'rebase everything from branching point of specified changeset'),
838 835 _(b'REV'),
839 836 ),
840 837 (b'r', b'rev', [], _(b'rebase these revisions'), _(b'REV')),
841 838 (
842 839 b'd',
843 840 b'dest',
844 841 b'',
845 842 _(b'rebase onto the specified changeset'),
846 843 _(b'REV'),
847 844 ),
848 845 (b'', b'collapse', False, _(b'collapse the rebased changesets')),
849 846 (
850 847 b'm',
851 848 b'message',
852 849 b'',
853 850 _(b'use text as collapse commit message'),
854 851 _(b'TEXT'),
855 852 ),
856 853 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
857 854 (
858 855 b'l',
859 856 b'logfile',
860 857 b'',
861 858 _(b'read collapse commit message from file'),
862 859 _(b'FILE'),
863 860 ),
864 861 (b'k', b'keep', False, _(b'keep original changesets')),
865 862 (b'', b'keepbranches', False, _(b'keep original branch names')),
866 863 (b'D', b'detach', False, _(b'(DEPRECATED)')),
867 864 (b'i', b'interactive', False, _(b'(DEPRECATED)')),
868 865 (b't', b'tool', b'', _(b'specify merge tool')),
869 866 (b'', b'stop', False, _(b'stop interrupted rebase')),
870 867 (b'c', b'continue', False, _(b'continue an interrupted rebase')),
871 868 (b'a', b'abort', False, _(b'abort an interrupted rebase')),
872 869 (
873 870 b'',
874 871 b'auto-orphans',
875 872 b'',
876 873 _(
877 874 b'automatically rebase orphan revisions '
878 875 b'in the specified revset (EXPERIMENTAL)'
879 876 ),
880 877 ),
881 878 ]
882 879 + cmdutil.dryrunopts
883 880 + cmdutil.formatteropts
884 881 + cmdutil.confirmopts,
885 882 _(b'[-s REV | -b REV] [-d REV] [OPTION]'),
886 883 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
887 884 )
888 885 def rebase(ui, repo, **opts):
889 886 """move changeset (and descendants) to a different branch
890 887
891 888 Rebase uses repeated merging to graft changesets from one part of
892 889 history (the source) onto another (the destination). This can be
893 890 useful for linearizing *local* changes relative to a master
894 891 development tree.
895 892
896 893 Published commits cannot be rebased (see :hg:`help phases`).
897 894 To copy commits, see :hg:`help graft`.
898 895
899 896 If you don't specify a destination changeset (``-d/--dest``), rebase
900 897 will use the same logic as :hg:`merge` to pick a destination. if
901 898 the current branch contains exactly one other head, the other head
902 899 is merged with by default. Otherwise, an explicit revision with
903 900 which to merge with must be provided. (destination changeset is not
904 901 modified by rebasing, but new changesets are added as its
905 902 descendants.)
906 903
907 904 Here are the ways to select changesets:
908 905
909 906 1. Explicitly select them using ``--rev``.
910 907
911 908 2. Use ``--source`` to select a root changeset and include all of its
912 909 descendants.
913 910
914 911 3. Use ``--base`` to select a changeset; rebase will find ancestors
915 912 and their descendants which are not also ancestors of the destination.
916 913
917 914 4. If you do not specify any of ``--rev``, ``--source``, or ``--base``,
918 915 rebase will use ``--base .`` as above.
919 916
920 917 If ``--source`` or ``--rev`` is used, special names ``SRC`` and ``ALLSRC``
921 918 can be used in ``--dest``. Destination would be calculated per source
922 919 revision with ``SRC`` substituted by that single source revision and
923 920 ``ALLSRC`` substituted by all source revisions.
924 921
925 922 Rebase will destroy original changesets unless you use ``--keep``.
926 923 It will also move your bookmarks (even if you do).
927 924
928 925 Some changesets may be dropped if they do not contribute changes
929 926 (e.g. merges from the destination branch).
930 927
931 928 Unlike ``merge``, rebase will do nothing if you are at the branch tip of
932 929 a named branch with two heads. You will need to explicitly specify source
933 930 and/or destination.
934 931
935 932 If you need to use a tool to automate merge/conflict decisions, you
936 933 can specify one with ``--tool``, see :hg:`help merge-tools`.
937 934 As a caveat: the tool will not be used to mediate when a file was
938 935 deleted, there is no hook presently available for this.
939 936
940 937 If a rebase is interrupted to manually resolve a conflict, it can be
941 938 continued with --continue/-c, aborted with --abort/-a, or stopped with
942 939 --stop.
943 940
944 941 .. container:: verbose
945 942
946 943 Examples:
947 944
948 945 - move "local changes" (current commit back to branching point)
949 946 to the current branch tip after a pull::
950 947
951 948 hg rebase
952 949
953 950 - move a single changeset to the stable branch::
954 951
955 952 hg rebase -r 5f493448 -d stable
956 953
957 954 - splice a commit and all its descendants onto another part of history::
958 955
959 956 hg rebase --source c0c3 --dest 4cf9
960 957
961 958 - rebase everything on a branch marked by a bookmark onto the
962 959 default branch::
963 960
964 961 hg rebase --base myfeature --dest default
965 962
966 963 - collapse a sequence of changes into a single commit::
967 964
968 965 hg rebase --collapse -r 1520:1525 -d .
969 966
970 967 - move a named branch while preserving its name::
971 968
972 969 hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
973 970
974 971 - stabilize orphaned changesets so history looks linear::
975 972
976 973 hg rebase -r 'orphan()-obsolete()'\
977 974 -d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
978 975 max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
979 976
980 977 Configuration Options:
981 978
982 979 You can make rebase require a destination if you set the following config
983 980 option::
984 981
985 982 [commands]
986 983 rebase.requiredest = True
987 984
988 985 By default, rebase will close the transaction after each commit. For
989 986 performance purposes, you can configure rebase to use a single transaction
990 987 across the entire rebase. WARNING: This setting introduces a significant
991 988 risk of losing the work you've done in a rebase if the rebase aborts
992 989 unexpectedly::
993 990
994 991 [rebase]
995 992 singletransaction = True
996 993
997 994 By default, rebase writes to the working copy, but you can configure it to
998 995 run in-memory for better performance. When the rebase is not moving the
999 996 parent(s) of the working copy (AKA the "currently checked out changesets"),
1000 997 this may also allow it to run even if the working copy is dirty::
1001 998
1002 999 [rebase]
1003 1000 experimental.inmemory = True
1004 1001
1005 1002 Return Values:
1006 1003
1007 1004 Returns 0 on success, 1 if nothing to rebase or there are
1008 1005 unresolved conflicts.
1009 1006
1010 1007 """
1011 1008 opts = pycompat.byteskwargs(opts)
1012 1009 inmemory = ui.configbool(b'rebase', b'experimental.inmemory')
1013 1010 action = cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
1014 1011 if action:
1015 1012 cmdutil.check_incompatible_arguments(
1016 1013 opts, action, [b'confirm', b'dry_run']
1017 1014 )
1018 1015 cmdutil.check_incompatible_arguments(
1019 1016 opts, action, [b'rev', b'source', b'base', b'dest']
1020 1017 )
1021 1018 cmdutil.check_at_most_one_arg(opts, b'confirm', b'dry_run')
1022 1019 cmdutil.check_at_most_one_arg(opts, b'rev', b'source', b'base')
1023 1020
1024 1021 if action or repo.currenttransaction() is not None:
1025 1022 # in-memory rebase is not compatible with resuming rebases.
1026 1023 # (Or if it is run within a transaction, since the restart logic can
1027 1024 # fail the entire transaction.)
1028 1025 inmemory = False
1029 1026
1030 1027 if opts.get(b'auto_orphans'):
1031 1028 disallowed_opts = set(opts) - {b'auto_orphans'}
1032 1029 cmdutil.check_incompatible_arguments(
1033 1030 opts, b'auto_orphans', disallowed_opts
1034 1031 )
1035 1032
1036 1033 userrevs = list(repo.revs(opts.get(b'auto_orphans')))
1037 1034 opts[b'rev'] = [revsetlang.formatspec(b'%ld and orphan()', userrevs)]
1038 1035 opts[b'dest'] = b'_destautoorphanrebase(SRC)'
1039 1036
1040 1037 if opts.get(b'dry_run') or opts.get(b'confirm'):
1041 1038 return _dryrunrebase(ui, repo, action, opts)
1042 1039 elif action == b'stop':
1043 1040 rbsrt = rebaseruntime(repo, ui)
1044 1041 with repo.wlock(), repo.lock():
1045 1042 rbsrt.restorestatus()
1046 1043 if rbsrt.collapsef:
1047 1044 raise error.Abort(_(b"cannot stop in --collapse session"))
1048 1045 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1049 1046 if not (rbsrt.keepf or allowunstable):
1050 1047 raise error.Abort(
1051 1048 _(
1052 1049 b"cannot remove original changesets with"
1053 1050 b" unrebased descendants"
1054 1051 ),
1055 1052 hint=_(
1056 1053 b'either enable obsmarkers to allow unstable '
1057 1054 b'revisions or use --keep to keep original '
1058 1055 b'changesets'
1059 1056 ),
1060 1057 )
1061 1058 # update to the current working revision
1062 1059 # to clear interrupted merge
1063 1060 hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
1064 1061 rbsrt._finishrebase()
1065 1062 return 0
1066 1063 elif inmemory:
1067 1064 try:
1068 1065 # in-memory merge doesn't support conflicts, so if we hit any, abort
1069 1066 # and re-run as an on-disk merge.
1070 1067 overrides = {(b'rebase', b'singletransaction'): True}
1071 1068 with ui.configoverride(overrides, b'rebase'):
1072 1069 return _dorebase(ui, repo, action, opts, inmemory=inmemory)
1073 1070 except error.InMemoryMergeConflictsError:
1074 1071 ui.warn(
1075 1072 _(
1076 1073 b'hit merge conflicts; re-running rebase without in-memory'
1077 1074 b' merge\n'
1078 1075 )
1079 1076 )
1080 1077 # TODO: Make in-memory merge not use the on-disk merge state, so
1081 1078 # we don't have to clean it here
1082 1079 mergemod.mergestate.clean(repo)
1083 1080 clearstatus(repo)
1084 1081 clearcollapsemsg(repo)
1085 1082 return _dorebase(ui, repo, action, opts, inmemory=False)
1086 1083 else:
1087 1084 return _dorebase(ui, repo, action, opts)
1088 1085
1089 1086
1090 1087 def _dryrunrebase(ui, repo, action, opts):
1091 1088 rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
1092 1089 confirm = opts.get(b'confirm')
1093 1090 if confirm:
1094 1091 ui.status(_(b'starting in-memory rebase\n'))
1095 1092 else:
1096 1093 ui.status(
1097 1094 _(b'starting dry-run rebase; repository will not be changed\n')
1098 1095 )
1099 1096 with repo.wlock(), repo.lock():
1100 1097 needsabort = True
1101 1098 try:
1102 1099 overrides = {(b'rebase', b'singletransaction'): True}
1103 1100 with ui.configoverride(overrides, b'rebase'):
1104 1101 _origrebase(
1105 1102 ui,
1106 1103 repo,
1107 1104 action,
1108 1105 opts,
1109 1106 rbsrt,
1110 1107 inmemory=True,
1111 1108 leaveunfinished=True,
1112 1109 )
1113 1110 except error.InMemoryMergeConflictsError:
1114 1111 ui.status(_(b'hit a merge conflict\n'))
1115 1112 return 1
1116 1113 except error.Abort:
1117 1114 needsabort = False
1118 1115 raise
1119 1116 else:
1120 1117 if confirm:
1121 1118 ui.status(_(b'rebase completed successfully\n'))
1122 1119 if not ui.promptchoice(_(b'apply changes (yn)?$$ &Yes $$ &No')):
1123 1120 # finish unfinished rebase
1124 1121 rbsrt._finishrebase()
1125 1122 else:
1126 1123 rbsrt._prepareabortorcontinue(
1127 1124 isabort=True, backup=False, suppwarns=True
1128 1125 )
1129 1126 needsabort = False
1130 1127 else:
1131 1128 ui.status(
1132 1129 _(
1133 1130 b'dry-run rebase completed successfully; run without'
1134 1131 b' -n/--dry-run to perform this rebase\n'
1135 1132 )
1136 1133 )
1137 1134 return 0
1138 1135 finally:
1139 1136 if needsabort:
1140 1137 # no need to store backup in case of dryrun
1141 1138 rbsrt._prepareabortorcontinue(
1142 1139 isabort=True, backup=False, suppwarns=True
1143 1140 )
1144 1141
1145 1142
1146 1143 def _dorebase(ui, repo, action, opts, inmemory=False):
1147 1144 rbsrt = rebaseruntime(repo, ui, inmemory, opts)
1148 1145 return _origrebase(ui, repo, action, opts, rbsrt, inmemory=inmemory)
1149 1146
1150 1147
1151 1148 def _origrebase(
1152 1149 ui, repo, action, opts, rbsrt, inmemory=False, leaveunfinished=False
1153 1150 ):
1154 1151 assert action != b'stop'
1155 1152 with repo.wlock(), repo.lock():
1156 1153 if opts.get(b'interactive'):
1157 1154 try:
1158 1155 if extensions.find(b'histedit'):
1159 1156 enablehistedit = b''
1160 1157 except KeyError:
1161 1158 enablehistedit = b" --config extensions.histedit="
1162 1159 help = b"hg%s help -e histedit" % enablehistedit
1163 1160 msg = (
1164 1161 _(
1165 1162 b"interactive history editing is supported by the "
1166 1163 b"'histedit' extension (see \"%s\")"
1167 1164 )
1168 1165 % help
1169 1166 )
1170 1167 raise error.Abort(msg)
1171 1168
1172 1169 if rbsrt.collapsemsg and not rbsrt.collapsef:
1173 1170 raise error.Abort(_(b'message can only be specified with collapse'))
1174 1171
1175 1172 if action:
1176 1173 if rbsrt.collapsef:
1177 1174 raise error.Abort(
1178 1175 _(b'cannot use collapse with continue or abort')
1179 1176 )
1180 1177 if action == b'abort' and opts.get(b'tool', False):
1181 1178 ui.warn(_(b'tool option will be ignored\n'))
1182 1179 if action == b'continue':
1183 1180 ms = mergemod.mergestate.read(repo)
1184 1181 mergeutil.checkunresolved(ms)
1185 1182
1186 1183 retcode = rbsrt._prepareabortorcontinue(
1187 1184 isabort=(action == b'abort')
1188 1185 )
1189 1186 if retcode is not None:
1190 1187 return retcode
1191 1188 else:
1192 1189 # search default destination in this space
1193 1190 # used in the 'hg pull --rebase' case, see issue 5214.
1194 1191 destspace = opts.get(b'_destspace')
1195 1192 destmap = _definedestmap(
1196 1193 ui,
1197 1194 repo,
1198 1195 inmemory,
1199 1196 opts.get(b'dest', None),
1200 1197 opts.get(b'source', None),
1201 1198 opts.get(b'base', None),
1202 1199 opts.get(b'rev', []),
1203 1200 destspace=destspace,
1204 1201 )
1205 1202 retcode = rbsrt._preparenewrebase(destmap)
1206 1203 if retcode is not None:
1207 1204 return retcode
1208 1205 storecollapsemsg(repo, rbsrt.collapsemsg)
1209 1206
1210 1207 tr = None
1211 1208
1212 1209 singletr = ui.configbool(b'rebase', b'singletransaction')
1213 1210 if singletr:
1214 1211 tr = repo.transaction(b'rebase')
1215 1212
1216 1213 # If `rebase.singletransaction` is enabled, wrap the entire operation in
1217 1214 # one transaction here. Otherwise, transactions are obtained when
1218 1215 # committing each node, which is slower but allows partial success.
1219 1216 with util.acceptintervention(tr):
1220 1217 # Same logic for the dirstate guard, except we don't create one when
1221 1218 # rebasing in-memory (it's not needed).
1222 1219 dsguard = None
1223 1220 if singletr and not inmemory:
1224 1221 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1225 1222 with util.acceptintervention(dsguard):
1226 1223 rbsrt._performrebase(tr)
1227 1224 if not leaveunfinished:
1228 1225 rbsrt._finishrebase()
1229 1226
1230 1227
1231 1228 def _definedestmap(
1232 1229 ui,
1233 1230 repo,
1234 1231 inmemory,
1235 1232 destf=None,
1236 1233 srcf=None,
1237 1234 basef=None,
1238 1235 revf=None,
1239 1236 destspace=None,
1240 1237 ):
1241 1238 """use revisions argument to define destmap {srcrev: destrev}"""
1242 1239 if revf is None:
1243 1240 revf = []
1244 1241
1245 1242 # destspace is here to work around issues with `hg pull --rebase` see
1246 1243 # issue5214 for details
1247 1244
1248 1245 cmdutil.checkunfinished(repo)
1249 1246 if not inmemory:
1250 1247 cmdutil.bailifchanged(repo)
1251 1248
1252 1249 if ui.configbool(b'commands', b'rebase.requiredest') and not destf:
1253 1250 raise error.Abort(
1254 1251 _(b'you must specify a destination'),
1255 1252 hint=_(b'use: hg rebase -d REV'),
1256 1253 )
1257 1254
1258 1255 dest = None
1259 1256
1260 1257 if revf:
1261 1258 rebaseset = scmutil.revrange(repo, revf)
1262 1259 if not rebaseset:
1263 1260 ui.status(_(b'empty "rev" revision set - nothing to rebase\n'))
1264 1261 return None
1265 1262 elif srcf:
1266 1263 src = scmutil.revrange(repo, [srcf])
1267 1264 if not src:
1268 1265 ui.status(_(b'empty "source" revision set - nothing to rebase\n'))
1269 1266 return None
1270 1267 rebaseset = repo.revs(b'(%ld)::', src) or src
1271 1268 else:
1272 1269 base = scmutil.revrange(repo, [basef or b'.'])
1273 1270 if not base:
1274 1271 ui.status(
1275 1272 _(b'empty "base" revision set - ' b"can't compute rebase set\n")
1276 1273 )
1277 1274 return None
1278 1275 if destf:
1279 1276 # --base does not support multiple destinations
1280 1277 dest = scmutil.revsingle(repo, destf)
1281 1278 else:
1282 1279 dest = repo[_destrebase(repo, base, destspace=destspace)]
1283 1280 destf = bytes(dest)
1284 1281
1285 1282 roots = [] # selected children of branching points
1286 1283 bpbase = {} # {branchingpoint: [origbase]}
1287 1284 for b in base: # group bases by branching points
1288 1285 bp = repo.revs(b'ancestor(%d, %d)', b, dest.rev()).first()
1289 1286 bpbase[bp] = bpbase.get(bp, []) + [b]
1290 1287 if None in bpbase:
1291 1288 # emulate the old behavior, showing "nothing to rebase" (a better
1292 1289 # behavior may be abort with "cannot find branching point" error)
1293 1290 bpbase.clear()
1294 1291 for bp, bs in pycompat.iteritems(bpbase): # calculate roots
1295 1292 roots += list(repo.revs(b'children(%d) & ancestors(%ld)', bp, bs))
1296 1293
1297 1294 rebaseset = repo.revs(b'%ld::', roots)
1298 1295
1299 1296 if not rebaseset:
1300 1297 # transform to list because smartsets are not comparable to
1301 1298 # lists. This should be improved to honor laziness of
1302 1299 # smartset.
1303 1300 if list(base) == [dest.rev()]:
1304 1301 if basef:
1305 1302 ui.status(
1306 1303 _(
1307 1304 b'nothing to rebase - %s is both "base"'
1308 1305 b' and destination\n'
1309 1306 )
1310 1307 % dest
1311 1308 )
1312 1309 else:
1313 1310 ui.status(
1314 1311 _(
1315 1312 b'nothing to rebase - working directory '
1316 1313 b'parent is also destination\n'
1317 1314 )
1318 1315 )
1319 1316 elif not repo.revs(b'%ld - ::%d', base, dest.rev()):
1320 1317 if basef:
1321 1318 ui.status(
1322 1319 _(
1323 1320 b'nothing to rebase - "base" %s is '
1324 1321 b'already an ancestor of destination '
1325 1322 b'%s\n'
1326 1323 )
1327 1324 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1328 1325 )
1329 1326 else:
1330 1327 ui.status(
1331 1328 _(
1332 1329 b'nothing to rebase - working '
1333 1330 b'directory parent is already an '
1334 1331 b'ancestor of destination %s\n'
1335 1332 )
1336 1333 % dest
1337 1334 )
1338 1335 else: # can it happen?
1339 1336 ui.status(
1340 1337 _(b'nothing to rebase from %s to %s\n')
1341 1338 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1342 1339 )
1343 1340 return None
1344 1341
1345 1342 if nodemod.wdirrev in rebaseset:
1346 1343 raise error.Abort(_(b'cannot rebase the working copy'))
1347 1344 rebasingwcp = repo[b'.'].rev() in rebaseset
1348 1345 ui.log(
1349 1346 b"rebase",
1350 1347 b"rebasing working copy parent: %r\n",
1351 1348 rebasingwcp,
1352 1349 rebase_rebasing_wcp=rebasingwcp,
1353 1350 )
1354 1351 if inmemory and rebasingwcp:
1355 1352 # Check these since we did not before.
1356 1353 cmdutil.checkunfinished(repo)
1357 1354 cmdutil.bailifchanged(repo)
1358 1355
1359 1356 if not destf:
1360 1357 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
1361 1358 destf = bytes(dest)
1362 1359
1363 1360 allsrc = revsetlang.formatspec(b'%ld', rebaseset)
1364 1361 alias = {b'ALLSRC': allsrc}
1365 1362
1366 1363 if dest is None:
1367 1364 try:
1368 1365 # fast path: try to resolve dest without SRC alias
1369 1366 dest = scmutil.revsingle(repo, destf, localalias=alias)
1370 1367 except error.RepoLookupError:
1371 1368 # multi-dest path: resolve dest for each SRC separately
1372 1369 destmap = {}
1373 1370 for r in rebaseset:
1374 1371 alias[b'SRC'] = revsetlang.formatspec(b'%d', r)
1375 1372 # use repo.anyrevs instead of scmutil.revsingle because we
1376 1373 # don't want to abort if destset is empty.
1377 1374 destset = repo.anyrevs([destf], user=True, localalias=alias)
1378 1375 size = len(destset)
1379 1376 if size == 1:
1380 1377 destmap[r] = destset.first()
1381 1378 elif size == 0:
1382 1379 ui.note(_(b'skipping %s - empty destination\n') % repo[r])
1383 1380 else:
1384 1381 raise error.Abort(
1385 1382 _(b'rebase destination for %s is not unique') % repo[r]
1386 1383 )
1387 1384
1388 1385 if dest is not None:
1389 1386 # single-dest case: assign dest to each rev in rebaseset
1390 1387 destrev = dest.rev()
1391 1388 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
1392 1389
1393 1390 if not destmap:
1394 1391 ui.status(_(b'nothing to rebase - empty destination\n'))
1395 1392 return None
1396 1393
1397 1394 return destmap
1398 1395
1399 1396
1400 1397 def externalparent(repo, state, destancestors):
1401 1398 """Return the revision that should be used as the second parent
1402 1399 when the revisions in state is collapsed on top of destancestors.
1403 1400 Abort if there is more than one parent.
1404 1401 """
1405 1402 parents = set()
1406 1403 source = min(state)
1407 1404 for rev in state:
1408 1405 if rev == source:
1409 1406 continue
1410 1407 for p in repo[rev].parents():
1411 1408 if p.rev() not in state and p.rev() not in destancestors:
1412 1409 parents.add(p.rev())
1413 1410 if not parents:
1414 1411 return nullrev
1415 1412 if len(parents) == 1:
1416 1413 return parents.pop()
1417 1414 raise error.Abort(
1418 1415 _(
1419 1416 b'unable to collapse on top of %d, there is more '
1420 1417 b'than one external parent: %s'
1421 1418 )
1422 1419 % (max(destancestors), b', '.join(b"%d" % p for p in sorted(parents)))
1423 1420 )
1424 1421
1425 1422
1426 1423 def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
1427 1424 '''Commit the memory changes with parents p1 and p2.
1428 1425 Return node of committed revision.'''
1429 1426 # Replicates the empty check in ``repo.commit``.
1430 1427 if wctx.isempty() and not repo.ui.configbool(b'ui', b'allowemptycommit'):
1431 1428 return None
1432 1429
1433 1430 # By convention, ``extra['branch']`` (set by extrafn) clobbers
1434 1431 # ``branch`` (used when passing ``--keepbranches``).
1435 1432 branch = None
1436 1433 if b'branch' in extra:
1437 1434 branch = extra[b'branch']
1438 1435
1439 1436 wctx.setparents(repo[p1].node(), repo[p2].node())
1440 1437 memctx = wctx.tomemctx(
1441 1438 commitmsg,
1442 1439 date=date,
1443 1440 extra=extra,
1444 1441 user=user,
1445 1442 branch=branch,
1446 1443 editor=editor,
1447 1444 )
1448 1445 commitres = repo.commitctx(memctx)
1449 1446 wctx.clean() # Might be reused
1450 1447 return commitres
1451 1448
1452 1449
1453 1450 def commitnode(repo, p1, p2, editor, extra, user, date, commitmsg):
1454 1451 '''Commit the wd changes with parents p1 and p2.
1455 1452 Return node of committed revision.'''
1456 1453 dsguard = util.nullcontextmanager()
1457 1454 if not repo.ui.configbool(b'rebase', b'singletransaction'):
1458 1455 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1459 1456 with dsguard:
1460 1457 repo.setparents(repo[p1].node(), repo[p2].node())
1461 1458
1462 1459 # Commit might fail if unresolved files exist
1463 1460 newnode = repo.commit(
1464 1461 text=commitmsg, user=user, date=date, extra=extra, editor=editor
1465 1462 )
1466 1463
1467 1464 repo.dirstate.setbranch(repo[newnode].branch())
1468 1465 return newnode
1469 1466
1470 1467
1471 def rebasenode(repo, rev, p1, base, collapse, dest, wctx):
1468 def rebasenode(repo, rev, p1, p2, base, collapse, dest, wctx):
1472 1469 """Rebase a single revision rev on top of p1 using base as merge ancestor"""
1473 1470 # Merge phase
1474 1471 # Update to destination and merge it with local
1475 1472 p1ctx = repo[p1]
1476 1473 if wctx.isinmemory():
1477 1474 wctx.setbase(p1ctx)
1478 1475 else:
1479 1476 if repo[b'.'].rev() != p1:
1480 1477 repo.ui.debug(b" update to %d:%s\n" % (p1, p1ctx))
1481 1478 mergemod.clean_update(p1ctx)
1482 1479 else:
1483 1480 repo.ui.debug(b" already in destination\n")
1484 1481 # This is, alas, necessary to invalidate workingctx's manifest cache,
1485 1482 # as well as other data we litter on it in other places.
1486 1483 wctx = repo[None]
1487 1484 repo.dirstate.write(repo.currenttransaction())
1488 1485 ctx = repo[rev]
1489 1486 repo.ui.debug(b" merge against %d:%s\n" % (rev, ctx))
1490 1487 if base is not None:
1491 1488 repo.ui.debug(b" detach base %d:%s\n" % (base, repo[base]))
1492 1489
1493 1490 # See explanation in merge.graft()
1494 1491 mergeancestor = repo.changelog.isancestor(p1ctx.node(), ctx.node())
1495 1492 stats = mergemod.update(
1496 1493 repo,
1497 1494 rev,
1498 1495 branchmerge=True,
1499 1496 force=True,
1500 1497 ancestor=base,
1501 1498 mergeancestor=mergeancestor,
1502 1499 labels=[b'dest', b'source'],
1503 1500 wc=wctx,
1504 1501 )
1502 wctx.setparents(p1ctx.node(), repo[p2].node())
1505 1503 if collapse:
1506 1504 copies.graftcopies(wctx, ctx, repo[dest])
1507 1505 else:
1508 1506 # If we're not using --collapse, we need to
1509 1507 # duplicate copies between the revision we're
1510 1508 # rebasing and its first parent.
1511 1509 copies.graftcopies(wctx, ctx, ctx.p1())
1512 1510 return stats
1513 1511
1514 1512
1515 1513 def adjustdest(repo, rev, destmap, state, skipped):
1516 1514 r"""adjust rebase destination given the current rebase state
1517 1515
1518 1516 rev is what is being rebased. Return a list of two revs, which are the
1519 1517 adjusted destinations for rev's p1 and p2, respectively. If a parent is
1520 1518 nullrev, return dest without adjustment for it.
1521 1519
1522 1520 For example, when doing rebasing B+E to F, C to G, rebase will first move B
1523 1521 to B1, and E's destination will be adjusted from F to B1.
1524 1522
1525 1523 B1 <- written during rebasing B
1526 1524 |
1527 1525 F <- original destination of B, E
1528 1526 |
1529 1527 | E <- rev, which is being rebased
1530 1528 | |
1531 1529 | D <- prev, one parent of rev being checked
1532 1530 | |
1533 1531 | x <- skipped, ex. no successor or successor in (::dest)
1534 1532 | |
1535 1533 | C <- rebased as C', different destination
1536 1534 | |
1537 1535 | B <- rebased as B1 C'
1538 1536 |/ |
1539 1537 A G <- destination of C, different
1540 1538
1541 1539 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
1542 1540 first move C to C1, G to G1, and when it's checking H, the adjusted
1543 1541 destinations will be [C1, G1].
1544 1542
1545 1543 H C1 G1
1546 1544 /| | /
1547 1545 F G |/
1548 1546 K | | -> K
1549 1547 | C D |
1550 1548 | |/ |
1551 1549 | B | ...
1552 1550 |/ |/
1553 1551 A A
1554 1552
1555 1553 Besides, adjust dest according to existing rebase information. For example,
1556 1554
1557 1555 B C D B needs to be rebased on top of C, C needs to be rebased on top
1558 1556 \|/ of D. We will rebase C first.
1559 1557 A
1560 1558
1561 1559 C' After rebasing C, when considering B's destination, use C'
1562 1560 | instead of the original C.
1563 1561 B D
1564 1562 \ /
1565 1563 A
1566 1564 """
1567 1565 # pick already rebased revs with same dest from state as interesting source
1568 1566 dest = destmap[rev]
1569 1567 source = [
1570 1568 s
1571 1569 for s, d in state.items()
1572 1570 if d > 0 and destmap[s] == dest and s not in skipped
1573 1571 ]
1574 1572
1575 1573 result = []
1576 1574 for prev in repo.changelog.parentrevs(rev):
1577 1575 adjusted = dest
1578 1576 if prev != nullrev:
1579 1577 candidate = repo.revs(b'max(%ld and (::%d))', source, prev).first()
1580 1578 if candidate is not None:
1581 1579 adjusted = state[candidate]
1582 1580 if adjusted == dest and dest in state:
1583 1581 adjusted = state[dest]
1584 1582 if adjusted == revtodo:
1585 1583 # sortsource should produce an order that makes this impossible
1586 1584 raise error.ProgrammingError(
1587 1585 b'rev %d should be rebased already at this time' % dest
1588 1586 )
1589 1587 result.append(adjusted)
1590 1588 return result
1591 1589
1592 1590
1593 1591 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
1594 1592 """
1595 1593 Abort if rebase will create divergence or rebase is noop because of markers
1596 1594
1597 1595 `rebaseobsrevs`: set of obsolete revision in source
1598 1596 `rebaseobsskipped`: set of revisions from source skipped because they have
1599 1597 successors in destination or no non-obsolete successor.
1600 1598 """
1601 1599 # Obsolete node with successors not in dest leads to divergence
1602 1600 divergenceok = ui.configbool(b'experimental', b'evolution.allowdivergence')
1603 1601 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
1604 1602
1605 1603 if divergencebasecandidates and not divergenceok:
1606 1604 divhashes = (bytes(repo[r]) for r in divergencebasecandidates)
1607 1605 msg = _(b"this rebase will cause divergences from: %s")
1608 1606 h = _(
1609 1607 b"to force the rebase please set "
1610 1608 b"experimental.evolution.allowdivergence=True"
1611 1609 )
1612 1610 raise error.Abort(msg % (b",".join(divhashes),), hint=h)
1613 1611
1614 1612
1615 1613 def successorrevs(unfi, rev):
1616 1614 """yield revision numbers for successors of rev"""
1617 1615 assert unfi.filtername is None
1618 1616 get_rev = unfi.changelog.index.get_rev
1619 1617 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
1620 1618 r = get_rev(s)
1621 1619 if r is not None:
1622 1620 yield r
1623 1621
1624 1622
1625 1623 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1626 1624 """Return new parents and optionally a merge base for rev being rebased
1627 1625
1628 1626 The destination specified by "dest" cannot always be used directly because
1629 1627 previously rebase result could affect destination. For example,
1630 1628
1631 1629 D E rebase -r C+D+E -d B
1632 1630 |/ C will be rebased to C'
1633 1631 B C D's new destination will be C' instead of B
1634 1632 |/ E's new destination will be C' instead of B
1635 1633 A
1636 1634
1637 1635 The new parents of a merge is slightly more complicated. See the comment
1638 1636 block below.
1639 1637 """
1640 1638 # use unfiltered changelog since successorrevs may return filtered nodes
1641 1639 assert repo.filtername is None
1642 1640 cl = repo.changelog
1643 1641 isancestor = cl.isancestorrev
1644 1642
1645 1643 dest = destmap[rev]
1646 1644 oldps = repo.changelog.parentrevs(rev) # old parents
1647 1645 newps = [nullrev, nullrev] # new parents
1648 1646 dests = adjustdest(repo, rev, destmap, state, skipped)
1649 1647 bases = list(oldps) # merge base candidates, initially just old parents
1650 1648
1651 1649 if all(r == nullrev for r in oldps[1:]):
1652 1650 # For non-merge changeset, just move p to adjusted dest as requested.
1653 1651 newps[0] = dests[0]
1654 1652 else:
1655 1653 # For merge changeset, if we move p to dests[i] unconditionally, both
1656 1654 # parents may change and the end result looks like "the merge loses a
1657 1655 # parent", which is a surprise. This is a limit because "--dest" only
1658 1656 # accepts one dest per src.
1659 1657 #
1660 1658 # Therefore, only move p with reasonable conditions (in this order):
1661 1659 # 1. use dest, if dest is a descendent of (p or one of p's successors)
1662 1660 # 2. use p's rebased result, if p is rebased (state[p] > 0)
1663 1661 #
1664 1662 # Comparing with adjustdest, the logic here does some additional work:
1665 1663 # 1. decide which parents will not be moved towards dest
1666 1664 # 2. if the above decision is "no", should a parent still be moved
1667 1665 # because it was rebased?
1668 1666 #
1669 1667 # For example:
1670 1668 #
1671 1669 # C # "rebase -r C -d D" is an error since none of the parents
1672 1670 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1673 1671 # A B D # B (using rule "2."), since B will be rebased.
1674 1672 #
1675 1673 # The loop tries to be not rely on the fact that a Mercurial node has
1676 1674 # at most 2 parents.
1677 1675 for i, p in enumerate(oldps):
1678 1676 np = p # new parent
1679 1677 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
1680 1678 np = dests[i]
1681 1679 elif p in state and state[p] > 0:
1682 1680 np = state[p]
1683 1681
1684 1682 # If one parent becomes an ancestor of the other, drop the ancestor
1685 1683 for j, x in enumerate(newps[:i]):
1686 1684 if x == nullrev:
1687 1685 continue
1688 1686 if isancestor(np, x): # CASE-1
1689 1687 np = nullrev
1690 1688 elif isancestor(x, np): # CASE-2
1691 1689 newps[j] = np
1692 1690 np = nullrev
1693 1691 # New parents forming an ancestor relationship does not
1694 1692 # mean the old parents have a similar relationship. Do not
1695 1693 # set bases[x] to nullrev.
1696 1694 bases[j], bases[i] = bases[i], bases[j]
1697 1695
1698 1696 newps[i] = np
1699 1697
1700 1698 # "rebasenode" updates to new p1, and the old p1 will be used as merge
1701 1699 # base. If only p2 changes, merging using unchanged p1 as merge base is
1702 1700 # suboptimal. Therefore swap parents to make the merge sane.
1703 1701 if newps[1] != nullrev and oldps[0] == newps[0]:
1704 1702 assert len(newps) == 2 and len(oldps) == 2
1705 1703 newps.reverse()
1706 1704 bases.reverse()
1707 1705
1708 1706 # No parent change might be an error because we fail to make rev a
1709 1707 # descendent of requested dest. This can happen, for example:
1710 1708 #
1711 1709 # C # rebase -r C -d D
1712 1710 # /| # None of A and B will be changed to D and rebase fails.
1713 1711 # A B D
1714 1712 if set(newps) == set(oldps) and dest not in newps:
1715 1713 raise error.Abort(
1716 1714 _(
1717 1715 b'cannot rebase %d:%s without '
1718 1716 b'moving at least one of its parents'
1719 1717 )
1720 1718 % (rev, repo[rev])
1721 1719 )
1722 1720
1723 1721 # Source should not be ancestor of dest. The check here guarantees it's
1724 1722 # impossible. With multi-dest, the initial check does not cover complex
1725 1723 # cases since we don't have abstractions to dry-run rebase cheaply.
1726 1724 if any(p != nullrev and isancestor(rev, p) for p in newps):
1727 1725 raise error.Abort(_(b'source is ancestor of destination'))
1728 1726
1729 1727 # Check if the merge will contain unwanted changes. That may happen if
1730 1728 # there are multiple special (non-changelog ancestor) merge bases, which
1731 1729 # cannot be handled well by the 3-way merge algorithm. For example:
1732 1730 #
1733 1731 # F
1734 1732 # /|
1735 1733 # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
1736 1734 # | | # as merge base, the difference between D and F will include
1737 1735 # B C # C, so the rebased F will contain C surprisingly. If "E" was
1738 1736 # |/ # chosen, the rebased F will contain B.
1739 1737 # A Z
1740 1738 #
1741 1739 # But our merge base candidates (D and E in above case) could still be
1742 1740 # better than the default (ancestor(F, Z) == null). Therefore still
1743 1741 # pick one (so choose p1 above).
1744 1742 if sum(1 for b in set(bases) if b != nullrev and b not in newps) > 1:
1745 1743 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
1746 1744 for i, base in enumerate(bases):
1747 1745 if base == nullrev or base in newps:
1748 1746 continue
1749 1747 # Revisions in the side (not chosen as merge base) branch that
1750 1748 # might contain "surprising" contents
1751 1749 other_bases = set(bases) - {base}
1752 1750 siderevs = list(
1753 1751 repo.revs(b'(%ld %% (%d+%d))', other_bases, base, dest)
1754 1752 )
1755 1753
1756 1754 # If those revisions are covered by rebaseset, the result is good.
1757 1755 # A merge in rebaseset would be considered to cover its ancestors.
1758 1756 if siderevs:
1759 1757 rebaseset = [
1760 1758 r for r, d in state.items() if d > 0 and r not in obsskipped
1761 1759 ]
1762 1760 merges = [
1763 1761 r for r in rebaseset if cl.parentrevs(r)[1] != nullrev
1764 1762 ]
1765 1763 unwanted[i] = list(
1766 1764 repo.revs(
1767 1765 b'%ld - (::%ld) - %ld', siderevs, merges, rebaseset
1768 1766 )
1769 1767 )
1770 1768
1771 1769 if any(revs is not None for revs in unwanted):
1772 1770 # Choose a merge base that has a minimal number of unwanted revs.
1773 1771 l, i = min(
1774 1772 (len(revs), i)
1775 1773 for i, revs in enumerate(unwanted)
1776 1774 if revs is not None
1777 1775 )
1778 1776
1779 1777 # The merge will include unwanted revisions. Abort now. Revisit this if
1780 1778 # we have a more advanced merge algorithm that handles multiple bases.
1781 1779 if l > 0:
1782 1780 unwanteddesc = _(b' or ').join(
1783 1781 (
1784 1782 b', '.join(b'%d:%s' % (r, repo[r]) for r in revs)
1785 1783 for revs in unwanted
1786 1784 if revs is not None
1787 1785 )
1788 1786 )
1789 1787 raise error.Abort(
1790 1788 _(b'rebasing %d:%s will include unwanted changes from %s')
1791 1789 % (rev, repo[rev], unwanteddesc)
1792 1790 )
1793 1791
1794 1792 # newps[0] should match merge base if possible. Currently, if newps[i]
1795 1793 # is nullrev, the only case is newps[i] and newps[j] (j < i), one is
1796 1794 # the other's ancestor. In that case, it's fine to not swap newps here.
1797 1795 # (see CASE-1 and CASE-2 above)
1798 1796 if i != 0:
1799 1797 if newps[i] != nullrev:
1800 1798 newps[0], newps[i] = newps[i], newps[0]
1801 1799 bases[0], bases[i] = bases[i], bases[0]
1802 1800
1803 1801 # "rebasenode" updates to new p1, use the corresponding merge base.
1804 1802 base = bases[0]
1805 1803
1806 1804 repo.ui.debug(b" future parents are %d and %d\n" % tuple(newps))
1807 1805
1808 1806 return newps[0], newps[1], base
1809 1807
1810 1808
1811 1809 def isagitpatch(repo, patchname):
1812 1810 """Return true if the given patch is in git format"""
1813 1811 mqpatch = os.path.join(repo.mq.path, patchname)
1814 1812 for line in patch.linereader(open(mqpatch, b'rb')):
1815 1813 if line.startswith(b'diff --git'):
1816 1814 return True
1817 1815 return False
1818 1816
1819 1817
1820 1818 def updatemq(repo, state, skipped, **opts):
1821 1819 """Update rebased mq patches - finalize and then import them"""
1822 1820 mqrebase = {}
1823 1821 mq = repo.mq
1824 1822 original_series = mq.fullseries[:]
1825 1823 skippedpatches = set()
1826 1824
1827 1825 for p in mq.applied:
1828 1826 rev = repo[p.node].rev()
1829 1827 if rev in state:
1830 1828 repo.ui.debug(
1831 1829 b'revision %d is an mq patch (%s), finalize it.\n'
1832 1830 % (rev, p.name)
1833 1831 )
1834 1832 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
1835 1833 else:
1836 1834 # Applied but not rebased, not sure this should happen
1837 1835 skippedpatches.add(p.name)
1838 1836
1839 1837 if mqrebase:
1840 1838 mq.finish(repo, mqrebase.keys())
1841 1839
1842 1840 # We must start import from the newest revision
1843 1841 for rev in sorted(mqrebase, reverse=True):
1844 1842 if rev not in skipped:
1845 1843 name, isgit = mqrebase[rev]
1846 1844 repo.ui.note(
1847 1845 _(b'updating mq patch %s to %d:%s\n')
1848 1846 % (name, state[rev], repo[state[rev]])
1849 1847 )
1850 1848 mq.qimport(
1851 1849 repo,
1852 1850 (),
1853 1851 patchname=name,
1854 1852 git=isgit,
1855 1853 rev=[b"%d" % state[rev]],
1856 1854 )
1857 1855 else:
1858 1856 # Rebased and skipped
1859 1857 skippedpatches.add(mqrebase[rev][0])
1860 1858
1861 1859 # Patches were either applied and rebased and imported in
1862 1860 # order, applied and removed or unapplied. Discard the removed
1863 1861 # ones while preserving the original series order and guards.
1864 1862 newseries = [
1865 1863 s
1866 1864 for s in original_series
1867 1865 if mq.guard_re.split(s, 1)[0] not in skippedpatches
1868 1866 ]
1869 1867 mq.fullseries[:] = newseries
1870 1868 mq.seriesdirty = True
1871 1869 mq.savedirty()
1872 1870
1873 1871
1874 1872 def storecollapsemsg(repo, collapsemsg):
1875 1873 """Store the collapse message to allow recovery"""
1876 1874 collapsemsg = collapsemsg or b''
1877 1875 f = repo.vfs(b"last-message.txt", b"w")
1878 1876 f.write(b"%s\n" % collapsemsg)
1879 1877 f.close()
1880 1878
1881 1879
1882 1880 def clearcollapsemsg(repo):
1883 1881 """Remove collapse message file"""
1884 1882 repo.vfs.unlinkpath(b"last-message.txt", ignoremissing=True)
1885 1883
1886 1884
1887 1885 def restorecollapsemsg(repo, isabort):
1888 1886 """Restore previously stored collapse message"""
1889 1887 try:
1890 1888 f = repo.vfs(b"last-message.txt")
1891 1889 collapsemsg = f.readline().strip()
1892 1890 f.close()
1893 1891 except IOError as err:
1894 1892 if err.errno != errno.ENOENT:
1895 1893 raise
1896 1894 if isabort:
1897 1895 # Oh well, just abort like normal
1898 1896 collapsemsg = b''
1899 1897 else:
1900 1898 raise error.Abort(_(b'missing .hg/last-message.txt for rebase'))
1901 1899 return collapsemsg
1902 1900
1903 1901
1904 1902 def clearstatus(repo):
1905 1903 """Remove the status files"""
1906 1904 # Make sure the active transaction won't write the state file
1907 1905 tr = repo.currenttransaction()
1908 1906 if tr:
1909 1907 tr.removefilegenerator(b'rebasestate')
1910 1908 repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True)
1911 1909
1912 1910
1913 1911 def sortsource(destmap):
1914 1912 """yield source revisions in an order that we only rebase things once
1915 1913
1916 1914 If source and destination overlaps, we should filter out revisions
1917 1915 depending on other revisions which hasn't been rebased yet.
1918 1916
1919 1917 Yield a sorted list of revisions each time.
1920 1918
1921 1919 For example, when rebasing A to B, B to C. This function yields [B], then
1922 1920 [A], indicating B needs to be rebased first.
1923 1921
1924 1922 Raise if there is a cycle so the rebase is impossible.
1925 1923 """
1926 1924 srcset = set(destmap)
1927 1925 while srcset:
1928 1926 srclist = sorted(srcset)
1929 1927 result = []
1930 1928 for r in srclist:
1931 1929 if destmap[r] not in srcset:
1932 1930 result.append(r)
1933 1931 if not result:
1934 1932 raise error.Abort(_(b'source and destination form a cycle'))
1935 1933 srcset -= set(result)
1936 1934 yield result
1937 1935
1938 1936
1939 1937 def buildstate(repo, destmap, collapse):
1940 1938 '''Define which revisions are going to be rebased and where
1941 1939
1942 1940 repo: repo
1943 1941 destmap: {srcrev: destrev}
1944 1942 '''
1945 1943 rebaseset = destmap.keys()
1946 1944 originalwd = repo[b'.'].rev()
1947 1945
1948 1946 # This check isn't strictly necessary, since mq detects commits over an
1949 1947 # applied patch. But it prevents messing up the working directory when
1950 1948 # a partially completed rebase is blocked by mq.
1951 1949 if b'qtip' in repo.tags():
1952 1950 mqapplied = set(repo[s.node].rev() for s in repo.mq.applied)
1953 1951 if set(destmap.values()) & mqapplied:
1954 1952 raise error.Abort(_(b'cannot rebase onto an applied mq patch'))
1955 1953
1956 1954 # Get "cycle" error early by exhausting the generator.
1957 1955 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
1958 1956 if not sortedsrc:
1959 1957 raise error.Abort(_(b'no matching revisions'))
1960 1958
1961 1959 # Only check the first batch of revisions to rebase not depending on other
1962 1960 # rebaseset. This means "source is ancestor of destination" for the second
1963 1961 # (and following) batches of revisions are not checked here. We rely on
1964 1962 # "defineparents" to do that check.
1965 1963 roots = list(repo.set(b'roots(%ld)', sortedsrc[0]))
1966 1964 if not roots:
1967 1965 raise error.Abort(_(b'no matching revisions'))
1968 1966
1969 1967 def revof(r):
1970 1968 return r.rev()
1971 1969
1972 1970 roots = sorted(roots, key=revof)
1973 1971 state = dict.fromkeys(rebaseset, revtodo)
1974 1972 emptyrebase = len(sortedsrc) == 1
1975 1973 for root in roots:
1976 1974 dest = repo[destmap[root.rev()]]
1977 1975 commonbase = root.ancestor(dest)
1978 1976 if commonbase == root:
1979 1977 raise error.Abort(_(b'source is ancestor of destination'))
1980 1978 if commonbase == dest:
1981 1979 wctx = repo[None]
1982 1980 if dest == wctx.p1():
1983 1981 # when rebasing to '.', it will use the current wd branch name
1984 1982 samebranch = root.branch() == wctx.branch()
1985 1983 else:
1986 1984 samebranch = root.branch() == dest.branch()
1987 1985 if not collapse and samebranch and dest in root.parents():
1988 1986 # mark the revision as done by setting its new revision
1989 1987 # equal to its old (current) revisions
1990 1988 state[root.rev()] = root.rev()
1991 1989 repo.ui.debug(b'source is a child of destination\n')
1992 1990 continue
1993 1991
1994 1992 emptyrebase = False
1995 1993 repo.ui.debug(b'rebase onto %s starting from %s\n' % (dest, root))
1996 1994 if emptyrebase:
1997 1995 return None
1998 1996 for rev in sorted(state):
1999 1997 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
2000 1998 # if all parents of this revision are done, then so is this revision
2001 1999 if parents and all((state.get(p) == p for p in parents)):
2002 2000 state[rev] = rev
2003 2001 return originalwd, destmap, state
2004 2002
2005 2003
2006 2004 def clearrebased(
2007 2005 ui,
2008 2006 repo,
2009 2007 destmap,
2010 2008 state,
2011 2009 skipped,
2012 2010 collapsedas=None,
2013 2011 keepf=False,
2014 2012 fm=None,
2015 2013 backup=True,
2016 2014 ):
2017 2015 """dispose of rebased revision at the end of the rebase
2018 2016
2019 2017 If `collapsedas` is not None, the rebase was a collapse whose result if the
2020 2018 `collapsedas` node.
2021 2019
2022 2020 If `keepf` is not True, the rebase has --keep set and no nodes should be
2023 2021 removed (but bookmarks still need to be moved).
2024 2022
2025 2023 If `backup` is False, no backup will be stored when stripping rebased
2026 2024 revisions.
2027 2025 """
2028 2026 tonode = repo.changelog.node
2029 2027 replacements = {}
2030 2028 moves = {}
2031 2029 stripcleanup = not obsolete.isenabled(repo, obsolete.createmarkersopt)
2032 2030
2033 2031 collapsednodes = []
2034 2032 for rev, newrev in sorted(state.items()):
2035 2033 if newrev >= 0 and newrev != rev:
2036 2034 oldnode = tonode(rev)
2037 2035 newnode = collapsedas or tonode(newrev)
2038 2036 moves[oldnode] = newnode
2039 2037 succs = None
2040 2038 if rev in skipped:
2041 2039 if stripcleanup or not repo[rev].obsolete():
2042 2040 succs = ()
2043 2041 elif collapsedas:
2044 2042 collapsednodes.append(oldnode)
2045 2043 else:
2046 2044 succs = (newnode,)
2047 2045 if succs is not None:
2048 2046 replacements[(oldnode,)] = succs
2049 2047 if collapsednodes:
2050 2048 replacements[tuple(collapsednodes)] = (collapsedas,)
2051 2049 if fm:
2052 2050 hf = fm.hexfunc
2053 2051 fl = fm.formatlist
2054 2052 fd = fm.formatdict
2055 2053 changes = {}
2056 2054 for oldns, newn in pycompat.iteritems(replacements):
2057 2055 for oldn in oldns:
2058 2056 changes[hf(oldn)] = fl([hf(n) for n in newn], name=b'node')
2059 2057 nodechanges = fd(changes, key=b"oldnode", value=b"newnodes")
2060 2058 fm.data(nodechanges=nodechanges)
2061 2059 if keepf:
2062 2060 replacements = {}
2063 2061 scmutil.cleanupnodes(repo, replacements, b'rebase', moves, backup=backup)
2064 2062
2065 2063
2066 2064 def pullrebase(orig, ui, repo, *args, **opts):
2067 2065 """Call rebase after pull if the latter has been invoked with --rebase"""
2068 2066 if opts.get('rebase'):
2069 2067 if ui.configbool(b'commands', b'rebase.requiredest'):
2070 2068 msg = _(b'rebase destination required by configuration')
2071 2069 hint = _(b'use hg pull followed by hg rebase -d DEST')
2072 2070 raise error.Abort(msg, hint=hint)
2073 2071
2074 2072 with repo.wlock(), repo.lock():
2075 2073 if opts.get('update'):
2076 2074 del opts['update']
2077 2075 ui.debug(
2078 2076 b'--update and --rebase are not compatible, ignoring '
2079 2077 b'the update flag\n'
2080 2078 )
2081 2079
2082 2080 cmdutil.checkunfinished(repo, skipmerge=True)
2083 2081 cmdutil.bailifchanged(
2084 2082 repo,
2085 2083 hint=_(
2086 2084 b'cannot pull with rebase: '
2087 2085 b'please commit or shelve your changes first'
2088 2086 ),
2089 2087 )
2090 2088
2091 2089 revsprepull = len(repo)
2092 2090 origpostincoming = commands.postincoming
2093 2091
2094 2092 def _dummy(*args, **kwargs):
2095 2093 pass
2096 2094
2097 2095 commands.postincoming = _dummy
2098 2096 try:
2099 2097 ret = orig(ui, repo, *args, **opts)
2100 2098 finally:
2101 2099 commands.postincoming = origpostincoming
2102 2100 revspostpull = len(repo)
2103 2101 if revspostpull > revsprepull:
2104 2102 # --rev option from pull conflict with rebase own --rev
2105 2103 # dropping it
2106 2104 if 'rev' in opts:
2107 2105 del opts['rev']
2108 2106 # positional argument from pull conflicts with rebase's own
2109 2107 # --source.
2110 2108 if 'source' in opts:
2111 2109 del opts['source']
2112 2110 # revsprepull is the len of the repo, not revnum of tip.
2113 2111 destspace = list(repo.changelog.revs(start=revsprepull))
2114 2112 opts['_destspace'] = destspace
2115 2113 try:
2116 2114 rebase(ui, repo, **opts)
2117 2115 except error.NoMergeDestAbort:
2118 2116 # we can maybe update instead
2119 2117 rev, _a, _b = destutil.destupdate(repo)
2120 2118 if rev == repo[b'.'].rev():
2121 2119 ui.status(_(b'nothing to rebase\n'))
2122 2120 else:
2123 2121 ui.status(_(b'nothing to rebase - updating instead\n'))
2124 2122 # not passing argument to get the bare update behavior
2125 2123 # with warning and trumpets
2126 2124 commands.update(ui, repo)
2127 2125 else:
2128 2126 if opts.get('tool'):
2129 2127 raise error.Abort(_(b'--tool can only be used with --rebase'))
2130 2128 ret = orig(ui, repo, *args, **opts)
2131 2129
2132 2130 return ret
2133 2131
2134 2132
2135 2133 def _filterobsoleterevs(repo, revs):
2136 2134 """returns a set of the obsolete revisions in revs"""
2137 2135 return set(r for r in revs if repo[r].obsolete())
2138 2136
2139 2137
2140 2138 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
2141 2139 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
2142 2140
2143 2141 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
2144 2142 obsolete nodes to be rebased given in `rebaseobsrevs`.
2145 2143
2146 2144 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
2147 2145 without a successor in destination.
2148 2146
2149 2147 `obsoleteextinctsuccessors` is a set of obsolete revisions with only
2150 2148 obsolete successors.
2151 2149 """
2152 2150 obsoletenotrebased = {}
2153 2151 obsoletewithoutsuccessorindestination = set()
2154 2152 obsoleteextinctsuccessors = set()
2155 2153
2156 2154 assert repo.filtername is None
2157 2155 cl = repo.changelog
2158 2156 get_rev = cl.index.get_rev
2159 2157 extinctrevs = set(repo.revs(b'extinct()'))
2160 2158 for srcrev in rebaseobsrevs:
2161 2159 srcnode = cl.node(srcrev)
2162 2160 # XXX: more advanced APIs are required to handle split correctly
2163 2161 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
2164 2162 # obsutil.allsuccessors includes node itself
2165 2163 successors.remove(srcnode)
2166 2164 succrevs = {get_rev(s) for s in successors}
2167 2165 succrevs.discard(None)
2168 2166 if succrevs.issubset(extinctrevs):
2169 2167 # all successors are extinct
2170 2168 obsoleteextinctsuccessors.add(srcrev)
2171 2169 if not successors:
2172 2170 # no successor
2173 2171 obsoletenotrebased[srcrev] = None
2174 2172 else:
2175 2173 dstrev = destmap[srcrev]
2176 2174 for succrev in succrevs:
2177 2175 if cl.isancestorrev(succrev, dstrev):
2178 2176 obsoletenotrebased[srcrev] = succrev
2179 2177 break
2180 2178 else:
2181 2179 # If 'srcrev' has a successor in rebase set but none in
2182 2180 # destination (which would be catched above), we shall skip it
2183 2181 # and its descendants to avoid divergence.
2184 2182 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
2185 2183 obsoletewithoutsuccessorindestination.add(srcrev)
2186 2184
2187 2185 return (
2188 2186 obsoletenotrebased,
2189 2187 obsoletewithoutsuccessorindestination,
2190 2188 obsoleteextinctsuccessors,
2191 2189 )
2192 2190
2193 2191
2194 2192 def abortrebase(ui, repo):
2195 2193 with repo.wlock(), repo.lock():
2196 2194 rbsrt = rebaseruntime(repo, ui)
2197 2195 rbsrt._prepareabortorcontinue(isabort=True)
2198 2196
2199 2197
2200 2198 def continuerebase(ui, repo):
2201 2199 with repo.wlock(), repo.lock():
2202 2200 rbsrt = rebaseruntime(repo, ui)
2203 2201 ms = mergemod.mergestate.read(repo)
2204 2202 mergeutil.checkunresolved(ms)
2205 2203 retcode = rbsrt._prepareabortorcontinue(isabort=False)
2206 2204 if retcode is not None:
2207 2205 return retcode
2208 2206 rbsrt._performrebase(None)
2209 2207 rbsrt._finishrebase()
2210 2208
2211 2209
2212 2210 def summaryhook(ui, repo):
2213 2211 if not repo.vfs.exists(b'rebasestate'):
2214 2212 return
2215 2213 try:
2216 2214 rbsrt = rebaseruntime(repo, ui, {})
2217 2215 rbsrt.restorestatus()
2218 2216 state = rbsrt.state
2219 2217 except error.RepoLookupError:
2220 2218 # i18n: column positioning for "hg summary"
2221 2219 msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n')
2222 2220 ui.write(msg)
2223 2221 return
2224 2222 numrebased = len([i for i in pycompat.itervalues(state) if i >= 0])
2225 2223 # i18n: column positioning for "hg summary"
2226 2224 ui.write(
2227 2225 _(b'rebase: %s, %s (rebase --continue)\n')
2228 2226 % (
2229 2227 ui.label(_(b'%d rebased'), b'rebase.rebased') % numrebased,
2230 2228 ui.label(_(b'%d remaining'), b'rebase.remaining')
2231 2229 % (len(state) - numrebased),
2232 2230 )
2233 2231 )
2234 2232
2235 2233
2236 2234 def uisetup(ui):
2237 2235 # Replace pull with a decorator to provide --rebase option
2238 2236 entry = extensions.wrapcommand(commands.table, b'pull', pullrebase)
2239 2237 entry[1].append(
2240 2238 (b'', b'rebase', None, _(b"rebase working directory to branch head"))
2241 2239 )
2242 2240 entry[1].append((b't', b'tool', b'', _(b"specify merge tool for rebase")))
2243 2241 cmdutil.summaryhooks.add(b'rebase', summaryhook)
2244 2242 statemod.addunfinished(
2245 2243 b'rebase',
2246 2244 fname=b'rebasestate',
2247 2245 stopflag=True,
2248 2246 continueflag=True,
2249 2247 abortfunc=abortrebase,
2250 2248 continuefunc=continuerebase,
2251 2249 )
@@ -1,34 +1,39 b''
1 1 == New Features ==
2 2
3 3 * `hg purge`/`hg clean` can now delete ignored files instead of
4 4 untracked files, with the new -i flag.
5 5
6 6 * `hg log` now defaults to using an '%' symbol for commits involved
7 7 in unresolved merge conflicts. That includes unresolved conflicts
8 8 caused by e.g. `hg update --merge` and `hg graft`. '@' still takes
9 9 precedence, so what used to be marked '@' still is.
10 10
11 11 * New `conflictlocal()` and `conflictother()` revsets return the
12 12 commits that are being merged, when there are conflicts. Also works
13 13 for conflicts caused by e.g. `hg graft`.
14 14
15 15
16 16 == New Experimental Features ==
17 17
18 18
19 19 == Bug Fixes ==
20 20
21 21
22 22 == Backwards Compatibility Changes ==
23 23
24 * When `hg rebase` pauses for merge conflict resolution, the working
25 copy will no longer have the rebased node as a second parent. You
26 can use the new `conflictparents()` revset for finding the other
27 parent during a conflict.
28
24 29
25 30 == Internal API Changes ==
26 31
27 32 * The deprecated `ui.progress()` has now been deleted. Please use
28 33 `ui.makeprogress()` instead.
29 34
30 35 * `hg.merge()` has lost its `abort` argument. Please call
31 36 `hg.abortmerge()` directly instead.
32 37
33 38 * The `*others` argument of `cmdutil.check_incompatible_arguments()`
34 39 changed from being varargs argument to being a single collection.
@@ -1,525 +1,525 b''
1 1 #testcases abortcommand abortflag
2 2 #testcases continuecommand continueflag
3 3
4 4 $ cat >> $HGRCPATH <<EOF
5 5 > [extensions]
6 6 > rebase=
7 7 >
8 8 > [phases]
9 9 > publish=False
10 10 >
11 11 > [alias]
12 12 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches}\n"
13 13 > EOF
14 14
15 15 #if abortflag
16 16 $ cat >> $HGRCPATH <<EOF
17 17 > [alias]
18 18 > abort = rebase --abort
19 19 > EOF
20 20 #endif
21 21
22 22 #if continueflag
23 23 $ cat >> $HGRCPATH <<EOF
24 24 > [alias]
25 25 > continue = rebase --continue
26 26 > EOF
27 27 #endif
28 28
29 29 $ hg init a
30 30 $ cd a
31 31
32 32 $ touch .hg/rebasestate
33 33 $ hg sum
34 34 parent: -1:000000000000 tip (empty repository)
35 35 branch: default
36 36 commit: (clean)
37 37 update: (current)
38 38 abort: .hg/rebasestate is incomplete
39 39 [255]
40 40 $ rm .hg/rebasestate
41 41
42 42 $ echo c1 > common
43 43 $ hg add common
44 44 $ hg ci -m C1
45 45
46 46 $ echo c2 >> common
47 47 $ hg ci -m C2
48 48
49 49 $ echo c3 >> common
50 50 $ hg ci -m C3
51 51
52 52 $ hg up -q -C 1
53 53
54 54 $ echo l1 >> extra
55 55 $ hg add extra
56 56 $ hg ci -m L1
57 57 created new head
58 58
59 59 $ sed -e 's/c2/l2/' common > common.new
60 60 $ mv common.new common
61 61 $ hg ci -m L2
62 62
63 63 $ hg phase --force --secret 2
64 64
65 65 $ hg tglog
66 66 @ 4:draft 'L2'
67 67 |
68 68 o 3:draft 'L1'
69 69 |
70 70 | o 2:secret 'C3'
71 71 |/
72 72 o 1:draft 'C2'
73 73 |
74 74 o 0:draft 'C1'
75 75
76 76
77 77 Conflicting rebase:
78 78
79 79 $ hg rebase -s 3 -d 2
80 80 rebasing 3:3163e20567cc "L1"
81 81 rebasing 4:46f0b057b5c0 "L2" (tip)
82 82 merging common
83 83 warning: conflicts while merging common! (edit, then use 'hg resolve --mark')
84 84 unresolved conflicts (see hg resolve, then hg rebase --continue)
85 85 [1]
86 86
87 87 Insert unsupported advisory merge record:
88 88
89 89 $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x
90 90 $ hg debugmergestate
91 91 * version 2 records
92 92 local: 3e046f2ecedb793b97ed32108086edd1a162f8bc
93 93 other: 46f0b057b5c061d276b91491c22151f78698abd2
94 94 labels:
95 95 local: dest
96 96 other: source
97 97 unrecognized entry: x advisory record
98 98 file extras: common (ancestorlinknode = 3163e20567cc93074fbb7a53c8b93312e59dbf2c)
99 99 file: common (record type "F", state "u", hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1)
100 100 local path: common (flags "")
101 101 ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6)
102 102 other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5)
103 103 $ hg resolve -l
104 104 U common
105 105
106 106 Insert unsupported mandatory merge record:
107 107
108 108 $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X
109 109 $ hg debugmergestate
110 110 * version 2 records
111 111 local: 3e046f2ecedb793b97ed32108086edd1a162f8bc
112 112 other: 46f0b057b5c061d276b91491c22151f78698abd2
113 113 labels:
114 114 local: dest
115 115 other: source
116 116 file extras: common (ancestorlinknode = 3163e20567cc93074fbb7a53c8b93312e59dbf2c)
117 117 file: common (record type "F", state "u", hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1)
118 118 local path: common (flags "")
119 119 ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6)
120 120 other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5)
121 121 unrecognized entry: X mandatory record
122 122 $ hg resolve -l
123 123 abort: unsupported merge state records: X
124 124 (see https://mercurial-scm.org/wiki/MergeStateRecords for more information)
125 125 [255]
126 126 $ hg resolve -ma
127 127 abort: unsupported merge state records: X
128 128 (see https://mercurial-scm.org/wiki/MergeStateRecords for more information)
129 129 [255]
130 130
131 131 Abort (should clear out unsupported merge state):
132 132
133 133 #if abortcommand
134 134 when in dry-run mode
135 135 $ hg abort --dry-run
136 136 rebase in progress, will be aborted
137 137 #endif
138 138
139 139 $ hg abort
140 140 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3e046f2ecedb-6beef7d5-backup.hg
141 141 rebase aborted
142 142 $ hg debugmergestate
143 143 no merge state found
144 144
145 145 $ hg tglog
146 146 @ 4:draft 'L2'
147 147 |
148 148 o 3:draft 'L1'
149 149 |
150 150 | o 2:secret 'C3'
151 151 |/
152 152 o 1:draft 'C2'
153 153 |
154 154 o 0:draft 'C1'
155 155
156 156 Test safety for inconsistent rebase state, which may be created (and
157 157 forgotten) by Mercurial earlier than 2.7. This emulates Mercurial
158 158 earlier than 2.7 by renaming ".hg/rebasestate" temporarily.
159 159
160 160 $ hg rebase -s 3 -d 2
161 161 rebasing 3:3163e20567cc "L1"
162 162 rebasing 4:46f0b057b5c0 "L2" (tip)
163 163 merging common
164 164 warning: conflicts while merging common! (edit, then use 'hg resolve --mark')
165 165 unresolved conflicts (see hg resolve, then hg rebase --continue)
166 166 [1]
167 167
168 168 $ mv .hg/rebasestate .hg/rebasestate.back
169 169 $ hg update --quiet --clean 2
170 170 $ hg --config extensions.mq= strip --quiet "destination()"
171 171 $ mv .hg/rebasestate.back .hg/rebasestate
172 172
173 173 $ hg continue
174 174 abort: cannot continue inconsistent rebase
175 175 (use "hg rebase --abort" to clear broken state)
176 176 [255]
177 177 $ hg summary | grep '^rebase: '
178 178 rebase: (use "hg rebase --abort" to clear broken state)
179 179 $ hg abort
180 180 rebase aborted (no revision is removed, only broken state is cleared)
181 181
182 182 $ cd ..
183 183
184 184
185 185 Construct new repo:
186 186
187 187 $ hg init b
188 188 $ cd b
189 189
190 190 $ echo a > a
191 191 $ hg ci -Am A
192 192 adding a
193 193
194 194 $ echo b > b
195 195 $ hg ci -Am B
196 196 adding b
197 197
198 198 $ echo c > c
199 199 $ hg ci -Am C
200 200 adding c
201 201
202 202 $ hg up -q 0
203 203
204 204 $ echo b > b
205 205 $ hg ci -Am 'B bis'
206 206 adding b
207 207 created new head
208 208
209 209 $ echo c1 > c
210 210 $ hg ci -Am C1
211 211 adding c
212 212
213 213 $ hg phase --force --secret 1
214 214 $ hg phase --public 1
215 215
216 216 Rebase and abort without generating new changesets:
217 217
218 218 $ hg tglog
219 219 @ 4:draft 'C1'
220 220 |
221 221 o 3:draft 'B bis'
222 222 |
223 223 | o 2:secret 'C'
224 224 | |
225 225 | o 1:public 'B'
226 226 |/
227 227 o 0:public 'A'
228 228
229 229 $ hg rebase -b 4 -d 2
230 230 rebasing 3:a6484957d6b9 "B bis"
231 231 note: not rebasing 3:a6484957d6b9 "B bis", its destination already has all its changes
232 232 rebasing 4:145842775fec "C1" (tip)
233 233 merging c
234 234 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
235 235 unresolved conflicts (see hg resolve, then hg rebase --continue)
236 236 [1]
237 237
238 238 $ hg tglog
239 @ 4:draft 'C1'
239 % 4:draft 'C1'
240 240 |
241 241 o 3:draft 'B bis'
242 242 |
243 243 | @ 2:secret 'C'
244 244 | |
245 245 | o 1:public 'B'
246 246 |/
247 247 o 0:public 'A'
248 248
249 249 $ hg rebase -a
250 250 rebase aborted
251 251
252 252 $ hg tglog
253 253 @ 4:draft 'C1'
254 254 |
255 255 o 3:draft 'B bis'
256 256 |
257 257 | o 2:secret 'C'
258 258 | |
259 259 | o 1:public 'B'
260 260 |/
261 261 o 0:public 'A'
262 262
263 263
264 264 $ cd ..
265 265
266 266 rebase abort should not leave working copy in a merge state if tip-1 is public
267 267 (issue4082)
268 268
269 269 $ hg init abortpublic
270 270 $ cd abortpublic
271 271 $ echo a > a && hg ci -Aqm a
272 272 $ hg book master
273 273 $ hg book foo
274 274 $ echo b > b && hg ci -Aqm b
275 275 $ hg up -q master
276 276 $ echo c > c && hg ci -Aqm c
277 277 $ hg phase -p -r .
278 278 $ hg up -q foo
279 279 $ echo C > c && hg ci -Aqm C
280 280 $ hg log -G --template "{rev} {desc} {bookmarks}"
281 281 @ 3 C foo
282 282 |
283 283 | o 2 c master
284 284 | |
285 285 o | 1 b
286 286 |/
287 287 o 0 a
288 288
289 289
290 290 $ hg rebase -d master -r foo
291 291 rebasing 3:6c0f977a22d8 "C" (foo tip)
292 292 merging c
293 293 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
294 294 unresolved conflicts (see hg resolve, then hg rebase --continue)
295 295 [1]
296 296 $ hg abort
297 297 rebase aborted
298 298 $ hg log -G --template "{rev} {desc} {bookmarks}"
299 299 @ 3 C foo
300 300 |
301 301 | o 2 c master
302 302 | |
303 303 o | 1 b
304 304 |/
305 305 o 0 a
306 306
307 307 $ cd ..
308 308
309 309 Make sure we don't clobber changes in the working directory when the
310 310 user has somehow managed to update to a different revision (issue4009)
311 311
312 312 $ hg init noupdate
313 313 $ cd noupdate
314 314 $ hg book @
315 315 $ echo original > a
316 316 $ hg add a
317 317 $ hg commit -m a
318 318 $ echo x > b
319 319 $ hg add b
320 320 $ hg commit -m b1
321 321 $ hg up 0
322 322 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
323 323 (leaving bookmark @)
324 324 $ hg book foo
325 325 $ echo y > b
326 326 $ hg add b
327 327 $ hg commit -m b2
328 328 created new head
329 329
330 330 $ hg rebase -d @ -b foo --tool=internal:fail
331 331 rebasing 2:070cf4580bb5 "b2" (foo tip)
332 332 unresolved conflicts (see hg resolve, then hg rebase --continue)
333 333 [1]
334 334
335 335 $ mv .hg/rebasestate ./ # so we're allowed to hg up like in mercurial <2.6.3
336 336 $ hg up -C 0 # user does other stuff in the repo
337 337 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
338 338
339 339 $ mv rebasestate .hg/ # user upgrades to 2.7
340 340
341 341 $ echo new > a
342 342 $ hg up 1 # user gets an error saying to run hg rebase --abort
343 343 abort: rebase in progress
344 344 (use 'hg rebase --continue' or 'hg rebase --abort')
345 345 [255]
346 346
347 347 $ cat a
348 348 new
349 349 $ hg abort
350 350 rebase aborted
351 351 $ cat a
352 352 new
353 353
354 354 $ cd ..
355 355
356 356 test aborting an interrupted series (issue5084)
357 357 $ hg init interrupted
358 358 $ cd interrupted
359 359 $ touch base
360 360 $ hg add base
361 361 $ hg commit -m base
362 362 $ touch a
363 363 $ hg add a
364 364 $ hg commit -m a
365 365 $ echo 1 > a
366 366 $ hg commit -m 1
367 367 $ touch b
368 368 $ hg add b
369 369 $ hg commit -m b
370 370 $ echo 2 >> a
371 371 $ hg commit -m c
372 372 $ touch d
373 373 $ hg add d
374 374 $ hg commit -m d
375 375 $ hg co -q 1
376 376 $ hg rm a
377 377 $ hg commit -m no-a
378 378 created new head
379 379 $ hg co 0
380 380 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 381 $ hg log -G --template "{rev} {desc} {bookmarks}"
382 382 o 6 no-a
383 383 |
384 384 | o 5 d
385 385 | |
386 386 | o 4 c
387 387 | |
388 388 | o 3 b
389 389 | |
390 390 | o 2 1
391 391 |/
392 392 o 1 a
393 393 |
394 394 @ 0 base
395 395
396 396 $ hg --config extensions.n=$TESTDIR/failfilemerge.py rebase -s 3 -d tip
397 397 rebasing 3:3a71550954f1 "b"
398 398 rebasing 4:e80b69427d80 "c"
399 399 abort: ^C
400 400 [255]
401 401
402 402 New operations are blocked with the correct state message
403 403
404 404 $ find .hg -name '*state' -prune | sort
405 405 .hg/dirstate
406 406 .hg/merge/state
407 407 .hg/rebasestate
408 408 .hg/undo.backup.dirstate
409 409 .hg/undo.dirstate
410 410 .hg/updatestate
411 411
412 412 $ hg rebase -s 3 -d tip
413 413 abort: rebase in progress
414 414 (use 'hg rebase --continue' or 'hg rebase --abort')
415 415 [255]
416 416 $ hg up .
417 417 abort: rebase in progress
418 418 (use 'hg rebase --continue' or 'hg rebase --abort')
419 419 [255]
420 420 $ hg up -C .
421 421 abort: rebase in progress
422 422 (use 'hg rebase --continue' or 'hg rebase --abort')
423 423 [255]
424 424
425 425 $ hg graft 3
426 426 abort: rebase in progress
427 427 (use 'hg rebase --continue' or 'hg rebase --abort')
428 428 [255]
429 429
430 430 $ hg abort
431 431 saved backup bundle to $TESTTMP/interrupted/.hg/strip-backup/3d8812cf300d-93041a90-backup.hg
432 432 rebase aborted
433 433 $ hg log -G --template "{rev} {desc} {bookmarks}"
434 434 o 6 no-a
435 435 |
436 436 | o 5 d
437 437 | |
438 438 | o 4 c
439 439 | |
440 440 | o 3 b
441 441 | |
442 442 | o 2 1
443 443 |/
444 444 o 1 a
445 445 |
446 446 @ 0 base
447 447
448 448 $ hg summary
449 449 parent: 0:df4f53cec30a
450 450 base
451 451 branch: default
452 452 commit: (clean)
453 453 update: 6 new changesets (update)
454 454 phases: 7 draft
455 455
456 456 $ cd ..
457 457 On the other hand, make sure we *do* clobber changes whenever we
458 458 haven't somehow managed to update the repo to a different revision
459 459 during a rebase (issue4661)
460 460
461 461 $ hg ini yesupdate
462 462 $ cd yesupdate
463 463 $ echo "initial data" > foo.txt
464 464 $ hg add
465 465 adding foo.txt
466 466 $ hg ci -m "initial checkin"
467 467 $ echo "change 1" > foo.txt
468 468 $ hg ci -m "change 1"
469 469 $ hg up 0
470 470 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
471 471 $ echo "conflicting change 1" > foo.txt
472 472 $ hg ci -m "conflicting 1"
473 473 created new head
474 474 $ echo "conflicting change 2" > foo.txt
475 475 $ hg ci -m "conflicting 2"
476 476
477 477 $ hg rebase -d 1 --tool 'internal:fail'
478 478 rebasing 2:e4ea5cdc9789 "conflicting 1"
479 479 unresolved conflicts (see hg resolve, then hg rebase --continue)
480 480 [1]
481 481 $ hg abort
482 482 rebase aborted
483 483 $ hg summary
484 484 parent: 3:b16646383533 tip
485 485 conflicting 2
486 486 branch: default
487 487 commit: (clean)
488 488 update: 1 new changesets, 2 branch heads (merge)
489 489 phases: 4 draft
490 490 $ cd ..
491 491
492 492 test aborting a rebase succeeds after rebasing with skipped commits onto a
493 493 public changeset (issue4896)
494 494
495 495 $ hg init succeedonpublic
496 496 $ cd succeedonpublic
497 497 $ echo 'content' > root
498 498 $ hg commit -A -m 'root' -q
499 499
500 500 set up public branch
501 501 $ echo 'content' > disappear
502 502 $ hg commit -A -m 'disappear public' -q
503 503 commit will cause merge conflict on rebase
504 504 $ echo '' > root
505 505 $ hg commit -m 'remove content public' -q
506 506 $ hg phase --public
507 507
508 508 setup the draft branch that will be rebased onto public commit
509 509 $ hg up -r 0 -q
510 510 $ echo 'content' > disappear
511 511 commit will disappear
512 512 $ hg commit -A -m 'disappear draft' -q
513 513 $ echo 'addedcontADDEDentadded' > root
514 514 commit will cause merge conflict on rebase
515 515 $ hg commit -m 'add content draft' -q
516 516
517 517 $ hg rebase -d 'public()' --tool :merge -q
518 518 note: not rebasing 3:0682fd3dabf5 "disappear draft", its destination already has all its changes
519 519 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
520 520 unresolved conflicts (see hg resolve, then hg rebase --continue)
521 521 [1]
522 522 $ hg abort
523 523 rebase aborted
524 524 $ cd ..
525 525
@@ -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" (D tip)
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 137 [255]
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" (C tip)
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 183 [255]
184 184
185 185 Rebase and collapse - E onto H:
186 186
187 187 $ hg rebase -s E --dest I --collapse # root (E) is not a merge
188 188 abort: unknown revision 'I'!
189 189 [255]
190 190
191 191 $ hg tglog
192 192 o 7: 64e264db77f0 'G'
193 193 |\
194 194 | o 6: 11abe3fb10b8 'F'
195 195 | |
196 196 | o 5: 49cb92066bfd 'E'
197 197 | |
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 B
211 211 C
212 212 E
213 213 F
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 [1]
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" (H tip)
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 389 [255]
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 407 [255]
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" (E tip)
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 487 [255]
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 "move2" (tip)
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 [255]
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 "Collapsed revision" (tip)
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 "b" (foo tip)
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 [1]
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 [1]
710 710 $ hg tglog
711 711 o 3: 63668d570d21 'C'
712 712 |
713 713 | @ 2: 82b8abf9c185 'D'
714 714 | |
715 @ | 1: f899f3910ce7 'B'
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" (C tip)
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 [1]
738 738 $ hg tglog
739 @ 3: 63668d570d21 'C'
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" (C tip)
762 762 abort: edit failed: false exited with status 1
763 763 [255]
764 764 $ hg tglog
765 765 % 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" (C tip) as 82b8abf9c185
776 776 saved backup bundle to $TESTTMP/aborted-editor/.hg/strip-backup/f899f3910ce7-7cab5e15-rebase.hg
@@ -1,501 +1,500 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}:{phase} '{desc}' {branches} {bookmarks}\n"
11 11 > EOF
12 12
13 13 $ hg init a
14 14 $ cd a
15 15 $ echo c1 >common
16 16 $ hg add common
17 17 $ hg ci -m C1
18 18
19 19 $ echo c2 >>common
20 20 $ hg ci -m C2
21 21
22 22 $ echo c3 >>common
23 23 $ hg ci -m C3
24 24
25 25 $ hg up -q -C 1
26 26
27 27 $ echo l1 >>extra
28 28 $ hg add extra
29 29 $ hg ci -m L1
30 30 created new head
31 31
32 32 $ sed -e 's/c2/l2/' common > common.new
33 33 $ mv common.new common
34 34 $ hg ci -m L2
35 35
36 36 $ echo l3 >> extra2
37 37 $ hg add extra2
38 38 $ hg ci -m L3
39 39 $ hg bookmark mybook
40 40
41 41 $ hg phase --force --secret 4
42 42
43 43 $ hg tglog
44 44 @ 5:secret 'L3' mybook
45 45 |
46 46 o 4:secret 'L2'
47 47 |
48 48 o 3:draft 'L1'
49 49 |
50 50 | o 2:draft 'C3'
51 51 |/
52 52 o 1:draft 'C2'
53 53 |
54 54 o 0:draft 'C1'
55 55
56 56 Try to call --continue:
57 57
58 58 $ hg rebase --continue
59 59 abort: no rebase in progress
60 60 [255]
61 61
62 62 Conflicting rebase:
63 63
64 64 $ hg rebase -s 3 -d 2
65 65 rebasing 3:3163e20567cc "L1"
66 66 rebasing 4:46f0b057b5c0 "L2"
67 67 merging common
68 68 warning: conflicts while merging common! (edit, then use 'hg resolve --mark')
69 69 unresolved conflicts (see hg resolve, then hg rebase --continue)
70 70 [1]
71 71
72 72 $ hg status --config commands.status.verbose=1
73 73 M common
74 74 ? common.orig
75 75 # The repository is in an unfinished *rebase* state.
76 76
77 77 # Unresolved merge conflicts:
78 78 #
79 79 # common
80 80 #
81 81 # To mark files as resolved: hg resolve --mark FILE
82 82
83 83 # To continue: hg rebase --continue
84 84 # To abort: hg rebase --abort
85 85 # To stop: hg rebase --stop
86 86
87 87
88 88 Try to continue without solving the conflict:
89 89
90 90 $ hg rebase --continue
91 91 abort: unresolved merge conflicts (see 'hg help resolve')
92 92 [255]
93 93
94 94 Conclude rebase:
95 95
96 96 $ echo 'resolved merge' >common
97 97 $ hg resolve -m common
98 98 (no more unresolved files)
99 99 continue: hg rebase --continue
100 100 $ hg rebase --continue
101 101 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
102 102 rebasing 4:46f0b057b5c0 "L2"
103 103 rebasing 5:8029388f38dc "L3" (mybook)
104 104 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3163e20567cc-5ca4656e-rebase.hg
105 105
106 106 $ hg tglog
107 107 @ 5:secret 'L3' mybook
108 108 |
109 109 o 4:secret 'L2'
110 110 |
111 111 o 3:draft 'L1'
112 112 |
113 113 o 2:draft 'C3'
114 114 |
115 115 o 1:draft 'C2'
116 116 |
117 117 o 0:draft 'C1'
118 118
119 119 Check correctness:
120 120
121 121 $ hg cat -r 0 common
122 122 c1
123 123
124 124 $ hg cat -r 1 common
125 125 c1
126 126 c2
127 127
128 128 $ hg cat -r 2 common
129 129 c1
130 130 c2
131 131 c3
132 132
133 133 $ hg cat -r 3 common
134 134 c1
135 135 c2
136 136 c3
137 137
138 138 $ hg cat -r 4 common
139 139 resolved merge
140 140
141 141 $ hg cat -r 5 common
142 142 resolved merge
143 143
144 144 Bookmark stays active after --continue
145 145 $ hg bookmarks
146 146 * mybook 5:d67b21408fc0
147 147
148 148 $ cd ..
149 149
150 150 Check that the right ancestors is used while rebasing a merge (issue4041)
151 151
152 152 $ hg init issue4041
153 153 $ cd issue4041
154 154 $ hg unbundle "$TESTDIR/bundles/issue4041.hg"
155 155 adding changesets
156 156 adding manifests
157 157 adding file changes
158 158 added 11 changesets with 8 changes to 3 files (+1 heads)
159 159 new changesets 24797d4f68de:2f2496ddf49d (11 drafts)
160 160 (run 'hg heads' to see heads)
161 161 $ hg up default
162 162 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 163 $ hg log -G
164 164 o changeset: 10:2f2496ddf49d
165 165 |\ branch: f1
166 166 | | tag: tip
167 167 | | parent: 7:4c9fbe56a16f
168 168 | | parent: 9:e31216eec445
169 169 | | user: szhang
170 170 | | date: Thu Sep 05 12:59:39 2013 -0400
171 171 | | summary: merge
172 172 | |
173 173 | o changeset: 9:e31216eec445
174 174 | | branch: f1
175 175 | | user: szhang
176 176 | | date: Thu Sep 05 12:59:10 2013 -0400
177 177 | | summary: more changes to f1
178 178 | |
179 179 | o changeset: 8:8e4e2c1a07ae
180 180 | |\ branch: f1
181 181 | | | parent: 2:4bc80088dc6b
182 182 | | | parent: 6:400110238667
183 183 | | | user: szhang
184 184 | | | date: Thu Sep 05 12:57:59 2013 -0400
185 185 | | | summary: bad merge
186 186 | | |
187 187 o | | changeset: 7:4c9fbe56a16f
188 188 |/ / branch: f1
189 189 | | parent: 2:4bc80088dc6b
190 190 | | user: szhang
191 191 | | date: Thu Sep 05 12:54:00 2013 -0400
192 192 | | summary: changed f1
193 193 | |
194 194 | o changeset: 6:400110238667
195 195 | | branch: f2
196 196 | | parent: 4:12e8ec6bb010
197 197 | | user: szhang
198 198 | | date: Tue Sep 03 13:58:02 2013 -0400
199 199 | | summary: changed f2 on f2
200 200 | |
201 201 | | @ changeset: 5:d79e2059b5c0
202 202 | | | parent: 3:8a951942e016
203 203 | | | user: szhang
204 204 | | | date: Tue Sep 03 13:57:39 2013 -0400
205 205 | | | summary: changed f2 on default
206 206 | | |
207 207 | o | changeset: 4:12e8ec6bb010
208 208 | |/ branch: f2
209 209 | | user: szhang
210 210 | | date: Tue Sep 03 13:57:18 2013 -0400
211 211 | | summary: created f2 branch
212 212 | |
213 213 | o changeset: 3:8a951942e016
214 214 | | parent: 0:24797d4f68de
215 215 | | user: szhang
216 216 | | date: Tue Sep 03 13:57:11 2013 -0400
217 217 | | summary: added f2.txt
218 218 | |
219 219 o | changeset: 2:4bc80088dc6b
220 220 | | branch: f1
221 221 | | user: szhang
222 222 | | date: Tue Sep 03 13:56:20 2013 -0400
223 223 | | summary: added f1.txt
224 224 | |
225 225 o | changeset: 1:ef53c9e6b608
226 226 |/ branch: f1
227 227 | user: szhang
228 228 | date: Tue Sep 03 13:55:26 2013 -0400
229 229 | summary: created f1 branch
230 230 |
231 231 o changeset: 0:24797d4f68de
232 232 user: szhang
233 233 date: Tue Sep 03 13:55:08 2013 -0400
234 234 summary: added default.txt
235 235
236 236 $ hg rebase -s9 -d2 --debug # use debug to really check merge base used
237 237 rebase onto 4bc80088dc6b starting from e31216eec445
238 238 rebasing on disk
239 239 rebase status stored
240 240 rebasing 9:e31216eec445 "more changes to f1"
241 241 future parents are 2 and -1
242 242 update to 2:4bc80088dc6b
243 243 resolving manifests
244 244 branchmerge: False, force: True, partial: False
245 245 ancestor: d79e2059b5c0+, local: d79e2059b5c0+, remote: 4bc80088dc6b
246 246 f2.txt: other deleted -> r
247 247 removing f2.txt
248 248 f1.txt: remote created -> g
249 249 getting f1.txt
250 250 merge against 9:e31216eec445
251 251 detach base 8:8e4e2c1a07ae
252 252 resolving manifests
253 253 branchmerge: True, force: True, partial: False
254 254 ancestor: 8e4e2c1a07ae, local: 4bc80088dc6b+, remote: e31216eec445
255 255 f1.txt: remote is newer -> g
256 256 getting f1.txt
257 257 committing files:
258 258 f1.txt
259 259 committing manifest
260 260 committing changelog
261 261 updating the branch cache
262 262 rebased as 19c888675e13
263 263 rebase status stored
264 264 rebasing 10:2f2496ddf49d "merge" (tip)
265 265 future parents are 11 and 7
266 266 already in destination
267 267 merge against 10:2f2496ddf49d
268 268 detach base 9:e31216eec445
269 269 resolving manifests
270 270 branchmerge: True, force: True, partial: False
271 271 ancestor: e31216eec445, local: 19c888675e13+, remote: 2f2496ddf49d
272 272 f1.txt: remote is newer -> g
273 273 getting f1.txt
274 274 committing files:
275 275 f1.txt
276 276 committing manifest
277 277 committing changelog
278 278 updating the branch cache
279 279 rebased as 2a7f09cac94c
280 280 rebase status stored
281 281 rebase merging completed
282 282 update back to initial working directory parent
283 283 resolving manifests
284 284 branchmerge: False, force: False, partial: False
285 285 ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0
286 286 f1.txt: other deleted -> r
287 287 removing f1.txt
288 288 f2.txt: remote created -> g
289 289 getting f2.txt
290 290 2 changesets found
291 291 list of changesets:
292 292 e31216eec445e44352c5f01588856059466a24c9
293 293 2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2
294 294 bundle2-output-bundle: "HG20", (1 params) 3 parts total
295 295 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
296 296 bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
297 297 bundle2-output-part: "phase-heads" 24 bytes payload
298 298 saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-15f7a814-rebase.hg
299 299 3 changesets found
300 300 list of changesets:
301 301 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
302 302 19c888675e133ab5dff84516926a65672eaf04d9
303 303 2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf
304 304 bundle2-output-bundle: "HG20", 3 parts total
305 305 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
306 306 bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
307 307 bundle2-output-part: "phase-heads" 24 bytes payload
308 308 adding branch
309 309 bundle2-input-bundle: with-transaction
310 310 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
311 311 adding changesets
312 312 add changeset 4c9fbe56a16f
313 313 add changeset 19c888675e13
314 314 add changeset 2a7f09cac94c
315 315 adding manifests
316 316 adding file changes
317 317 adding f1.txt revisions
318 318 bundle2-input-part: total payload size 1686
319 319 bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
320 320 bundle2-input-part: total payload size 74
321 321 truncating cache/rbc-revs-v1 to 56
322 322 bundle2-input-part: "phase-heads" supported
323 323 bundle2-input-part: total payload size 24
324 324 bundle2-input-bundle: 3 parts total
325 325 added 2 changesets with 2 changes to 1 files
326 326 updating the branch cache
327 327 invalid branch cache (served): tip differs
328 328 invalid branch cache (served.hidden): tip differs
329 329 rebase completed
330 330
331 331 Test minimization of merge conflicts
332 332 $ hg up -q null
333 333 $ echo a > a
334 334 $ hg add a
335 335 $ hg commit -q -m 'a'
336 336 $ echo b >> a
337 337 $ hg commit -q -m 'ab'
338 338 $ hg bookmark ab
339 339 $ hg up -q '.^'
340 340 $ echo b >> a
341 341 $ echo c >> a
342 342 $ hg commit -q -m 'abc'
343 343 $ hg rebase -s 7bc217434fc1 -d ab --keep
344 344 rebasing 13:7bc217434fc1 "abc" (tip)
345 345 merging a
346 346 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
347 347 unresolved conflicts (see hg resolve, then hg rebase --continue)
348 348 [1]
349 349 $ hg diff
350 350 diff -r 328e4ab1f7cc a
351 351 --- a/a Thu Jan 01 00:00:00 1970 +0000
352 352 +++ b/a * (glob)
353 353 @@ -1,2 +1,6 @@
354 354 a
355 355 b
356 356 +<<<<<<< dest: 328e4ab1f7cc ab - test: ab
357 357 +=======
358 358 +c
359 359 +>>>>>>> source: 7bc217434fc1 - test: abc
360 360 $ hg rebase --abort
361 361 rebase aborted
362 362 $ hg up -q -C 7bc217434fc1
363 363 $ hg rebase -s . -d ab --keep -t internal:merge3
364 364 rebasing 13:7bc217434fc1 "abc" (tip)
365 365 merging a
366 366 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
367 367 unresolved conflicts (see hg resolve, then hg rebase --continue)
368 368 [1]
369 369 $ hg diff
370 370 diff -r 328e4ab1f7cc a
371 371 --- a/a Thu Jan 01 00:00:00 1970 +0000
372 372 +++ b/a * (glob)
373 373 @@ -1,2 +1,8 @@
374 374 a
375 375 +<<<<<<< dest: 328e4ab1f7cc ab - test: ab
376 376 b
377 377 +||||||| base
378 378 +=======
379 379 +b
380 380 +c
381 381 +>>>>>>> source: 7bc217434fc1 - test: abc
382 382
383 383 Test rebase with obsstore turned on and off (issue5606)
384 384
385 385 $ cd $TESTTMP
386 386 $ hg init b
387 387 $ cd b
388 388 $ hg debugdrawdag <<'EOS'
389 389 > D
390 390 > |
391 391 > C
392 392 > |
393 393 > B E
394 394 > |/
395 395 > A
396 396 > EOS
397 397
398 398 $ hg update E -q
399 399 $ echo 3 > B
400 400 $ hg commit --amend -m E -A B -q
401 401 $ hg rebase -r B+D -d . --config experimental.evolution=true
402 402 rebasing 1:112478962961 "B" (B)
403 403 merging B
404 404 warning: conflicts while merging B! (edit, then use 'hg resolve --mark')
405 405 unresolved conflicts (see hg resolve, then hg rebase --continue)
406 406 [1]
407 407
408 408 $ echo 4 > B
409 409 $ hg resolve -m
410 410 (no more unresolved files)
411 411 continue: hg rebase --continue
412 412 $ hg rebase --continue --config experimental.evolution=none
413 413 rebasing 1:112478962961 "B" (B)
414 414 rebasing 3:f585351a92f8 "D" (D)
415 415 warning: orphaned descendants detected, not stripping 112478962961
416 416 saved backup bundle to $TESTTMP/b/.hg/strip-backup/f585351a92f8-e536a9e4-rebase.hg
417 417
418 418 $ rm .hg/localtags
419 419 $ hg tglog
420 420 o 5:draft 'D'
421 421 |
422 422 o 4:draft 'B'
423 423 |
424 424 @ 3:draft 'E'
425 425 |
426 426 | o 2:draft 'C'
427 427 | |
428 428 | o 1:draft 'B'
429 429 |/
430 430 o 0:draft 'A'
431 431
432 432
433 433 Test where the conflict happens when rebasing a merge commit
434 434
435 435 $ cd $TESTTMP
436 436 $ hg init conflict-in-merge
437 437 $ cd conflict-in-merge
438 438 $ hg debugdrawdag <<'EOS'
439 439 > F # F/conflict = foo\n
440 440 > |\
441 441 > D E
442 442 > |/
443 443 > C B # B/conflict = bar\n
444 444 > |/
445 445 > A
446 446 > EOS
447 447
448 448 $ hg co F
449 449 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
450 450 $ hg rebase -d B
451 451 rebasing 2:dc0947a82db8 "C" (C)
452 452 rebasing 3:e7b3f00ed42e "D" (D)
453 453 rebasing 4:03ca77807e91 "E" (E)
454 454 rebasing 5:9a6b91dc2044 "F" (F tip)
455 455 merging conflict
456 456 warning: conflicts while merging conflict! (edit, then use 'hg resolve --mark')
457 457 unresolved conflicts (see hg resolve, then hg rebase --continue)
458 458 [1]
459 The current parents are not 7 and 8 even though that's what we're merging
460 459 $ hg tglog
461 460 @ 8:draft 'E'
462 461 |
463 | o 7:draft 'D'
462 | @ 7:draft 'D'
464 463 |/
465 464 o 6:draft 'C'
466 465 |
467 | @ 5:draft 'F'
466 | % 5:draft 'F'
468 467 | |\
469 468 | | o 4:draft 'E'
470 469 | | |
471 470 | o | 3:draft 'D'
472 471 | |/
473 472 | o 2:draft 'C'
474 473 | |
475 474 o | 1:draft 'B'
476 475 |/
477 476 o 0:draft 'A'
478 477
479 478 $ echo baz > conflict
480 479 $ hg resolve -m
481 480 (no more unresolved files)
482 481 continue: hg rebase --continue
483 482 $ hg rebase -c
484 483 already rebased 2:dc0947a82db8 "C" (C) as 0199610c343e
485 484 already rebased 3:e7b3f00ed42e "D" (D) as f0dd538aaa63
486 485 already rebased 4:03ca77807e91 "E" (E) as cbf25af8347d
487 486 rebasing 5:9a6b91dc2044 "F" (F)
488 487 saved backup bundle to $TESTTMP/conflict-in-merge/.hg/strip-backup/dc0947a82db8-ca7e7d5b-rebase.hg
489 488 $ hg tglog
490 489 @ 5:draft 'F'
491 490 |\
492 491 | o 4:draft 'E'
493 492 | |
494 493 o | 3:draft 'D'
495 494 |/
496 495 o 2:draft 'C'
497 496 |
498 497 o 1:draft 'B'
499 498 |
500 499 o 0:draft 'A'
501 500
@@ -1,480 +1,480 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 > tglogp = log -G --template "{rev}: {node|short} {phase} '{desc}' {branches}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16
17 17 $ echo A > A
18 18 $ hg ci -Am A
19 19 adding A
20 20
21 21 $ echo B > B
22 22 $ hg ci -Am B
23 23 adding B
24 24
25 25 $ echo C >> A
26 26 $ hg ci -m C
27 27
28 28 $ hg up -q -C 0
29 29
30 30 $ echo D >> A
31 31 $ hg ci -m D
32 32 created new head
33 33
34 34 $ echo E > E
35 35 $ hg ci -Am E
36 36 adding E
37 37
38 38 $ cd ..
39 39
40 40
41 41 Changes during an interruption - continue:
42 42
43 43 $ hg clone -q -u . a a1
44 44 $ cd a1
45 45
46 46 $ hg tglog
47 47 @ 4: ae36e8e3dfd7 'E'
48 48 |
49 49 o 3: 46b37eabc604 'D'
50 50 |
51 51 | o 2: 965c486023db 'C'
52 52 | |
53 53 | o 1: 27547f69f254 'B'
54 54 |/
55 55 o 0: 4a2df7238c3b 'A'
56 56
57 57 Rebasing B onto E:
58 58
59 59 $ hg rebase -s 1 -d 4
60 60 rebasing 1:27547f69f254 "B"
61 61 rebasing 2:965c486023db "C"
62 62 merging A
63 63 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
64 64 unresolved conflicts (see hg resolve, then hg rebase --continue)
65 65 [1]
66 66
67 67 Force a commit on C during the interruption:
68 68
69 69 $ hg up -q -C 2 --config 'extensions.rebase=!'
70 70
71 71 $ echo 'Extra' > Extra
72 72 $ hg add Extra
73 73 $ hg ci -m 'Extra' --config 'extensions.rebase=!'
74 74
75 75 Force this commit onto secret phase
76 76
77 77 $ hg phase --force --secret 6
78 78
79 79 $ hg tglogp
80 80 @ 6: deb5d2f93d8b secret 'Extra'
81 81 |
82 82 | o 5: 45396c49d53b draft 'B'
83 83 | |
84 84 | o 4: ae36e8e3dfd7 draft 'E'
85 85 | |
86 86 | o 3: 46b37eabc604 draft 'D'
87 87 | |
88 88 o | 2: 965c486023db draft 'C'
89 89 | |
90 90 o | 1: 27547f69f254 draft 'B'
91 91 |/
92 92 o 0: 4a2df7238c3b draft 'A'
93 93
94 94 Resume the rebasing:
95 95
96 96 $ hg rebase --continue
97 97 already rebased 1:27547f69f254 "B" as 45396c49d53b
98 98 rebasing 2:965c486023db "C"
99 99 merging A
100 100 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
101 101 unresolved conflicts (see hg resolve, then hg rebase --continue)
102 102 [1]
103 103
104 104 Solve the conflict and go on:
105 105
106 106 $ echo 'conflict solved' > A
107 107 $ rm A.orig
108 108 $ hg resolve -m A
109 109 (no more unresolved files)
110 110 continue: hg rebase --continue
111 111
112 112 $ hg rebase --continue
113 113 already rebased 1:27547f69f254 "B" as 45396c49d53b
114 114 rebasing 2:965c486023db "C"
115 115 warning: orphaned descendants detected, not stripping 27547f69f254, 965c486023db
116 116
117 117 $ hg tglogp
118 118 o 7: d2d25e26288e draft 'C'
119 119 |
120 120 | o 6: deb5d2f93d8b secret 'Extra'
121 121 | |
122 122 o | 5: 45396c49d53b draft 'B'
123 123 | |
124 124 @ | 4: ae36e8e3dfd7 draft 'E'
125 125 | |
126 126 o | 3: 46b37eabc604 draft 'D'
127 127 | |
128 128 | o 2: 965c486023db draft 'C'
129 129 | |
130 130 | o 1: 27547f69f254 draft 'B'
131 131 |/
132 132 o 0: 4a2df7238c3b draft 'A'
133 133
134 134 $ cd ..
135 135
136 136
137 137 Changes during an interruption - abort:
138 138
139 139 $ hg clone -q -u . a a2
140 140 $ cd a2
141 141
142 142 $ hg tglog
143 143 @ 4: ae36e8e3dfd7 'E'
144 144 |
145 145 o 3: 46b37eabc604 'D'
146 146 |
147 147 | o 2: 965c486023db 'C'
148 148 | |
149 149 | o 1: 27547f69f254 'B'
150 150 |/
151 151 o 0: 4a2df7238c3b 'A'
152 152
153 153 Rebasing B onto E:
154 154
155 155 $ hg rebase -s 1 -d 4
156 156 rebasing 1:27547f69f254 "B"
157 157 rebasing 2:965c486023db "C"
158 158 merging A
159 159 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
160 160 unresolved conflicts (see hg resolve, then hg rebase --continue)
161 161 [1]
162 162
163 163 Force a commit on B' during the interruption:
164 164
165 165 $ hg up -q -C 5 --config 'extensions.rebase=!'
166 166
167 167 $ echo 'Extra' > Extra
168 168 $ hg add Extra
169 169 $ hg ci -m 'Extra' --config 'extensions.rebase=!'
170 170
171 171 $ hg tglog
172 172 @ 6: 402ee3642b59 'Extra'
173 173 |
174 174 o 5: 45396c49d53b 'B'
175 175 |
176 176 o 4: ae36e8e3dfd7 'E'
177 177 |
178 178 o 3: 46b37eabc604 'D'
179 179 |
180 180 | o 2: 965c486023db 'C'
181 181 | |
182 182 | o 1: 27547f69f254 'B'
183 183 |/
184 184 o 0: 4a2df7238c3b 'A'
185 185
186 186 Abort the rebasing:
187 187
188 188 $ hg rebase --abort
189 189 warning: new changesets detected on destination branch, can't strip
190 190 rebase aborted
191 191
192 192 $ hg tglog
193 193 @ 6: 402ee3642b59 'Extra'
194 194 |
195 195 o 5: 45396c49d53b 'B'
196 196 |
197 197 o 4: ae36e8e3dfd7 'E'
198 198 |
199 199 o 3: 46b37eabc604 'D'
200 200 |
201 201 | o 2: 965c486023db 'C'
202 202 | |
203 203 | o 1: 27547f69f254 'B'
204 204 |/
205 205 o 0: 4a2df7238c3b 'A'
206 206
207 207 $ cd ..
208 208
209 209 Changes during an interruption - abort (again):
210 210
211 211 $ hg clone -q -u . a a3
212 212 $ cd a3
213 213
214 214 $ hg tglogp
215 215 @ 4: ae36e8e3dfd7 draft 'E'
216 216 |
217 217 o 3: 46b37eabc604 draft 'D'
218 218 |
219 219 | o 2: 965c486023db draft 'C'
220 220 | |
221 221 | o 1: 27547f69f254 draft 'B'
222 222 |/
223 223 o 0: 4a2df7238c3b draft 'A'
224 224
225 225 Rebasing B onto E:
226 226
227 227 $ hg rebase -s 1 -d 4
228 228 rebasing 1:27547f69f254 "B"
229 229 rebasing 2:965c486023db "C"
230 230 merging A
231 231 warning: conflicts while merging A! (edit, then use 'hg resolve --mark')
232 232 unresolved conflicts (see hg resolve, then hg rebase --continue)
233 233 [1]
234 234
235 235 Change phase on B and B'
236 236
237 237 $ hg up -q -C 5 --config 'extensions.rebase=!'
238 238 $ hg phase --public 1
239 239 $ hg phase --public 5
240 240 $ hg phase --secret -f 2
241 241
242 242 $ hg tglogp
243 243 @ 5: 45396c49d53b public 'B'
244 244 |
245 245 o 4: ae36e8e3dfd7 public 'E'
246 246 |
247 247 o 3: 46b37eabc604 public 'D'
248 248 |
249 249 | o 2: 965c486023db secret 'C'
250 250 | |
251 251 | o 1: 27547f69f254 public 'B'
252 252 |/
253 253 o 0: 4a2df7238c3b public 'A'
254 254
255 255 Abort the rebasing:
256 256
257 257 $ hg rebase --abort
258 258 warning: can't clean up public changesets 45396c49d53b
259 259 rebase aborted
260 260
261 261 $ hg tglogp
262 262 @ 5: 45396c49d53b public 'B'
263 263 |
264 264 o 4: ae36e8e3dfd7 public 'E'
265 265 |
266 266 o 3: 46b37eabc604 public 'D'
267 267 |
268 268 | o 2: 965c486023db secret 'C'
269 269 | |
270 270 | o 1: 27547f69f254 public 'B'
271 271 |/
272 272 o 0: 4a2df7238c3b public 'A'
273 273
274 274 Test rebase interrupted by hooks
275 275
276 276 $ hg up 2
277 277 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
278 278 $ echo F > F
279 279 $ hg add F
280 280 $ hg ci -m F
281 281
282 282 $ cd ..
283 283
284 284 (precommit version)
285 285
286 286 $ cp -R a3 hook-precommit
287 287 $ cd hook-precommit
288 288 $ hg rebase --source 2 --dest 5 --tool internal:other --config 'hooks.precommit=hg status | grep "M A"'
289 289 rebasing 2:965c486023db "C"
290 290 M A
291 291 rebasing 6:a0b2430ebfb8 "F" (tip)
292 292 abort: precommit hook exited with status 1
293 293 [255]
294 294 $ hg tglogp
295 295 @ 7: 401ccec5e39f secret 'C'
296 296 |
297 | @ 6: a0b2430ebfb8 secret 'F'
297 | o 6: a0b2430ebfb8 secret 'F'
298 298 | |
299 299 o | 5: 45396c49d53b public 'B'
300 300 | |
301 301 o | 4: ae36e8e3dfd7 public 'E'
302 302 | |
303 303 o | 3: 46b37eabc604 public 'D'
304 304 | |
305 305 | o 2: 965c486023db secret 'C'
306 306 | |
307 307 | o 1: 27547f69f254 public 'B'
308 308 |/
309 309 o 0: 4a2df7238c3b public 'A'
310 310
311 311 $ hg rebase --continue
312 312 already rebased 2:965c486023db "C" as 401ccec5e39f
313 313 rebasing 6:a0b2430ebfb8 "F"
314 314 saved backup bundle to $TESTTMP/hook-precommit/.hg/strip-backup/965c486023db-aa6250e7-rebase.hg
315 315 $ hg tglogp
316 316 @ 6: 6e92a149ac6b secret 'F'
317 317 |
318 318 o 5: 401ccec5e39f secret 'C'
319 319 |
320 320 o 4: 45396c49d53b public 'B'
321 321 |
322 322 o 3: ae36e8e3dfd7 public 'E'
323 323 |
324 324 o 2: 46b37eabc604 public 'D'
325 325 |
326 326 | o 1: 27547f69f254 public 'B'
327 327 |/
328 328 o 0: 4a2df7238c3b public 'A'
329 329
330 330 $ cd ..
331 331
332 332 (pretxncommit version)
333 333
334 334 $ cp -R a3 hook-pretxncommit
335 335 $ cd hook-pretxncommit
336 336 $ hg rebase --source 2 --dest 5 --tool internal:other \
337 337 > --config 'hooks.tonative.pretxncommit=True' --config 'hooks.pretxncommit=hg log -r $HG_NODE | grep "summary: C"'
338 338 rebasing 2:965c486023db "C"
339 339 summary: C
340 340 rebasing 6:a0b2430ebfb8 "F" (tip)
341 341 transaction abort!
342 342 rollback completed
343 343 abort: pretxncommit hook exited with status 1
344 344 [255]
345 345 $ hg tglogp
346 346 @ 7: 401ccec5e39f secret 'C'
347 347 |
348 | @ 6: a0b2430ebfb8 secret 'F'
348 | o 6: a0b2430ebfb8 secret 'F'
349 349 | |
350 350 o | 5: 45396c49d53b public 'B'
351 351 | |
352 352 o | 4: ae36e8e3dfd7 public 'E'
353 353 | |
354 354 o | 3: 46b37eabc604 public 'D'
355 355 | |
356 356 | o 2: 965c486023db secret 'C'
357 357 | |
358 358 | o 1: 27547f69f254 public 'B'
359 359 |/
360 360 o 0: 4a2df7238c3b public 'A'
361 361
362 362 $ hg rebase --continue
363 363 already rebased 2:965c486023db "C" as 401ccec5e39f
364 364 rebasing 6:a0b2430ebfb8 "F"
365 365 saved backup bundle to $TESTTMP/hook-pretxncommit/.hg/strip-backup/965c486023db-aa6250e7-rebase.hg
366 366 $ hg tglogp
367 367 @ 6: 6e92a149ac6b secret 'F'
368 368 |
369 369 o 5: 401ccec5e39f secret 'C'
370 370 |
371 371 o 4: 45396c49d53b public 'B'
372 372 |
373 373 o 3: ae36e8e3dfd7 public 'E'
374 374 |
375 375 o 2: 46b37eabc604 public 'D'
376 376 |
377 377 | o 1: 27547f69f254 public 'B'
378 378 |/
379 379 o 0: 4a2df7238c3b public 'A'
380 380
381 381 $ cd ..
382 382
383 383 (pretxnclose version)
384 384
385 385 $ cp -R a3 hook-pretxnclose
386 386 $ cd hook-pretxnclose
387 387 $ hg rebase --source 2 --dest 5 --tool internal:other --config 'hooks.pretxnclose=hg log -r tip | grep "summary: C"'
388 388 rebasing 2:965c486023db "C"
389 389 summary: C
390 390 rebasing 6:a0b2430ebfb8 "F" (tip)
391 391 transaction abort!
392 392 rollback completed
393 393 abort: pretxnclose hook exited with status 1
394 394 [255]
395 395 $ hg tglogp
396 396 @ 7: 401ccec5e39f secret 'C'
397 397 |
398 | @ 6: a0b2430ebfb8 secret 'F'
398 | o 6: a0b2430ebfb8 secret 'F'
399 399 | |
400 400 o | 5: 45396c49d53b public 'B'
401 401 | |
402 402 o | 4: ae36e8e3dfd7 public 'E'
403 403 | |
404 404 o | 3: 46b37eabc604 public 'D'
405 405 | |
406 406 | o 2: 965c486023db secret 'C'
407 407 | |
408 408 | o 1: 27547f69f254 public 'B'
409 409 |/
410 410 o 0: 4a2df7238c3b public 'A'
411 411
412 412 $ hg rebase --continue
413 413 already rebased 2:965c486023db "C" as 401ccec5e39f
414 414 rebasing 6:a0b2430ebfb8 "F"
415 415 saved backup bundle to $TESTTMP/hook-pretxnclose/.hg/strip-backup/965c486023db-aa6250e7-rebase.hg
416 416 $ hg tglogp
417 417 @ 6: 6e92a149ac6b secret 'F'
418 418 |
419 419 o 5: 401ccec5e39f secret 'C'
420 420 |
421 421 o 4: 45396c49d53b public 'B'
422 422 |
423 423 o 3: ae36e8e3dfd7 public 'E'
424 424 |
425 425 o 2: 46b37eabc604 public 'D'
426 426 |
427 427 | o 1: 27547f69f254 public 'B'
428 428 |/
429 429 o 0: 4a2df7238c3b public 'A'
430 430
431 431 $ cd ..
432 432
433 433 Make sure merge state is cleaned up after a no-op rebase merge (issue5494)
434 434 $ hg init repo
435 435 $ cd repo
436 436 $ echo a > a
437 437 $ hg commit -qAm base
438 438 $ echo b >> a
439 439 $ hg commit -qm b
440 440 $ hg up '.^'
441 441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 442 $ echo c >> a
443 443 $ hg commit -qm c
444 444 $ hg rebase -s 1 -d 2 --noninteractive
445 445 rebasing 1:fdaca8533b86 "b"
446 446 merging a
447 447 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
448 448 unresolved conflicts (see hg resolve, then hg rebase --continue)
449 449 [1]
450 450 $ echo a > a
451 451 $ echo c >> a
452 452 $ hg resolve --mark a
453 453 (no more unresolved files)
454 454 continue: hg rebase --continue
455 455 $ hg rebase --continue
456 456 rebasing 1:fdaca8533b86 "b"
457 457 note: not rebasing 1:fdaca8533b86 "b", its destination already has all its changes
458 458 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/fdaca8533b86-7fd70513-rebase.hg
459 459 $ hg resolve --list
460 460 $ test -d .hg/merge
461 461 [1]
462 462 Now try again with --collapse
463 463 $ hg unbundle -q .hg/strip-backup/fdaca8533b86-7fd70513-rebase.hg
464 464 $ hg rebase -s 2 -d 1 --noninteractive --collapse
465 465 rebasing 2:fdaca8533b86 "b" (tip)
466 466 merging a
467 467 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
468 468 unresolved conflicts (see hg resolve, then hg rebase --continue)
469 469 [1]
470 470 $ echo a > a
471 471 $ echo c >> a
472 472 $ hg resolve --mark a
473 473 (no more unresolved files)
474 474 continue: hg rebase --continue
475 475 $ hg rebase --continue
476 476 rebasing 2:fdaca8533b86 "b" (tip)
477 477 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/fdaca8533b86-7fd70513-rebase.hg
478 478 $ hg resolve --list
479 479 $ test -d .hg/merge
480 480 [1]
@@ -1,2142 +1,2138 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 > [ui]
9 9 > logtemplate= {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 "D" (tip)
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 "D" (tip)
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 [255]
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 "C" (tip)
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" (F tip)
562 562 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
563 563 [255]
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 "I" (tip)
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 "J" (tip)
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 "C" (tip)
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 "D" (tip)
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 "P" (tip)
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 "nonrelevant" (tip), 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 951 [255]
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 "bar foo" (tip)
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 [1]
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 "dummy change" (tip)
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 1155 [255]
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" (f tip)
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" (f tip)
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" (F tip)
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" (F tip)
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" (F tip)
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" (F tip)
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" (F tip)
1464 1464 note: not rebasing 5:66f1a38021c9 "F" (F tip), 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" (F tip)
1500 1500 note: not rebasing 5:66f1a38021c9 "F" (F tip), 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 1569 [255]
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" (E tip)
1587 1587 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1588 1588 [255]
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 "b" (tip)
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 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip)
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 "D1" (book D1 tip), 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 [1]
1792 1792
1793 1793 $ cp -R . $TESTTMP/hidden-state2
1794 1794
1795 1795 $ hg log -G
1796 1796 @ 2:b18e25de2cf5 D
1797 1797 |
1798 | @ 1:2ec65233581b B (pruned using prune)
1799 |/
1800 1798 o 0:426bada5c675 A
1801 1799
1802 1800 $ hg summary
1803 1801 parent: 2:b18e25de2cf5 tip
1804 1802 D
1805 parent: 1:2ec65233581b (obsolete)
1806 B
1807 1803 branch: default
1808 commit: 2 modified, 1 unknown, 1 unresolved (merge)
1804 commit: 1 modified, 1 added, 1 unknown, 1 unresolved
1809 1805 update: (current)
1810 phases: 3 draft
1806 phases: 2 draft
1811 1807 rebase: 0 rebased, 2 remaining (rebase --continue)
1812 1808
1813 1809 $ hg rebase --abort
1814 1810 rebase aborted
1815 1811
1816 1812 Also test --continue for the above case
1817 1813
1818 1814 $ cd $TESTTMP/hidden-state2
1819 1815 $ hg resolve -m
1820 1816 (no more unresolved files)
1821 1817 continue: hg rebase --continue
1822 1818 $ hg rebase --continue
1823 1819 rebasing 1:2ec65233581b "B"
1824 1820 rebasing 3:7829726be4dc "C" (tip)
1825 1821 $ hg log -G
1826 1822 @ 5:1964d5d5b547 C
1827 1823 |
1828 1824 o 4:68deb90c12a2 B
1829 1825 |
1830 1826 o 2:b18e25de2cf5 D
1831 1827 |
1832 1828 o 0:426bada5c675 A
1833 1829
1834 1830 ====================
1835 1831 Test --stop option |
1836 1832 ====================
1837 1833 $ cd ..
1838 1834 $ hg init rbstop
1839 1835 $ cd rbstop
1840 1836 $ echo a>a
1841 1837 $ hg ci -Aqma
1842 1838 $ echo b>b
1843 1839 $ hg ci -Aqmb
1844 1840 $ echo c>c
1845 1841 $ hg ci -Aqmc
1846 1842 $ echo d>d
1847 1843 $ hg ci -Aqmd
1848 1844 $ hg up 0 -q
1849 1845 $ echo f>f
1850 1846 $ hg ci -Aqmf
1851 1847 $ echo D>d
1852 1848 $ hg ci -Aqm "conflict with d"
1853 1849 $ hg up 3 -q
1854 1850 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1855 1851 o 5:00bfc9898aeb test
1856 1852 | conflict with d
1857 1853 |
1858 1854 o 4:dafd40200f93 test
1859 1855 | f
1860 1856 |
1861 1857 | @ 3:055a42cdd887 test
1862 1858 | | d
1863 1859 | |
1864 1860 | o 2:177f92b77385 test
1865 1861 | | c
1866 1862 | |
1867 1863 | o 1:d2ae7f538514 test
1868 1864 |/ b
1869 1865 |
1870 1866 o 0:cb9a9f314b8b test
1871 1867 a
1872 1868
1873 1869 $ hg rebase -s 1 -d 5
1874 1870 rebasing 1:d2ae7f538514 "b"
1875 1871 rebasing 2:177f92b77385 "c"
1876 1872 rebasing 3:055a42cdd887 "d"
1877 1873 merging d
1878 1874 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1879 1875 unresolved conflicts (see hg resolve, then hg rebase --continue)
1880 1876 [1]
1881 1877 $ hg rebase --stop
1882 1878 1 new orphan changesets
1883 1879 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1884 1880 o 7:7fffad344617 test
1885 1881 | c
1886 1882 |
1887 1883 o 6:b15528633407 test
1888 1884 | b
1889 1885 |
1890 1886 o 5:00bfc9898aeb test
1891 1887 | conflict with d
1892 1888 |
1893 1889 o 4:dafd40200f93 test
1894 1890 | f
1895 1891 |
1896 1892 | @ 3:055a42cdd887 test
1897 1893 | | d
1898 1894 | |
1899 1895 | x 2:177f92b77385 test
1900 1896 | | c
1901 1897 | |
1902 1898 | x 1:d2ae7f538514 test
1903 1899 |/ b
1904 1900 |
1905 1901 o 0:cb9a9f314b8b test
1906 1902 a
1907 1903
1908 1904 Test it aborts if unstable csets is not allowed:
1909 1905 ===============================================
1910 1906 $ cat >> $HGRCPATH << EOF
1911 1907 > [experimental]
1912 1908 > evolution.allowunstable=False
1913 1909 > EOF
1914 1910
1915 1911 $ hg strip 6 --no-backup -q
1916 1912 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1917 1913 o 5:00bfc9898aeb test
1918 1914 | conflict with d
1919 1915 |
1920 1916 o 4:dafd40200f93 test
1921 1917 | f
1922 1918 |
1923 1919 | @ 3:055a42cdd887 test
1924 1920 | | d
1925 1921 | |
1926 1922 | o 2:177f92b77385 test
1927 1923 | | c
1928 1924 | |
1929 1925 | o 1:d2ae7f538514 test
1930 1926 |/ b
1931 1927 |
1932 1928 o 0:cb9a9f314b8b test
1933 1929 a
1934 1930
1935 1931 $ hg rebase -s 1 -d 5
1936 1932 rebasing 1:d2ae7f538514 "b"
1937 1933 rebasing 2:177f92b77385 "c"
1938 1934 rebasing 3:055a42cdd887 "d"
1939 1935 merging d
1940 1936 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1941 1937 unresolved conflicts (see hg resolve, then hg rebase --continue)
1942 1938 [1]
1943 1939 $ hg rebase --stop
1944 1940 abort: cannot remove original changesets with unrebased descendants
1945 1941 (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets)
1946 1942 [255]
1947 1943 $ hg rebase --abort
1948 1944 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1949 1945 rebase aborted
1950 1946
1951 1947 Test --stop when --keep is passed:
1952 1948 ==================================
1953 1949 $ hg rebase -s 1 -d 5 --keep
1954 1950 rebasing 1:d2ae7f538514 "b"
1955 1951 rebasing 2:177f92b77385 "c"
1956 1952 rebasing 3:055a42cdd887 "d"
1957 1953 merging d
1958 1954 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1959 1955 unresolved conflicts (see hg resolve, then hg rebase --continue)
1960 1956 [1]
1961 1957 $ hg rebase --stop
1962 1958 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1963 1959 o 7:7fffad344617 test
1964 1960 | c
1965 1961 |
1966 1962 o 6:b15528633407 test
1967 1963 | b
1968 1964 |
1969 1965 o 5:00bfc9898aeb test
1970 1966 | conflict with d
1971 1967 |
1972 1968 o 4:dafd40200f93 test
1973 1969 | f
1974 1970 |
1975 1971 | @ 3:055a42cdd887 test
1976 1972 | | d
1977 1973 | |
1978 1974 | o 2:177f92b77385 test
1979 1975 | | c
1980 1976 | |
1981 1977 | o 1:d2ae7f538514 test
1982 1978 |/ b
1983 1979 |
1984 1980 o 0:cb9a9f314b8b test
1985 1981 a
1986 1982
1987 1983 Test --stop aborts when --collapse was passed:
1988 1984 =============================================
1989 1985 $ cat >> $HGRCPATH << EOF
1990 1986 > [experimental]
1991 1987 > evolution.allowunstable=True
1992 1988 > EOF
1993 1989
1994 1990 $ hg strip 6
1995 1991 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1996 1992 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1997 1993 o 5:00bfc9898aeb test
1998 1994 | conflict with d
1999 1995 |
2000 1996 o 4:dafd40200f93 test
2001 1997 | f
2002 1998 |
2003 1999 | @ 3:055a42cdd887 test
2004 2000 | | d
2005 2001 | |
2006 2002 | o 2:177f92b77385 test
2007 2003 | | c
2008 2004 | |
2009 2005 | o 1:d2ae7f538514 test
2010 2006 |/ b
2011 2007 |
2012 2008 o 0:cb9a9f314b8b test
2013 2009 a
2014 2010
2015 2011 $ hg rebase -s 1 -d 5 --collapse -m "collapsed b c d"
2016 2012 rebasing 1:d2ae7f538514 "b"
2017 2013 rebasing 2:177f92b77385 "c"
2018 2014 rebasing 3:055a42cdd887 "d"
2019 2015 merging d
2020 2016 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2021 2017 unresolved conflicts (see hg resolve, then hg rebase --continue)
2022 2018 [1]
2023 2019 $ hg rebase --stop
2024 2020 abort: cannot stop in --collapse session
2025 2021 [255]
2026 2022 $ hg rebase --abort
2027 2023 rebase aborted
2028 2024 $ hg diff
2029 2025 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
2030 2026 o 5:00bfc9898aeb test
2031 2027 | conflict with d
2032 2028 |
2033 2029 o 4:dafd40200f93 test
2034 2030 | f
2035 2031 |
2036 2032 | @ 3:055a42cdd887 test
2037 2033 | | d
2038 2034 | |
2039 2035 | o 2:177f92b77385 test
2040 2036 | | c
2041 2037 | |
2042 2038 | o 1:d2ae7f538514 test
2043 2039 |/ b
2044 2040 |
2045 2041 o 0:cb9a9f314b8b test
2046 2042 a
2047 2043
2048 2044 Test --stop raise errors with conflicting options:
2049 2045 =================================================
2050 2046 $ hg rebase -s 3 -d 5
2051 2047 rebasing 3:055a42cdd887 "d"
2052 2048 merging d
2053 2049 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2054 2050 unresolved conflicts (see hg resolve, then hg rebase --continue)
2055 2051 [1]
2056 2052 $ hg rebase --stop --dry-run
2057 2053 abort: cannot specify both --stop and --dry-run
2058 2054 [255]
2059 2055
2060 2056 $ hg rebase -s 3 -d 5
2061 2057 abort: rebase in progress
2062 2058 (use 'hg rebase --continue' or 'hg rebase --abort')
2063 2059 [255]
2064 2060 $ hg rebase --stop --continue
2065 2061 abort: cannot specify both --stop and --continue
2066 2062 [255]
2067 2063
2068 2064 Test --stop moves bookmarks of original revisions to new rebased nodes:
2069 2065 ======================================================================
2070 2066 $ cd ..
2071 2067 $ hg init repo
2072 2068 $ cd repo
2073 2069
2074 2070 $ echo a > a
2075 2071 $ hg ci -Am A
2076 2072 adding a
2077 2073
2078 2074 $ echo b > b
2079 2075 $ hg ci -Am B
2080 2076 adding b
2081 2077 $ hg book X
2082 2078 $ hg book Y
2083 2079
2084 2080 $ echo c > c
2085 2081 $ hg ci -Am C
2086 2082 adding c
2087 2083 $ hg book Z
2088 2084
2089 2085 $ echo d > d
2090 2086 $ hg ci -Am D
2091 2087 adding d
2092 2088
2093 2089 $ hg up 0 -q
2094 2090 $ echo e > e
2095 2091 $ hg ci -Am E
2096 2092 adding e
2097 2093 created new head
2098 2094
2099 2095 $ echo doubt > d
2100 2096 $ hg ci -Am "conflict with d"
2101 2097 adding d
2102 2098
2103 2099 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2104 2100 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2105 2101 |
2106 2102 o 4: 9c1e55f411b6 'E' bookmarks:
2107 2103 |
2108 2104 | o 3: 67a385d4e6f2 'D' bookmarks: Z
2109 2105 | |
2110 2106 | o 2: 49cb3485fa0c 'C' bookmarks: Y
2111 2107 | |
2112 2108 | o 1: 6c81ed0049f8 'B' bookmarks: X
2113 2109 |/
2114 2110 o 0: 1994f17a630e 'A' bookmarks:
2115 2111
2116 2112 $ hg rebase -s 1 -d 5
2117 2113 rebasing 1:6c81ed0049f8 "B" (X)
2118 2114 rebasing 2:49cb3485fa0c "C" (Y)
2119 2115 rebasing 3:67a385d4e6f2 "D" (Z)
2120 2116 merging d
2121 2117 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2122 2118 unresolved conflicts (see hg resolve, then hg rebase --continue)
2123 2119 [1]
2124 2120 $ hg rebase --stop
2125 2121 1 new orphan changesets
2126 2122 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2127 2123 o 7: 9c86c650b686 'C' bookmarks: Y
2128 2124 |
2129 2125 o 6: 9b87b54e5fd8 'B' bookmarks: X
2130 2126 |
2131 2127 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2132 2128 |
2133 2129 o 4: 9c1e55f411b6 'E' bookmarks:
2134 2130 |
2135 2131 | * 3: 67a385d4e6f2 'D' bookmarks: Z
2136 2132 | |
2137 2133 | x 2: 49cb3485fa0c 'C' bookmarks:
2138 2134 | |
2139 2135 | x 1: 6c81ed0049f8 'B' bookmarks:
2140 2136 |/
2141 2137 o 0: 1994f17a630e 'A' bookmarks:
2142 2138
@@ -1,529 +1,527 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 [255]
66 66
67 67 $ hg rebase --continue --collapse
68 68 abort: cannot use collapse with continue or abort
69 69 [255]
70 70
71 71 $ hg rebase --continue --dest 4
72 72 abort: cannot specify both --continue and --dest
73 73 [255]
74 74
75 75 $ hg rebase --base 5 --source 4
76 76 abort: cannot specify both --source and --base
77 77 [255]
78 78
79 79 $ hg rebase --rev 5 --source 4
80 80 abort: cannot specify both --rev and --source
81 81 [255]
82 82 $ hg rebase --base 5 --rev 4
83 83 abort: cannot specify both --rev and --base
84 84 [255]
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 97 [255]
98 98
99 99 $ hg rebase --source 'wdir()' --dest 6
100 100 abort: cannot rebase the working copy
101 101 [255]
102 102
103 103 $ hg rebase --source '1 & !1' --dest 8
104 104 empty "source" revision set - nothing to rebase
105 105 [1]
106 106
107 107 $ hg rebase --base '1 & !1' --dest 8
108 108 empty "base" revision set - can't compute rebase set
109 109 [1]
110 110
111 111 $ hg rebase --dest 8
112 112 nothing to rebase - working directory parent is also destination
113 113 [1]
114 114
115 115 $ hg rebase -b . --dest 8
116 116 nothing to rebase - e7ec4e813ba6 is both "base" and destination
117 117 [1]
118 118
119 119 $ hg up -q 7
120 120
121 121 $ hg rebase --dest 8 --traceback
122 122 nothing to rebase - working directory parent is already an ancestor of destination e7ec4e813ba6
123 123 [1]
124 124
125 125 $ hg rebase --dest 8 -b.
126 126 nothing to rebase - "base" 02de42196ebe is already an ancestor of destination e7ec4e813ba6
127 127 [1]
128 128
129 129 $ hg rebase --dest '1 & !1'
130 130 abort: empty revision set
131 131 [255]
132 132
133 133 These work:
134 134
135 135 Rebase with no arguments (from 3 onto 8):
136 136
137 137 $ cd ..
138 138 $ hg clone -q -u . a2heads a1
139 139 $ cd a1
140 140 $ hg up -q -C 3
141 141
142 142 $ hg rebase
143 143 rebasing 1:42ccdea3bb16 "B"
144 144 rebasing 2:5fddd98957c8 "C"
145 145 rebasing 3:32af7686d403 "D"
146 146 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
147 147
148 148 $ hg tglog
149 149 @ 6: ed65089c18f8 'D'
150 150 |
151 151 o 5: 7621bf1a2f17 'C'
152 152 |
153 153 o 4: 9430a62369c6 'B'
154 154 |
155 155 o 3: e7ec4e813ba6 'I'
156 156 |
157 157 o 2: 02de42196ebe 'H'
158 158 |
159 159 o 1: 24b6387c8c8c 'F'
160 160 |
161 161 o 0: cd010b8cd998 'A'
162 162
163 163 Try to rollback after a rebase (fail):
164 164
165 165 $ hg rollback
166 166 no rollback information available
167 167 [1]
168 168
169 169 $ cd ..
170 170
171 171 Rebase with base == '.' => same as no arguments (from 3 onto 8):
172 172
173 173 $ hg clone -q -u 3 a2heads a2
174 174 $ cd a2
175 175
176 176 $ hg rebase --base .
177 177 rebasing 1:42ccdea3bb16 "B"
178 178 rebasing 2:5fddd98957c8 "C"
179 179 rebasing 3:32af7686d403 "D"
180 180 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
181 181
182 182 $ hg tglog
183 183 @ 6: ed65089c18f8 'D'
184 184 |
185 185 o 5: 7621bf1a2f17 'C'
186 186 |
187 187 o 4: 9430a62369c6 'B'
188 188 |
189 189 o 3: e7ec4e813ba6 'I'
190 190 |
191 191 o 2: 02de42196ebe 'H'
192 192 |
193 193 o 1: 24b6387c8c8c 'F'
194 194 |
195 195 o 0: cd010b8cd998 'A'
196 196
197 197 $ cd ..
198 198
199 199
200 200 Rebase with dest == branch(.) => same as no arguments (from 3 onto 8):
201 201
202 202 $ hg clone -q -u 3 a a3
203 203 $ cd a3
204 204
205 205 $ hg rebase --dest 'branch(.)'
206 206 rebasing 1:42ccdea3bb16 "B"
207 207 rebasing 2:5fddd98957c8 "C"
208 208 rebasing 3:32af7686d403 "D"
209 209 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
210 210
211 211 $ hg tglog
212 212 @ 8: ed65089c18f8 'D'
213 213 |
214 214 o 7: 7621bf1a2f17 'C'
215 215 |
216 216 o 6: 9430a62369c6 'B'
217 217 |
218 218 o 5: e7ec4e813ba6 'I'
219 219 |
220 220 o 4: 02de42196ebe 'H'
221 221 |
222 222 | o 3: eea13746799a 'G'
223 223 |/|
224 224 o | 2: 24b6387c8c8c 'F'
225 225 | |
226 226 | o 1: 9520eea781bc 'E'
227 227 |/
228 228 o 0: cd010b8cd998 'A'
229 229
230 230 $ cd ..
231 231
232 232
233 233 Specify only source (from 2 onto 8):
234 234
235 235 $ hg clone -q -u . a2heads a4
236 236 $ cd a4
237 237
238 238 $ hg rebase --source 'desc("C")'
239 239 rebasing 2:5fddd98957c8 "C"
240 240 rebasing 3:32af7686d403 "D"
241 241 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
242 242
243 243 $ hg tglog
244 244 o 6: 7726e9fd58f7 'D'
245 245 |
246 246 o 5: 72c8333623d0 'C'
247 247 |
248 248 @ 4: e7ec4e813ba6 'I'
249 249 |
250 250 o 3: 02de42196ebe 'H'
251 251 |
252 252 o 2: 24b6387c8c8c 'F'
253 253 |
254 254 | o 1: 42ccdea3bb16 'B'
255 255 |/
256 256 o 0: cd010b8cd998 'A'
257 257
258 258 $ cd ..
259 259
260 260
261 261 Specify only dest (from 3 onto 6):
262 262
263 263 $ hg clone -q -u 3 a a5
264 264 $ cd a5
265 265
266 266 $ hg rebase --dest 6
267 267 rebasing 1:42ccdea3bb16 "B"
268 268 rebasing 2:5fddd98957c8 "C"
269 269 rebasing 3:32af7686d403 "D"
270 270 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
271 271
272 272 $ hg tglog
273 273 @ 8: 8eeb3c33ad33 'D'
274 274 |
275 275 o 7: 2327fea05063 'C'
276 276 |
277 277 o 6: e4e5be0395b2 'B'
278 278 |
279 279 | o 5: e7ec4e813ba6 'I'
280 280 | |
281 281 | o 4: 02de42196ebe 'H'
282 282 | |
283 283 o | 3: eea13746799a 'G'
284 284 |\|
285 285 | o 2: 24b6387c8c8c 'F'
286 286 | |
287 287 o | 1: 9520eea781bc 'E'
288 288 |/
289 289 o 0: cd010b8cd998 'A'
290 290
291 291 $ cd ..
292 292
293 293
294 294 Specify only base (from 1 onto 8):
295 295
296 296 $ hg clone -q -u . a2heads a6
297 297 $ cd a6
298 298
299 299 $ hg rebase --base 'desc("D")'
300 300 rebasing 1:42ccdea3bb16 "B"
301 301 rebasing 2:5fddd98957c8 "C"
302 302 rebasing 3:32af7686d403 "D"
303 303 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
304 304
305 305 $ hg tglog
306 306 o 6: ed65089c18f8 'D'
307 307 |
308 308 o 5: 7621bf1a2f17 'C'
309 309 |
310 310 o 4: 9430a62369c6 'B'
311 311 |
312 312 @ 3: e7ec4e813ba6 'I'
313 313 |
314 314 o 2: 02de42196ebe 'H'
315 315 |
316 316 o 1: 24b6387c8c8c 'F'
317 317 |
318 318 o 0: cd010b8cd998 'A'
319 319
320 320 $ cd ..
321 321
322 322
323 323 Specify source and dest (from 2 onto 7):
324 324
325 325 $ hg clone -q -u . a a7
326 326 $ cd a7
327 327
328 328 $ hg rebase --source 2 --dest 7
329 329 rebasing 2:5fddd98957c8 "C"
330 330 rebasing 3:32af7686d403 "D"
331 331 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
332 332
333 333 $ hg tglog
334 334 o 8: 668acadedd30 'D'
335 335 |
336 336 o 7: 09eb682ba906 'C'
337 337 |
338 338 | @ 6: e7ec4e813ba6 'I'
339 339 |/
340 340 o 5: 02de42196ebe 'H'
341 341 |
342 342 | o 4: eea13746799a 'G'
343 343 |/|
344 344 o | 3: 24b6387c8c8c 'F'
345 345 | |
346 346 | o 2: 9520eea781bc 'E'
347 347 |/
348 348 | o 1: 42ccdea3bb16 'B'
349 349 |/
350 350 o 0: cd010b8cd998 'A'
351 351
352 352 $ cd ..
353 353
354 354
355 355 Specify base and dest (from 1 onto 7):
356 356
357 357 $ hg clone -q -u . a a8
358 358 $ cd a8
359 359
360 360 $ hg rebase --base 3 --dest 7
361 361 rebasing 1:42ccdea3bb16 "B"
362 362 rebasing 2:5fddd98957c8 "C"
363 363 rebasing 3:32af7686d403 "D"
364 364 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/42ccdea3bb16-3cb021d3-rebase.hg
365 365
366 366 $ hg tglog
367 367 o 8: 287cc92ba5a4 'D'
368 368 |
369 369 o 7: 6824f610a250 'C'
370 370 |
371 371 o 6: 7c6027df6a99 'B'
372 372 |
373 373 | @ 5: e7ec4e813ba6 'I'
374 374 |/
375 375 o 4: 02de42196ebe 'H'
376 376 |
377 377 | o 3: eea13746799a 'G'
378 378 |/|
379 379 o | 2: 24b6387c8c8c 'F'
380 380 | |
381 381 | o 1: 9520eea781bc 'E'
382 382 |/
383 383 o 0: cd010b8cd998 'A'
384 384
385 385 $ cd ..
386 386
387 387
388 388 Specify only revs (from 2 onto 8)
389 389
390 390 $ hg clone -q -u . a2heads a9
391 391 $ cd a9
392 392
393 393 $ hg rebase --rev 'desc("C")::'
394 394 rebasing 2:5fddd98957c8 "C"
395 395 rebasing 3:32af7686d403 "D"
396 396 saved backup bundle to $TESTTMP/a9/.hg/strip-backup/5fddd98957c8-f9244fa1-rebase.hg
397 397
398 398 $ hg tglog
399 399 o 6: 7726e9fd58f7 'D'
400 400 |
401 401 o 5: 72c8333623d0 'C'
402 402 |
403 403 @ 4: e7ec4e813ba6 'I'
404 404 |
405 405 o 3: 02de42196ebe 'H'
406 406 |
407 407 o 2: 24b6387c8c8c 'F'
408 408 |
409 409 | o 1: 42ccdea3bb16 'B'
410 410 |/
411 411 o 0: cd010b8cd998 'A'
412 412
413 413 $ cd ..
414 414
415 415 Rebasing both a single revision and a merge in one command
416 416
417 417 $ hg clone -q -u . a aX
418 418 $ cd aX
419 419 $ hg rebase -r 3 -r 6 --dest 8
420 420 rebasing 3:32af7686d403 "D"
421 421 rebasing 6:eea13746799a "G"
422 422 saved backup bundle to $TESTTMP/aX/.hg/strip-backup/eea13746799a-ad273fd6-rebase.hg
423 423 $ cd ..
424 424
425 425 Test --tool parameter:
426 426
427 427 $ hg init b
428 428 $ cd b
429 429
430 430 $ echo c1 > c1
431 431 $ hg ci -Am c1
432 432 adding c1
433 433
434 434 $ echo c2 > c2
435 435 $ hg ci -Am c2
436 436 adding c2
437 437
438 438 $ hg up -q 0
439 439 $ echo c2b > c2
440 440 $ hg ci -Am c2b
441 441 adding c2
442 442 created new head
443 443
444 444 $ cd ..
445 445
446 446 $ hg clone -q -u . b b1
447 447 $ cd b1
448 448
449 449 $ hg rebase -s 2 -d 1 --tool internal:local
450 450 rebasing 2:e4e3f3546619 "c2b" (tip)
451 451 note: not rebasing 2:e4e3f3546619 "c2b" (tip), its destination already has all its changes
452 452 saved backup bundle to $TESTTMP/b1/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg
453 453
454 454 $ hg cat c2
455 455 c2
456 456
457 457 $ cd ..
458 458
459 459
460 460 $ hg clone -q -u . b b2
461 461 $ cd b2
462 462
463 463 $ hg rebase -s 2 -d 1 --tool internal:other
464 464 rebasing 2:e4e3f3546619 "c2b" (tip)
465 465 saved backup bundle to $TESTTMP/b2/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg
466 466
467 467 $ hg cat c2
468 468 c2b
469 469
470 470 $ cd ..
471 471
472 472
473 473 $ hg clone -q -u . b b3
474 474 $ cd b3
475 475
476 476 $ hg rebase -s 2 -d 1 --tool internal:fail
477 477 rebasing 2:e4e3f3546619 "c2b" (tip)
478 478 unresolved conflicts (see hg resolve, then hg rebase --continue)
479 479 [1]
480 480
481 481 $ hg summary
482 482 parent: 1:56daeba07f4b
483 483 c2
484 parent: 2:e4e3f3546619 tip
485 c2b
486 484 branch: default
487 commit: 1 modified, 1 unresolved (merge)
488 update: (current)
485 commit: 1 unresolved (clean)
486 update: 1 new changesets, 2 branch heads (merge)
489 487 phases: 3 draft
490 488 rebase: 0 rebased, 1 remaining (rebase --continue)
491 489
492 490 $ hg resolve -l
493 491 U c2
494 492
495 493 $ hg resolve -m c2
496 494 (no more unresolved files)
497 495 continue: hg rebase --continue
498 496 $ hg graft --continue
499 497 abort: no graft in progress
500 498 (continue: hg rebase --continue)
501 499 [255]
502 500 $ hg rebase -c --tool internal:fail
503 501 rebasing 2:e4e3f3546619 "c2b" (tip)
504 502 note: not rebasing 2:e4e3f3546619 "c2b" (tip), its destination already has all its changes
505 503 saved backup bundle to $TESTTMP/b3/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg
506 504
507 505 $ hg rebase -i
508 506 abort: interactive history editing is supported by the 'histedit' extension (see "hg --config extensions.histedit= help -e histedit")
509 507 [255]
510 508
511 509 $ hg rebase --interactive
512 510 abort: interactive history editing is supported by the 'histedit' extension (see "hg --config extensions.histedit= help -e histedit")
513 511 [255]
514 512
515 513 $ cd ..
516 514
517 515 No common ancestor
518 516
519 517 $ hg init separaterepo
520 518 $ cd separaterepo
521 519 $ touch a
522 520 $ hg commit -Aqm a
523 521 $ hg up -q null
524 522 $ touch b
525 523 $ hg commit -Aqm b
526 524 $ hg rebase -d 0
527 525 nothing to rebase from d7486e00c6f1 to 3903775176ed
528 526 [1]
529 527 $ cd ..
@@ -1,204 +1,204 b''
1 1 #testcases continuecommand continueflag
2 2 Rebasing using a single transaction
3 3
4 4 $ cat >> $HGRCPATH <<EOF
5 5 > [extensions]
6 6 > rebase=
7 7 > drawdag=$TESTDIR/drawdag.py
8 8 >
9 9 > [rebase]
10 10 > singletransaction=True
11 11 >
12 12 > [phases]
13 13 > publish=False
14 14 >
15 15 > [alias]
16 16 > tglog = log -G --template "{rev}: {desc}"
17 17 > EOF
18 18
19 19 #if continueflag
20 20 $ cat >> $HGRCPATH <<EOF
21 21 > [alias]
22 22 > continue = rebase --continue
23 23 > EOF
24 24 #endif
25 25
26 26 Check that a simple rebase works
27 27
28 28 $ hg init simple && cd simple
29 29 $ hg debugdrawdag <<'EOF'
30 30 > Z
31 31 > |
32 32 > | D
33 33 > | |
34 34 > | C
35 35 > | |
36 36 > Y B
37 37 > |/
38 38 > A
39 39 > EOF
40 40 - We should only see one status stored message. It comes from the start.
41 41 $ hg rebase --debug -b D -d Z | grep 'status stored'
42 42 rebase status stored
43 43 $ hg tglog
44 44 o 5: D
45 45 |
46 46 o 4: C
47 47 |
48 48 o 3: B
49 49 |
50 50 o 2: Z
51 51 |
52 52 o 1: Y
53 53 |
54 54 o 0: A
55 55
56 56 $ cd ..
57 57
58 58 Check that --collapse works
59 59
60 60 $ hg init collapse && cd collapse
61 61 $ hg debugdrawdag <<'EOF'
62 62 > Z
63 63 > |
64 64 > | D
65 65 > | |
66 66 > | C
67 67 > | |
68 68 > Y B
69 69 > |/
70 70 > A
71 71 > EOF
72 72 - We should only see two status stored messages. One from the start, one from
73 73 - cmdutil.commitforceeditor() which forces tr.writepending()
74 74 $ hg rebase --collapse --debug -b D -d Z | grep 'status stored'
75 75 rebase status stored
76 76 rebase status stored
77 77 $ hg tglog
78 78 o 3: Collapsed revision
79 79 | * B
80 80 | * C
81 81 | * D
82 82 o 2: Z
83 83 |
84 84 o 1: Y
85 85 |
86 86 o 0: A
87 87
88 88 $ cd ..
89 89
90 90 With --collapse, check that conflicts can be resolved and rebase can then be
91 91 continued
92 92
93 93 $ hg init collapse-conflict && cd collapse-conflict
94 94 $ hg debugdrawdag <<'EOF'
95 95 > Z # Z/conflict=Z
96 96 > |
97 97 > | D
98 98 > | |
99 99 > | C # C/conflict=C
100 100 > | |
101 101 > Y B
102 102 > |/
103 103 > A
104 104 > EOF
105 105 $ hg rebase --collapse -b D -d Z
106 106 rebasing 1:112478962961 "B" (B)
107 107 rebasing 3:c26739dbe603 "C" (C)
108 108 merging conflict
109 109 warning: conflicts while merging conflict! (edit, then use 'hg resolve --mark')
110 110 unresolved conflicts (see hg resolve, then hg rebase --continue)
111 111 [1]
112 112 $ hg tglog
113 113 o 5: D
114 114 |
115 115 | @ 4: Z
116 116 | |
117 @ | 3: C
117 % | 3: C
118 118 | |
119 119 | o 2: Y
120 120 | |
121 121 o | 1: B
122 122 |/
123 123 o 0: A
124 124
125 125 $ hg st
126 M C
127 126 M conflict
128 127 A B
128 A C
129 129 ? conflict.orig
130 130 $ echo resolved > conflict
131 131 $ hg resolve -m
132 132 (no more unresolved files)
133 133 continue: hg rebase --continue
134 134 $ hg continue
135 135 already rebased 1:112478962961 "B" (B) as 79bc8f4973ce
136 136 rebasing 3:c26739dbe603 "C" (C)
137 137 rebasing 5:d24bb333861c "D" (D tip)
138 138 saved backup bundle to $TESTTMP/collapse-conflict/.hg/strip-backup/112478962961-b5b34645-rebase.hg
139 139 $ hg tglog
140 140 o 3: Collapsed revision
141 141 | * B
142 142 | * C
143 143 | * D
144 144 o 2: Z
145 145 |
146 146 o 1: Y
147 147 |
148 148 o 0: A
149 149
150 150 $ cd ..
151 151
152 152 With --collapse, check that the commit message editing can be canceled and
153 153 rebase can then be continued
154 154
155 155 $ hg init collapse-cancel-editor && cd collapse-cancel-editor
156 156 $ hg debugdrawdag <<'EOF'
157 157 > Z
158 158 > |
159 159 > | D
160 160 > | |
161 161 > | C
162 162 > | |
163 163 > Y B
164 164 > |/
165 165 > A
166 166 > EOF
167 167 $ HGEDITOR=false hg --config ui.interactive=1 rebase --collapse -b D -d Z
168 168 rebasing 1:112478962961 "B" (B)
169 169 rebasing 3:26805aba1e60 "C" (C)
170 170 rebasing 5:f585351a92f8 "D" (D tip)
171 171 transaction abort!
172 172 rollback completed
173 173 abort: edit failed: false exited with status 1
174 174 [255]
175 175 $ hg tglog
176 176 o 5: D
177 177 |
178 178 | o 4: Z
179 179 | |
180 180 o | 3: C
181 181 | |
182 182 | o 2: Y
183 183 | |
184 184 o | 1: B
185 185 |/
186 186 o 0: A
187 187
188 188 $ hg continue
189 189 rebasing 1:112478962961 "B" (B)
190 190 rebasing 3:26805aba1e60 "C" (C)
191 191 rebasing 5:f585351a92f8 "D" (D tip)
192 192 saved backup bundle to $TESTTMP/collapse-cancel-editor/.hg/strip-backup/112478962961-cb2a9b47-rebase.hg
193 193 $ hg tglog
194 194 o 3: Collapsed revision
195 195 | * B
196 196 | * C
197 197 | * D
198 198 o 2: Z
199 199 |
200 200 o 1: Y
201 201 |
202 202 o 0: A
203 203
204 204 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now