##// END OF EJS Templates
rebase: switch from util.Abort to util.InterventionRequired where appropriate (bc)
Augie Fackler -
r18933:42b620fc default
parent child Browse files
Show More
@@ -1,787 +1,788 b''
1 1 # rebase.py - rebasing feature for mercurial
2 2 #
3 3 # Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''command to move sets of revisions to a different ancestor
9 9
10 10 This extension lets you rebase changesets in an existing Mercurial
11 11 repository.
12 12
13 13 For more information:
14 14 http://mercurial.selenic.com/wiki/RebaseExtension
15 15 '''
16 16
17 17 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
18 from mercurial import extensions, patch, scmutil, phases, obsolete
18 from mercurial import extensions, patch, scmutil, phases, obsolete, error
19 19 from mercurial.commands import templateopts
20 20 from mercurial.node import nullrev
21 21 from mercurial.lock import release
22 22 from mercurial.i18n import _
23 23 import os, errno
24 24
25 25 nullmerge = -2
26 26 revignored = -3
27 27
28 28 cmdtable = {}
29 29 command = cmdutil.command(cmdtable)
30 30 testedwith = 'internal'
31 31
32 32 @command('rebase',
33 33 [('s', 'source', '',
34 34 _('rebase from the specified changeset'), _('REV')),
35 35 ('b', 'base', '',
36 36 _('rebase from the base of the specified changeset '
37 37 '(up to greatest common ancestor of base and dest)'),
38 38 _('REV')),
39 39 ('r', 'rev', [],
40 40 _('rebase these revisions'),
41 41 _('REV')),
42 42 ('d', 'dest', '',
43 43 _('rebase onto the specified changeset'), _('REV')),
44 44 ('', 'collapse', False, _('collapse the rebased changesets')),
45 45 ('m', 'message', '',
46 46 _('use text as collapse commit message'), _('TEXT')),
47 47 ('e', 'edit', False, _('invoke editor on commit messages')),
48 48 ('l', 'logfile', '',
49 49 _('read collapse commit message from file'), _('FILE')),
50 50 ('', 'keep', False, _('keep original changesets')),
51 51 ('', 'keepbranches', False, _('keep original branch names')),
52 52 ('D', 'detach', False, _('(DEPRECATED)')),
53 53 ('t', 'tool', '', _('specify merge tool')),
54 54 ('c', 'continue', False, _('continue an interrupted rebase')),
55 55 ('a', 'abort', False, _('abort an interrupted rebase'))] +
56 56 templateopts,
57 57 _('[-s REV | -b REV] [-d REV] [OPTION]'))
58 58 def rebase(ui, repo, **opts):
59 59 """move changeset (and descendants) to a different branch
60 60
61 61 Rebase uses repeated merging to graft changesets from one part of
62 62 history (the source) onto another (the destination). This can be
63 63 useful for linearizing *local* changes relative to a master
64 64 development tree.
65 65
66 66 You should not rebase changesets that have already been shared
67 67 with others. Doing so will force everybody else to perform the
68 68 same rebase or they will end up with duplicated changesets after
69 69 pulling in your rebased changesets.
70 70
71 71 In its default configuration, Mercurial will prevent you from
72 72 rebasing published changes. See :hg:`help phases` for details.
73 73
74 74 If you don't specify a destination changeset (``-d/--dest``),
75 75 rebase uses the tipmost head of the current named branch as the
76 76 destination. (The destination changeset is not modified by
77 77 rebasing, but new changesets are added as its descendants.)
78 78
79 79 You can specify which changesets to rebase in two ways: as a
80 80 "source" changeset or as a "base" changeset. Both are shorthand
81 81 for a topologically related set of changesets (the "source
82 82 branch"). If you specify source (``-s/--source``), rebase will
83 83 rebase that changeset and all of its descendants onto dest. If you
84 84 specify base (``-b/--base``), rebase will select ancestors of base
85 85 back to but not including the common ancestor with dest. Thus,
86 86 ``-b`` is less precise but more convenient than ``-s``: you can
87 87 specify any changeset in the source branch, and rebase will select
88 88 the whole branch. If you specify neither ``-s`` nor ``-b``, rebase
89 89 uses the parent of the working directory as the base.
90 90
91 91 For advanced usage, a third way is available through the ``--rev``
92 92 option. It allows you to specify an arbitrary set of changesets to
93 93 rebase. Descendants of revs you specify with this option are not
94 94 automatically included in the rebase.
95 95
96 96 By default, rebase recreates the changesets in the source branch
97 97 as descendants of dest and then destroys the originals. Use
98 98 ``--keep`` to preserve the original source changesets. Some
99 99 changesets in the source branch (e.g. merges from the destination
100 100 branch) may be dropped if they no longer contribute any change.
101 101
102 102 One result of the rules for selecting the destination changeset
103 103 and source branch is that, unlike ``merge``, rebase will do
104 104 nothing if you are at the latest (tipmost) head of a named branch
105 105 with two heads. You need to explicitly specify source and/or
106 106 destination (or ``update`` to the other head, if it's the head of
107 107 the intended source branch).
108 108
109 109 If a rebase is interrupted to manually resolve a merge, it can be
110 110 continued with --continue/-c or aborted with --abort/-a.
111 111
112 112 Returns 0 on success, 1 if nothing to rebase.
113 113 """
114 114 originalwd = target = None
115 115 activebookmark = None
116 116 external = nullrev
117 117 state = {}
118 118 skipped = set()
119 119 targetancestors = set()
120 120
121 121 editor = None
122 122 if opts.get('edit'):
123 123 editor = cmdutil.commitforceeditor
124 124
125 125 lock = wlock = None
126 126 try:
127 127 wlock = repo.wlock()
128 128 lock = repo.lock()
129 129
130 130 # Validate input and define rebasing points
131 131 destf = opts.get('dest', None)
132 132 srcf = opts.get('source', None)
133 133 basef = opts.get('base', None)
134 134 revf = opts.get('rev', [])
135 135 contf = opts.get('continue')
136 136 abortf = opts.get('abort')
137 137 collapsef = opts.get('collapse', False)
138 138 collapsemsg = cmdutil.logmessage(ui, opts)
139 139 extrafn = opts.get('extrafn') # internal, used by e.g. hgsubversion
140 140 keepf = opts.get('keep', False)
141 141 keepbranchesf = opts.get('keepbranches', False)
142 142 # keepopen is not meant for use on the command line, but by
143 143 # other extensions
144 144 keepopen = opts.get('keepopen', False)
145 145
146 146 if collapsemsg and not collapsef:
147 147 raise util.Abort(
148 148 _('message can only be specified with collapse'))
149 149
150 150 if contf or abortf:
151 151 if contf and abortf:
152 152 raise util.Abort(_('cannot use both abort and continue'))
153 153 if collapsef:
154 154 raise util.Abort(
155 155 _('cannot use collapse with continue or abort'))
156 156 if srcf or basef or destf:
157 157 raise util.Abort(
158 158 _('abort and continue do not allow specifying revisions'))
159 159 if opts.get('tool', False):
160 160 ui.warn(_('tool option will be ignored\n'))
161 161
162 162 (originalwd, target, state, skipped, collapsef, keepf,
163 163 keepbranchesf, external, activebookmark) = restorestatus(repo)
164 164 if abortf:
165 165 return abort(repo, originalwd, target, state)
166 166 else:
167 167 if srcf and basef:
168 168 raise util.Abort(_('cannot specify both a '
169 169 'source and a base'))
170 170 if revf and basef:
171 171 raise util.Abort(_('cannot specify both a '
172 172 'revision and a base'))
173 173 if revf and srcf:
174 174 raise util.Abort(_('cannot specify both a '
175 175 'revision and a source'))
176 176
177 177 cmdutil.bailifchanged(repo)
178 178
179 179 if not destf:
180 180 # Destination defaults to the latest revision in the
181 181 # current branch
182 182 branch = repo[None].branch()
183 183 dest = repo[branch]
184 184 else:
185 185 dest = scmutil.revsingle(repo, destf)
186 186
187 187 if revf:
188 188 rebaseset = repo.revs('%lr', revf)
189 189 elif srcf:
190 190 src = scmutil.revrange(repo, [srcf])
191 191 rebaseset = repo.revs('(%ld)::', src)
192 192 else:
193 193 base = scmutil.revrange(repo, [basef or '.'])
194 194 rebaseset = repo.revs(
195 195 '(children(ancestor(%ld, %d)) and ::(%ld))::',
196 196 base, dest, base)
197 197 if rebaseset:
198 198 root = min(rebaseset)
199 199 else:
200 200 root = None
201 201
202 202 if not rebaseset:
203 203 repo.ui.debug('base is ancestor of destination\n')
204 204 result = None
205 205 elif (not (keepf or obsolete._enabled)
206 206 and repo.revs('first(children(%ld) - %ld)',
207 207 rebaseset, rebaseset)):
208 208 raise util.Abort(
209 209 _("can't remove original changesets with"
210 210 " unrebased descendants"),
211 211 hint=_('use --keep to keep original changesets'))
212 212 elif not keepf and not repo[root].mutable():
213 213 raise util.Abort(_("can't rebase immutable changeset %s")
214 214 % repo[root],
215 215 hint=_('see hg help phases for details'))
216 216 else:
217 217 result = buildstate(repo, dest, rebaseset, collapsef)
218 218
219 219 if not result:
220 220 # Empty state built, nothing to rebase
221 221 ui.status(_('nothing to rebase\n'))
222 222 return 1
223 223 else:
224 224 originalwd, target, state = result
225 225 if collapsef:
226 226 targetancestors = repo.changelog.ancestors([target],
227 227 inclusive=True)
228 228 external = checkexternal(repo, state, targetancestors)
229 229
230 230 if keepbranchesf:
231 231 assert not extrafn, 'cannot use both keepbranches and extrafn'
232 232 def extrafn(ctx, extra):
233 233 extra['branch'] = ctx.branch()
234 234 if collapsef:
235 235 branches = set()
236 236 for rev in state:
237 237 branches.add(repo[rev].branch())
238 238 if len(branches) > 1:
239 239 raise util.Abort(_('cannot collapse multiple named '
240 240 'branches'))
241 241
242 242
243 243 # Rebase
244 244 if not targetancestors:
245 245 targetancestors = repo.changelog.ancestors([target], inclusive=True)
246 246
247 247 # Keep track of the current bookmarks in order to reset them later
248 248 currentbookmarks = repo._bookmarks.copy()
249 249 activebookmark = activebookmark or repo._bookmarkcurrent
250 250 if activebookmark:
251 251 bookmarks.unsetcurrent(repo)
252 252
253 253 sortedstate = sorted(state)
254 254 total = len(sortedstate)
255 255 pos = 0
256 256 for rev in sortedstate:
257 257 pos += 1
258 258 if state[rev] == -1:
259 259 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])),
260 260 _('changesets'), total)
261 261 storestatus(repo, originalwd, target, state, collapsef, keepf,
262 262 keepbranchesf, external, activebookmark)
263 263 p1, p2 = defineparents(repo, rev, target, state,
264 264 targetancestors)
265 265 if len(repo.parents()) == 2:
266 266 repo.ui.debug('resuming interrupted rebase\n')
267 267 else:
268 268 try:
269 269 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
270 270 stats = rebasenode(repo, rev, p1, state, collapsef)
271 271 if stats and stats[3] > 0:
272 raise util.Abort(_('unresolved conflicts (see hg '
273 'resolve, then hg rebase --continue)'))
272 raise error.InterventionRequired(
273 _('unresolved conflicts (see hg '
274 'resolve, then hg rebase --continue)'))
274 275 finally:
275 276 ui.setconfig('ui', 'forcemerge', '')
276 277 cmdutil.duplicatecopies(repo, rev, target)
277 278 if not collapsef:
278 279 newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn,
279 280 editor=editor)
280 281 else:
281 282 # Skip commit if we are collapsing
282 283 repo.setparents(repo[p1].node())
283 284 newrev = None
284 285 # Update the state
285 286 if newrev is not None:
286 287 state[rev] = repo[newrev].rev()
287 288 else:
288 289 if not collapsef:
289 290 ui.note(_('no changes, revision %d skipped\n') % rev)
290 291 ui.debug('next revision set to %s\n' % p1)
291 292 skipped.add(rev)
292 293 state[rev] = p1
293 294
294 295 ui.progress(_('rebasing'), None)
295 296 ui.note(_('rebase merging completed\n'))
296 297
297 298 if collapsef and not keepopen:
298 299 p1, p2 = defineparents(repo, min(state), target,
299 300 state, targetancestors)
300 301 if collapsemsg:
301 302 commitmsg = collapsemsg
302 303 else:
303 304 commitmsg = 'Collapsed revision'
304 305 for rebased in state:
305 306 if rebased not in skipped and state[rebased] > nullmerge:
306 307 commitmsg += '\n* %s' % repo[rebased].description()
307 308 commitmsg = ui.edit(commitmsg, repo.ui.username())
308 309 newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
309 310 extrafn=extrafn, editor=editor)
310 311
311 312 if 'qtip' in repo.tags():
312 313 updatemq(repo, state, skipped, **opts)
313 314
314 315 if currentbookmarks:
315 316 # Nodeids are needed to reset bookmarks
316 317 nstate = {}
317 318 for k, v in state.iteritems():
318 319 if v > nullmerge:
319 320 nstate[repo[k].node()] = repo[v].node()
320 321 # XXX this is the same as dest.node() for the non-continue path --
321 322 # this should probably be cleaned up
322 323 targetnode = repo[target].node()
323 324
324 325 if not keepf:
325 326 collapsedas = None
326 327 if collapsef:
327 328 collapsedas = newrev
328 329 clearrebased(ui, repo, state, skipped, collapsedas)
329 330
330 331 if currentbookmarks:
331 332 updatebookmarks(repo, targetnode, nstate, currentbookmarks)
332 333
333 334 clearstatus(repo)
334 335 ui.note(_("rebase completed\n"))
335 336 util.unlinkpath(repo.sjoin('undo'), ignoremissing=True)
336 337 if skipped:
337 338 ui.note(_("%d revisions have been skipped\n") % len(skipped))
338 339
339 340 if (activebookmark and
340 341 repo['tip'].node() == repo._bookmarks[activebookmark]):
341 342 bookmarks.setcurrent(repo, activebookmark)
342 343
343 344 finally:
344 345 release(lock, wlock)
345 346
346 347 def checkexternal(repo, state, targetancestors):
347 348 """Check whether one or more external revisions need to be taken in
348 349 consideration. In the latter case, abort.
349 350 """
350 351 external = nullrev
351 352 source = min(state)
352 353 for rev in state:
353 354 if rev == source:
354 355 continue
355 356 # Check externals and fail if there are more than one
356 357 for p in repo[rev].parents():
357 358 if (p.rev() not in state
358 359 and p.rev() not in targetancestors):
359 360 if external != nullrev:
360 361 raise util.Abort(_('unable to collapse, there is more '
361 362 'than one external parent'))
362 363 external = p.rev()
363 364 return external
364 365
365 366 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None):
366 367 'Commit the changes and store useful information in extra'
367 368 try:
368 369 repo.setparents(repo[p1].node(), repo[p2].node())
369 370 ctx = repo[rev]
370 371 if commitmsg is None:
371 372 commitmsg = ctx.description()
372 373 extra = {'rebase_source': ctx.hex()}
373 374 if extrafn:
374 375 extrafn(ctx, extra)
375 376 # Commit might fail if unresolved files exist
376 377 newrev = repo.commit(text=commitmsg, user=ctx.user(),
377 378 date=ctx.date(), extra=extra, editor=editor)
378 379 repo.dirstate.setbranch(repo[newrev].branch())
379 380 targetphase = max(ctx.phase(), phases.draft)
380 381 # retractboundary doesn't overwrite upper phase inherited from parent
381 382 newnode = repo[newrev].node()
382 383 if newnode:
383 384 phases.retractboundary(repo, targetphase, [newnode])
384 385 return newrev
385 386 except util.Abort:
386 387 # Invalidate the previous setparents
387 388 repo.dirstate.invalidate()
388 389 raise
389 390
390 391 def rebasenode(repo, rev, p1, state, collapse):
391 392 'Rebase a single revision'
392 393 # Merge phase
393 394 # Update to target and merge it with local
394 395 if repo['.'].rev() != repo[p1].rev():
395 396 repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
396 397 merge.update(repo, p1, False, True, False)
397 398 else:
398 399 repo.ui.debug(" already in target\n")
399 400 repo.dirstate.write()
400 401 repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
401 402 base = None
402 403 if repo[rev].rev() != repo[min(state)].rev():
403 404 base = repo[rev].p1().node()
404 405 # When collapsing in-place, the parent is the common ancestor, we
405 406 # have to allow merging with it.
406 407 return merge.update(repo, rev, True, True, False, base, collapse)
407 408
408 409 def nearestrebased(repo, rev, state):
409 410 """return the nearest ancestors of rev in the rebase result"""
410 411 rebased = [r for r in state if state[r] > nullmerge]
411 412 candidates = repo.revs('max(%ld and (::%d))', rebased, rev)
412 413 if candidates:
413 414 return state[candidates[0]]
414 415 else:
415 416 return None
416 417
417 418 def defineparents(repo, rev, target, state, targetancestors):
418 419 'Return the new parent relationship of the revision that will be rebased'
419 420 parents = repo[rev].parents()
420 421 p1 = p2 = nullrev
421 422
422 423 P1n = parents[0].rev()
423 424 if P1n in targetancestors:
424 425 p1 = target
425 426 elif P1n in state:
426 427 if state[P1n] == nullmerge:
427 428 p1 = target
428 429 elif state[P1n] == revignored:
429 430 p1 = nearestrebased(repo, P1n, state)
430 431 if p1 is None:
431 432 p1 = target
432 433 else:
433 434 p1 = state[P1n]
434 435 else: # P1n external
435 436 p1 = target
436 437 p2 = P1n
437 438
438 439 if len(parents) == 2 and parents[1].rev() not in targetancestors:
439 440 P2n = parents[1].rev()
440 441 # interesting second parent
441 442 if P2n in state:
442 443 if p1 == target: # P1n in targetancestors or external
443 444 p1 = state[P2n]
444 445 elif state[P2n] == revignored:
445 446 p2 = nearestrebased(repo, P2n, state)
446 447 if p2 is None:
447 448 # no ancestors rebased yet, detach
448 449 p2 = target
449 450 else:
450 451 p2 = state[P2n]
451 452 else: # P2n external
452 453 if p2 != nullrev: # P1n external too => rev is a merged revision
453 454 raise util.Abort(_('cannot use revision %d as base, result '
454 455 'would have 3 parents') % rev)
455 456 p2 = P2n
456 457 repo.ui.debug(" future parents are %d and %d\n" %
457 458 (repo[p1].rev(), repo[p2].rev()))
458 459 return p1, p2
459 460
460 461 def isagitpatch(repo, patchname):
461 462 'Return true if the given patch is in git format'
462 463 mqpatch = os.path.join(repo.mq.path, patchname)
463 464 for line in patch.linereader(file(mqpatch, 'rb')):
464 465 if line.startswith('diff --git'):
465 466 return True
466 467 return False
467 468
468 469 def updatemq(repo, state, skipped, **opts):
469 470 'Update rebased mq patches - finalize and then import them'
470 471 mqrebase = {}
471 472 mq = repo.mq
472 473 original_series = mq.fullseries[:]
473 474 skippedpatches = set()
474 475
475 476 for p in mq.applied:
476 477 rev = repo[p.node].rev()
477 478 if rev in state:
478 479 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
479 480 (rev, p.name))
480 481 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
481 482 else:
482 483 # Applied but not rebased, not sure this should happen
483 484 skippedpatches.add(p.name)
484 485
485 486 if mqrebase:
486 487 mq.finish(repo, mqrebase.keys())
487 488
488 489 # We must start import from the newest revision
489 490 for rev in sorted(mqrebase, reverse=True):
490 491 if rev not in skipped:
491 492 name, isgit = mqrebase[rev]
492 493 repo.ui.debug('import mq patch %d (%s)\n' % (state[rev], name))
493 494 mq.qimport(repo, (), patchname=name, git=isgit,
494 495 rev=[str(state[rev])])
495 496 else:
496 497 # Rebased and skipped
497 498 skippedpatches.add(mqrebase[rev][0])
498 499
499 500 # Patches were either applied and rebased and imported in
500 501 # order, applied and removed or unapplied. Discard the removed
501 502 # ones while preserving the original series order and guards.
502 503 newseries = [s for s in original_series
503 504 if mq.guard_re.split(s, 1)[0] not in skippedpatches]
504 505 mq.fullseries[:] = newseries
505 506 mq.seriesdirty = True
506 507 mq.savedirty()
507 508
508 509 def updatebookmarks(repo, targetnode, nstate, originalbookmarks):
509 510 'Move bookmarks to their correct changesets, and delete divergent ones'
510 511 marks = repo._bookmarks
511 512 for k, v in originalbookmarks.iteritems():
512 513 if v in nstate:
513 514 # update the bookmarks for revs that have moved
514 515 marks[k] = nstate[v]
515 516 bookmarks.deletedivergent(repo, [targetnode], k)
516 517
517 518 marks.write()
518 519
519 520 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
520 521 external, activebookmark):
521 522 'Store the current status to allow recovery'
522 523 f = repo.opener("rebasestate", "w")
523 524 f.write(repo[originalwd].hex() + '\n')
524 525 f.write(repo[target].hex() + '\n')
525 526 f.write(repo[external].hex() + '\n')
526 527 f.write('%d\n' % int(collapse))
527 528 f.write('%d\n' % int(keep))
528 529 f.write('%d\n' % int(keepbranches))
529 530 f.write('%s\n' % (activebookmark or ''))
530 531 for d, v in state.iteritems():
531 532 oldrev = repo[d].hex()
532 533 if v > nullmerge:
533 534 newrev = repo[v].hex()
534 535 else:
535 536 newrev = v
536 537 f.write("%s:%s\n" % (oldrev, newrev))
537 538 f.close()
538 539 repo.ui.debug('rebase status stored\n')
539 540
540 541 def clearstatus(repo):
541 542 'Remove the status files'
542 543 util.unlinkpath(repo.join("rebasestate"), ignoremissing=True)
543 544
544 545 def restorestatus(repo):
545 546 'Restore a previously stored status'
546 547 try:
547 548 target = None
548 549 collapse = False
549 550 external = nullrev
550 551 activebookmark = None
551 552 state = {}
552 553 f = repo.opener("rebasestate")
553 554 for i, l in enumerate(f.read().splitlines()):
554 555 if i == 0:
555 556 originalwd = repo[l].rev()
556 557 elif i == 1:
557 558 target = repo[l].rev()
558 559 elif i == 2:
559 560 external = repo[l].rev()
560 561 elif i == 3:
561 562 collapse = bool(int(l))
562 563 elif i == 4:
563 564 keep = bool(int(l))
564 565 elif i == 5:
565 566 keepbranches = bool(int(l))
566 567 elif i == 6 and not (len(l) == 81 and ':' in l):
567 568 # line 6 is a recent addition, so for backwards compatibility
568 569 # check that the line doesn't look like the oldrev:newrev lines
569 570 activebookmark = l
570 571 else:
571 572 oldrev, newrev = l.split(':')
572 573 if newrev in (str(nullmerge), str(revignored)):
573 574 state[repo[oldrev].rev()] = int(newrev)
574 575 else:
575 576 state[repo[oldrev].rev()] = repo[newrev].rev()
576 577 skipped = set()
577 578 # recompute the set of skipped revs
578 579 if not collapse:
579 580 seen = set([target])
580 581 for old, new in sorted(state.items()):
581 582 if new != nullrev and new in seen:
582 583 skipped.add(old)
583 584 seen.add(new)
584 585 repo.ui.debug('computed skipped revs: %s\n' % skipped)
585 586 repo.ui.debug('rebase status resumed\n')
586 587 return (originalwd, target, state, skipped,
587 588 collapse, keep, keepbranches, external, activebookmark)
588 589 except IOError, err:
589 590 if err.errno != errno.ENOENT:
590 591 raise
591 592 raise util.Abort(_('no rebase in progress'))
592 593
593 594 def abort(repo, originalwd, target, state):
594 595 'Restore the repository to its original state'
595 596 dstates = [s for s in state.values() if s != nullrev]
596 597 immutable = [d for d in dstates if not repo[d].mutable()]
597 598 if immutable:
598 599 raise util.Abort(_("can't abort rebase due to immutable changesets %s")
599 600 % ', '.join(str(repo[r]) for r in immutable),
600 601 hint=_('see hg help phases for details'))
601 602
602 603 descendants = set()
603 604 if dstates:
604 605 descendants = set(repo.changelog.descendants(dstates))
605 606 if descendants - set(dstates):
606 607 repo.ui.warn(_("warning: new changesets detected on target branch, "
607 608 "can't abort\n"))
608 609 return -1
609 610 else:
610 611 # Strip from the first rebased revision
611 612 merge.update(repo, repo[originalwd].rev(), False, True, False)
612 613 rebased = filter(lambda x: x > -1 and x != target, state.values())
613 614 if rebased:
614 615 strippoints = [c.node() for c in repo.set('roots(%ld)', rebased)]
615 616 # no backup of rebased cset versions needed
616 617 repair.strip(repo.ui, repo, strippoints)
617 618 clearstatus(repo)
618 619 repo.ui.warn(_('rebase aborted\n'))
619 620 return 0
620 621
621 622 def buildstate(repo, dest, rebaseset, collapse):
622 623 '''Define which revisions are going to be rebased and where
623 624
624 625 repo: repo
625 626 dest: context
626 627 rebaseset: set of rev
627 628 '''
628 629
629 630 # This check isn't strictly necessary, since mq detects commits over an
630 631 # applied patch. But it prevents messing up the working directory when
631 632 # a partially completed rebase is blocked by mq.
632 633 if 'qtip' in repo.tags() and (dest.node() in
633 634 [s.node for s in repo.mq.applied]):
634 635 raise util.Abort(_('cannot rebase onto an applied mq patch'))
635 636
636 637 roots = list(repo.set('roots(%ld)', rebaseset))
637 638 if not roots:
638 639 raise util.Abort(_('no matching revisions'))
639 640 roots.sort()
640 641 state = {}
641 642 detachset = set()
642 643 for root in roots:
643 644 commonbase = root.ancestor(dest)
644 645 if commonbase == root:
645 646 raise util.Abort(_('source is ancestor of destination'))
646 647 if commonbase == dest:
647 648 samebranch = root.branch() == dest.branch()
648 649 if not collapse and samebranch and root in dest.children():
649 650 repo.ui.debug('source is a child of destination\n')
650 651 return None
651 652
652 653 repo.ui.debug('rebase onto %d starting from %s\n' % (dest, roots))
653 654 state.update(dict.fromkeys(rebaseset, nullrev))
654 655 # Rebase tries to turn <dest> into a parent of <root> while
655 656 # preserving the number of parents of rebased changesets:
656 657 #
657 658 # - A changeset with a single parent will always be rebased as a
658 659 # changeset with a single parent.
659 660 #
660 661 # - A merge will be rebased as merge unless its parents are both
661 662 # ancestors of <dest> or are themselves in the rebased set and
662 663 # pruned while rebased.
663 664 #
664 665 # If one parent of <root> is an ancestor of <dest>, the rebased
665 666 # version of this parent will be <dest>. This is always true with
666 667 # --base option.
667 668 #
668 669 # Otherwise, we need to *replace* the original parents with
669 670 # <dest>. This "detaches" the rebased set from its former location
670 671 # and rebases it onto <dest>. Changes introduced by ancestors of
671 672 # <root> not common with <dest> (the detachset, marked as
672 673 # nullmerge) are "removed" from the rebased changesets.
673 674 #
674 675 # - If <root> has a single parent, set it to <dest>.
675 676 #
676 677 # - If <root> is a merge, we cannot decide which parent to
677 678 # replace, the rebase operation is not clearly defined.
678 679 #
679 680 # The table below sums up this behavior:
680 681 #
681 682 # +------------------+----------------------+-------------------------+
682 683 # | | one parent | merge |
683 684 # +------------------+----------------------+-------------------------+
684 685 # | parent in | new parent is <dest> | parents in ::<dest> are |
685 686 # | ::<dest> | | remapped to <dest> |
686 687 # +------------------+----------------------+-------------------------+
687 688 # | unrelated source | new parent is <dest> | ambiguous, abort |
688 689 # +------------------+----------------------+-------------------------+
689 690 #
690 691 # The actual abort is handled by `defineparents`
691 692 if len(root.parents()) <= 1:
692 693 # ancestors of <root> not ancestors of <dest>
693 694 detachset.update(repo.changelog.findmissingrevs([commonbase.rev()],
694 695 [root.rev()]))
695 696 for r in detachset:
696 697 if r not in state:
697 698 state[r] = nullmerge
698 699 if len(roots) > 1:
699 700 # If we have multiple roots, we may have "hole" in the rebase set.
700 701 # Rebase roots that descend from those "hole" should not be detached as
701 702 # other root are. We use the special `revignored` to inform rebase that
702 703 # the revision should be ignored but that `defineparents` should search
703 704 # a rebase destination that make sense regarding rebased topology.
704 705 rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset))
705 706 for ignored in set(rebasedomain) - set(rebaseset):
706 707 state[ignored] = revignored
707 708 return repo['.'].rev(), dest.rev(), state
708 709
709 710 def clearrebased(ui, repo, state, skipped, collapsedas=None):
710 711 """dispose of rebased revision at the end of the rebase
711 712
712 713 If `collapsedas` is not None, the rebase was a collapse whose result if the
713 714 `collapsedas` node."""
714 715 if obsolete._enabled:
715 716 markers = []
716 717 for rev, newrev in sorted(state.items()):
717 718 if newrev >= 0:
718 719 if rev in skipped:
719 720 succs = ()
720 721 elif collapsedas is not None:
721 722 succs = (repo[collapsedas],)
722 723 else:
723 724 succs = (repo[newrev],)
724 725 markers.append((repo[rev], succs))
725 726 if markers:
726 727 obsolete.createmarkers(repo, markers)
727 728 else:
728 729 rebased = [rev for rev in state if state[rev] > nullmerge]
729 730 if rebased:
730 731 stripped = []
731 732 for root in repo.set('roots(%ld)', rebased):
732 733 if set(repo.changelog.descendants([root.rev()])) - set(state):
733 734 ui.warn(_("warning: new changesets detected "
734 735 "on source branch, not stripping\n"))
735 736 else:
736 737 stripped.append(root.node())
737 738 if stripped:
738 739 # backup the old csets by default
739 740 repair.strip(ui, repo, stripped, "all")
740 741
741 742
742 743 def pullrebase(orig, ui, repo, *args, **opts):
743 744 'Call rebase after pull if the latter has been invoked with --rebase'
744 745 if opts.get('rebase'):
745 746 if opts.get('update'):
746 747 del opts['update']
747 748 ui.debug('--update and --rebase are not compatible, ignoring '
748 749 'the update flag\n')
749 750
750 751 movemarkfrom = repo['.'].node()
751 752 cmdutil.bailifchanged(repo)
752 753 revsprepull = len(repo)
753 754 origpostincoming = commands.postincoming
754 755 def _dummy(*args, **kwargs):
755 756 pass
756 757 commands.postincoming = _dummy
757 758 try:
758 759 orig(ui, repo, *args, **opts)
759 760 finally:
760 761 commands.postincoming = origpostincoming
761 762 revspostpull = len(repo)
762 763 if revspostpull > revsprepull:
763 764 # --rev option from pull conflict with rebase own --rev
764 765 # dropping it
765 766 if 'rev' in opts:
766 767 del opts['rev']
767 768 rebase(ui, repo, **opts)
768 769 branch = repo[None].branch()
769 770 dest = repo[branch].rev()
770 771 if dest != repo['.'].rev():
771 772 # there was nothing to rebase we force an update
772 773 hg.update(repo, dest)
773 774 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
774 775 ui.status(_("updating bookmark %s\n")
775 776 % repo._bookmarkcurrent)
776 777 else:
777 778 if opts.get('tool'):
778 779 raise util.Abort(_('--tool can only be used with --rebase'))
779 780 orig(ui, repo, *args, **opts)
780 781
781 782 def uisetup(ui):
782 783 'Replace pull with a decorator to provide --rebase option'
783 784 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
784 785 entry[1].append(('', 'rebase', None,
785 786 _("rebase working directory to branch head")))
786 787 entry[1].append(('t', 'tool', '',
787 788 _("specify merge tool for rebase")))
@@ -1,158 +1,158 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}:{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 c1 > common
18 18 $ hg add common
19 19 $ hg ci -m C1
20 20
21 21 $ echo c2 >> common
22 22 $ hg ci -m C2
23 23
24 24 $ echo c3 >> common
25 25 $ hg ci -m C3
26 26
27 27 $ hg up -q -C 1
28 28
29 29 $ echo l1 >> extra
30 30 $ hg add extra
31 31 $ hg ci -m L1
32 32 created new head
33 33
34 34 $ sed -e 's/c2/l2/' common > common.new
35 35 $ mv common.new common
36 36 $ hg ci -m L2
37 37
38 38 $ hg phase --force --secret 2
39 39
40 40 $ hg tglog
41 41 @ 4:draft 'L2'
42 42 |
43 43 o 3:draft 'L1'
44 44 |
45 45 | o 2:secret 'C3'
46 46 |/
47 47 o 1:draft 'C2'
48 48 |
49 49 o 0:draft 'C1'
50 50
51 51
52 52 Conflicting rebase:
53 53
54 54 $ hg rebase -s 3 -d 2
55 55 merging common
56 56 warning: conflicts during merge.
57 57 merging common incomplete! (edit conflicts, then use 'hg resolve --mark')
58 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
58 unresolved conflicts (see hg resolve, then hg rebase --continue)
59 59 [255]
60 60
61 61 Abort:
62 62
63 63 $ hg rebase --abort
64 64 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
65 65 rebase aborted
66 66
67 67 $ hg tglog
68 68 @ 4:draft 'L2'
69 69 |
70 70 o 3:draft 'L1'
71 71 |
72 72 | o 2:secret 'C3'
73 73 |/
74 74 o 1:draft 'C2'
75 75 |
76 76 o 0:draft 'C1'
77 77
78 78 $ cd ..
79 79
80 80
81 81 Construct new repo:
82 82
83 83 $ hg init b
84 84 $ cd b
85 85
86 86 $ echo a > a
87 87 $ hg ci -Am A
88 88 adding a
89 89
90 90 $ echo b > b
91 91 $ hg ci -Am B
92 92 adding b
93 93
94 94 $ echo c > c
95 95 $ hg ci -Am C
96 96 adding c
97 97
98 98 $ hg up -q 0
99 99
100 100 $ echo b > b
101 101 $ hg ci -Am 'B bis'
102 102 adding b
103 103 created new head
104 104
105 105 $ echo c1 > c
106 106 $ hg ci -Am C1
107 107 adding c
108 108
109 109 $ hg phase --force --secret 1
110 110 $ hg phase --public 1
111 111
112 112 Rebase and abort without generating new changesets:
113 113
114 114 $ hg tglog
115 115 @ 4:draft 'C1'
116 116 |
117 117 o 3:draft 'B bis'
118 118 |
119 119 | o 2:secret 'C'
120 120 | |
121 121 | o 1:public 'B'
122 122 |/
123 123 o 0:public 'A'
124 124
125 125 $ hg rebase -b 4 -d 2
126 126 merging c
127 127 warning: conflicts during merge.
128 128 merging c incomplete! (edit conflicts, then use 'hg resolve --mark')
129 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
129 unresolved conflicts (see hg resolve, then hg rebase --continue)
130 130 [255]
131 131
132 132 $ hg tglog
133 133 @ 4:draft 'C1'
134 134 |
135 135 o 3:draft 'B bis'
136 136 |
137 137 | @ 2:secret 'C'
138 138 | |
139 139 | o 1:public 'B'
140 140 |/
141 141 o 0:public 'A'
142 142
143 143 $ hg rebase -a
144 144 rebase aborted
145 145
146 146 $ hg tglog
147 147 @ 4:draft 'C1'
148 148 |
149 149 o 3:draft 'B bis'
150 150 |
151 151 | o 2:secret 'C'
152 152 | |
153 153 | o 1:public 'B'
154 154 |/
155 155 o 0:public 'A'
156 156
157 157
158 158 $ cd ..
@@ -1,162 +1,162 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' bookmarks: {bookmarks}\n"
11 11 > EOF
12 12
13 13 Create a repo with several bookmarks
14 14 $ hg init a
15 15 $ cd a
16 16
17 17 $ echo a > a
18 18 $ hg ci -Am A
19 19 adding a
20 20
21 21 $ echo b > b
22 22 $ hg ci -Am B
23 23 adding b
24 24 $ hg book 'X'
25 25 $ hg book 'Y'
26 26
27 27 $ echo c > c
28 28 $ hg ci -Am C
29 29 adding c
30 30 $ hg book 'Z'
31 31
32 32 $ hg up -q 0
33 33
34 34 $ echo d > d
35 35 $ hg ci -Am D
36 36 adding d
37 37 created new head
38 38
39 39 $ hg book W
40 40
41 41 $ hg tglog
42 42 @ 3: 'D' bookmarks: W
43 43 |
44 44 | o 2: 'C' bookmarks: Y Z
45 45 | |
46 46 | o 1: 'B' bookmarks: X
47 47 |/
48 48 o 0: 'A' bookmarks:
49 49
50 50
51 51 Move only rebased bookmarks
52 52
53 53 $ cd ..
54 54 $ hg clone -q a a1
55 55
56 56 $ cd a1
57 57 $ hg up -q Z
58 58
59 59 Test deleting divergent bookmarks from dest (issue3685)
60 60
61 61 $ hg book -r 3 Z@diverge
62 62
63 63 ... and also test that bookmarks not on dest or not being moved aren't deleted
64 64
65 65 $ hg book -r 3 X@diverge
66 66 $ hg book -r 0 Y@diverge
67 67
68 68 $ hg tglog
69 69 o 3: 'D' bookmarks: W X@diverge Z@diverge
70 70 |
71 71 | @ 2: 'C' bookmarks: Y Z
72 72 | |
73 73 | o 1: 'B' bookmarks: X
74 74 |/
75 75 o 0: 'A' bookmarks: Y@diverge
76 76
77 77 $ hg rebase -s Y -d 3
78 78 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
79 79
80 80 $ hg tglog
81 81 @ 3: 'C' bookmarks: Y Z
82 82 |
83 83 o 2: 'D' bookmarks: W X@diverge
84 84 |
85 85 | o 1: 'B' bookmarks: X
86 86 |/
87 87 o 0: 'A' bookmarks: Y@diverge
88 88
89 89 Keep bookmarks to the correct rebased changeset
90 90
91 91 $ cd ..
92 92 $ hg clone -q a a2
93 93
94 94 $ cd a2
95 95 $ hg up -q Z
96 96
97 97 $ hg rebase -s 1 -d 3
98 98 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
99 99
100 100 $ hg tglog
101 101 @ 3: 'C' bookmarks: Y Z
102 102 |
103 103 o 2: 'B' bookmarks: X
104 104 |
105 105 o 1: 'D' bookmarks: W
106 106 |
107 107 o 0: 'A' bookmarks:
108 108
109 109
110 110 Keep active bookmark on the correct changeset
111 111
112 112 $ cd ..
113 113 $ hg clone -q a a3
114 114
115 115 $ cd a3
116 116 $ hg up -q X
117 117
118 118 $ hg rebase -d W
119 119 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
120 120
121 121 $ hg tglog
122 122 @ 3: 'C' bookmarks: Y Z
123 123 |
124 124 o 2: 'B' bookmarks: X
125 125 |
126 126 o 1: 'D' bookmarks: W
127 127 |
128 128 o 0: 'A' bookmarks:
129 129
130 130 rebase --continue with bookmarks present (issue3802)
131 131
132 132 $ hg up 2
133 133 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
134 134 $ echo 'C' > c
135 135 $ hg add c
136 136 $ hg ci -m 'other C'
137 137 created new head
138 138 $ hg up 3
139 139 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 140 $ hg rebase
141 141 merging c
142 142 warning: conflicts during merge.
143 143 merging c incomplete! (edit conflicts, then use 'hg resolve --mark')
144 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
144 unresolved conflicts (see hg resolve, then hg rebase --continue)
145 145 [255]
146 146 $ echo 'c' > c
147 147 $ hg resolve --mark c
148 148 $ hg rebase --continue
149 149 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/3d5fa227f4b5-backup.hg (glob)
150 150 $ hg tglog
151 151 @ 4: 'C' bookmarks: Y Z
152 152 |
153 153 o 3: 'other C' bookmarks:
154 154 |
155 155 o 2: 'B' bookmarks: X
156 156 |
157 157 o 1: 'D' bookmarks: W
158 158 |
159 159 o 0: 'A' bookmarks:
160 160
161 161
162 162 $ cd ..
@@ -1,150 +1,150 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}:{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 add A
19 19 $ hg ci -m A
20 20
21 21 $ echo 'B' > B
22 22 $ hg add B
23 23 $ hg ci -m 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 add E
36 36 $ hg ci -m E
37 37
38 38 $ hg up -q -C 0
39 39
40 40 $ hg branch 'notdefault'
41 41 marked working directory as branch notdefault
42 42 (branches are permanent and global, did you want a bookmark?)
43 43 $ echo F >> A
44 44 $ hg ci -m F
45 45
46 46 $ cd ..
47 47
48 48
49 49 Rebasing B onto E - check keep: and phases
50 50
51 51 $ hg clone -q -u . a a1
52 52 $ cd a1
53 53 $ hg phase --force --secret 2
54 54
55 55 $ hg tglog
56 56 @ 5:draft 'F' notdefault
57 57 |
58 58 | o 4:draft 'E'
59 59 | |
60 60 | o 3:draft 'D'
61 61 |/
62 62 | o 2:secret 'C'
63 63 | |
64 64 | o 1:draft 'B'
65 65 |/
66 66 o 0:draft 'A'
67 67
68 68 $ hg rebase -s 1 -d 4 --keep
69 69 merging A
70 70 warning: conflicts during merge.
71 71 merging A incomplete! (edit conflicts, then use 'hg resolve --mark')
72 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
72 unresolved conflicts (see hg resolve, then hg rebase --continue)
73 73 [255]
74 74
75 75 Solve the conflict and go on:
76 76
77 77 $ echo 'conflict solved' > A
78 78 $ rm A.orig
79 79 $ hg resolve -m A
80 80 $ hg rebase --continue
81 81
82 82 $ hg tglog
83 83 @ 7:secret 'C'
84 84 |
85 85 o 6:draft 'B'
86 86 |
87 87 | o 5:draft 'F' notdefault
88 88 | |
89 89 o | 4:draft 'E'
90 90 | |
91 91 o | 3:draft 'D'
92 92 |/
93 93 | o 2:secret 'C'
94 94 | |
95 95 | o 1:draft 'B'
96 96 |/
97 97 o 0:draft 'A'
98 98
99 99 $ cd ..
100 100
101 101
102 102 Rebase F onto E - check keepbranches:
103 103
104 104 $ hg clone -q -u . a a2
105 105 $ cd a2
106 106 $ hg phase --force --secret 2
107 107
108 108 $ hg tglog
109 109 @ 5:draft 'F' notdefault
110 110 |
111 111 | o 4:draft 'E'
112 112 | |
113 113 | o 3:draft 'D'
114 114 |/
115 115 | o 2:secret 'C'
116 116 | |
117 117 | o 1:draft 'B'
118 118 |/
119 119 o 0:draft 'A'
120 120
121 121 $ hg rebase -s 5 -d 4 --keepbranches
122 122 merging A
123 123 warning: conflicts during merge.
124 124 merging A incomplete! (edit conflicts, then use 'hg resolve --mark')
125 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
125 unresolved conflicts (see hg resolve, then hg rebase --continue)
126 126 [255]
127 127
128 128 Solve the conflict and go on:
129 129
130 130 $ echo 'conflict solved' > A
131 131 $ rm A.orig
132 132 $ hg resolve -m A
133 133 $ hg rebase --continue
134 134 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
135 135
136 136 $ hg tglog
137 137 @ 5:draft 'F' notdefault
138 138 |
139 139 o 4:draft 'E'
140 140 |
141 141 o 3:draft 'D'
142 142 |
143 143 | o 2:secret 'C'
144 144 | |
145 145 | o 1:draft 'B'
146 146 |/
147 147 o 0:draft 'A'
148 148
149 149
150 150 $ cd ..
@@ -1,126 +1,126 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}:{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 merging common
66 66 warning: conflicts during merge.
67 67 merging common incomplete! (edit conflicts, then use 'hg resolve --mark')
68 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
68 unresolved conflicts (see hg resolve, then hg rebase --continue)
69 69 [255]
70 70
71 71 Try to continue without solving the conflict:
72 72
73 73 $ hg rebase --continue
74 74 abort: unresolved merge conflicts (see hg help resolve)
75 75 [255]
76 76
77 77 Conclude rebase:
78 78
79 79 $ echo 'resolved merge' >common
80 80 $ hg resolve -m common
81 81 $ hg rebase --continue
82 82 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
83 83
84 84 $ hg tglog
85 85 @ 5:secret 'L3' mybook
86 86 |
87 87 o 4:secret 'L2'
88 88 |
89 89 o 3:draft 'L1'
90 90 |
91 91 o 2:draft 'C3'
92 92 |
93 93 o 1:draft 'C2'
94 94 |
95 95 o 0:draft 'C1'
96 96
97 97 Check correctness:
98 98
99 99 $ hg cat -r 0 common
100 100 c1
101 101
102 102 $ hg cat -r 1 common
103 103 c1
104 104 c2
105 105
106 106 $ hg cat -r 2 common
107 107 c1
108 108 c2
109 109 c3
110 110
111 111 $ hg cat -r 3 common
112 112 c1
113 113 c2
114 114 c3
115 115
116 116 $ hg cat -r 4 common
117 117 resolved merge
118 118
119 119 $ hg cat -r 5 common
120 120 resolved merge
121 121
122 122 Bookmark stays active after --continue
123 123 $ hg bookmarks
124 124 * mybook 5:d67b21408fc0
125 125
126 126 $ cd ..
@@ -1,398 +1,398 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 8 changesets with 7 changes to 7 files (+2 heads)
21 21 (run 'hg heads' to see heads, 'hg merge' to merge)
22 22 $ hg up tip
23 23 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24
25 25 $ cd ..
26 26
27 27
28 28 Rebasing D onto H detaching from C:
29 29
30 30 $ hg clone -q -u . a a1
31 31 $ cd a1
32 32
33 33 $ hg tglog
34 34 @ 7: 'H'
35 35 |
36 36 | o 6: 'G'
37 37 |/|
38 38 o | 5: 'F'
39 39 | |
40 40 | o 4: 'E'
41 41 |/
42 42 | o 3: 'D'
43 43 | |
44 44 | o 2: 'C'
45 45 | |
46 46 | o 1: 'B'
47 47 |/
48 48 o 0: 'A'
49 49
50 50 $ hg phase --force --secret 3
51 51 $ hg rebase -s 3 -d 7
52 52 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
53 53
54 54 $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
55 55 @ 7:secret 'D'
56 56 |
57 57 o 6:draft 'H'
58 58 |
59 59 | o 5:draft 'G'
60 60 |/|
61 61 o | 4:draft 'F'
62 62 | |
63 63 | o 3:draft 'E'
64 64 |/
65 65 | o 2:draft 'C'
66 66 | |
67 67 | o 1:draft 'B'
68 68 |/
69 69 o 0:draft 'A'
70 70
71 71 $ hg manifest
72 72 A
73 73 D
74 74 F
75 75 H
76 76
77 77 $ cd ..
78 78
79 79
80 80 Rebasing C onto H detaching from B:
81 81
82 82 $ hg clone -q -u . a a2
83 83 $ cd a2
84 84
85 85 $ hg tglog
86 86 @ 7: 'H'
87 87 |
88 88 | o 6: 'G'
89 89 |/|
90 90 o | 5: 'F'
91 91 | |
92 92 | o 4: 'E'
93 93 |/
94 94 | o 3: 'D'
95 95 | |
96 96 | o 2: 'C'
97 97 | |
98 98 | o 1: 'B'
99 99 |/
100 100 o 0: 'A'
101 101
102 102 $ hg rebase -s 2 -d 7
103 103 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
104 104
105 105 $ hg tglog
106 106 @ 7: 'D'
107 107 |
108 108 o 6: 'C'
109 109 |
110 110 o 5: 'H'
111 111 |
112 112 | o 4: 'G'
113 113 |/|
114 114 o | 3: 'F'
115 115 | |
116 116 | o 2: 'E'
117 117 |/
118 118 | o 1: 'B'
119 119 |/
120 120 o 0: 'A'
121 121
122 122 $ hg manifest
123 123 A
124 124 C
125 125 D
126 126 F
127 127 H
128 128
129 129 $ cd ..
130 130
131 131
132 132 Rebasing B onto H using detach (same as not using it):
133 133
134 134 $ hg clone -q -u . a a3
135 135 $ cd a3
136 136
137 137 $ hg tglog
138 138 @ 7: 'H'
139 139 |
140 140 | o 6: 'G'
141 141 |/|
142 142 o | 5: 'F'
143 143 | |
144 144 | o 4: 'E'
145 145 |/
146 146 | o 3: 'D'
147 147 | |
148 148 | o 2: 'C'
149 149 | |
150 150 | o 1: 'B'
151 151 |/
152 152 o 0: 'A'
153 153
154 154 $ hg rebase -s 1 -d 7
155 155 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
156 156
157 157 $ hg tglog
158 158 @ 7: 'D'
159 159 |
160 160 o 6: 'C'
161 161 |
162 162 o 5: 'B'
163 163 |
164 164 o 4: 'H'
165 165 |
166 166 | o 3: 'G'
167 167 |/|
168 168 o | 2: 'F'
169 169 | |
170 170 | o 1: 'E'
171 171 |/
172 172 o 0: 'A'
173 173
174 174 $ hg manifest
175 175 A
176 176 B
177 177 C
178 178 D
179 179 F
180 180 H
181 181
182 182 $ cd ..
183 183
184 184
185 185 Rebasing C onto H detaching from B and collapsing:
186 186
187 187 $ hg clone -q -u . a a4
188 188 $ cd a4
189 189 $ hg phase --force --secret 3
190 190
191 191 $ hg tglog
192 192 @ 7: 'H'
193 193 |
194 194 | o 6: 'G'
195 195 |/|
196 196 o | 5: 'F'
197 197 | |
198 198 | o 4: 'E'
199 199 |/
200 200 | o 3: 'D'
201 201 | |
202 202 | o 2: 'C'
203 203 | |
204 204 | o 1: 'B'
205 205 |/
206 206 o 0: 'A'
207 207
208 208 $ hg rebase --collapse -s 2 -d 7
209 209 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
210 210
211 211 $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
212 212 @ 6:secret 'Collapsed revision
213 213 | * C
214 214 | * D'
215 215 o 5:draft 'H'
216 216 |
217 217 | o 4:draft 'G'
218 218 |/|
219 219 o | 3:draft 'F'
220 220 | |
221 221 | o 2:draft 'E'
222 222 |/
223 223 | o 1:draft 'B'
224 224 |/
225 225 o 0:draft 'A'
226 226
227 227 $ hg manifest
228 228 A
229 229 C
230 230 D
231 231 F
232 232 H
233 233
234 234 $ cd ..
235 235
236 236 Rebasing across null as ancestor
237 237 $ hg clone -q -U a a5
238 238
239 239 $ cd a5
240 240
241 241 $ echo x > x
242 242
243 243 $ hg add x
244 244
245 245 $ hg ci -m "extra branch"
246 246 created new head
247 247
248 248 $ hg tglog
249 249 @ 8: 'extra branch'
250 250
251 251 o 7: 'H'
252 252 |
253 253 | o 6: 'G'
254 254 |/|
255 255 o | 5: 'F'
256 256 | |
257 257 | o 4: 'E'
258 258 |/
259 259 | o 3: 'D'
260 260 | |
261 261 | o 2: 'C'
262 262 | |
263 263 | o 1: 'B'
264 264 |/
265 265 o 0: 'A'
266 266
267 267 $ hg rebase -s 1 -d tip
268 268 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
269 269
270 270 $ hg tglog
271 271 @ 8: 'D'
272 272 |
273 273 o 7: 'C'
274 274 |
275 275 o 6: 'B'
276 276 |
277 277 o 5: 'extra branch'
278 278
279 279 o 4: 'H'
280 280 |
281 281 | o 3: 'G'
282 282 |/|
283 283 o | 2: 'F'
284 284 | |
285 285 | o 1: 'E'
286 286 |/
287 287 o 0: 'A'
288 288
289 289
290 290 $ hg rebase -d 5 -s 7
291 291 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/13547172c9c0-backup.hg (glob)
292 292 $ hg tglog
293 293 @ 8: 'D'
294 294 |
295 295 o 7: 'C'
296 296 |
297 297 | o 6: 'B'
298 298 |/
299 299 o 5: 'extra branch'
300 300
301 301 o 4: 'H'
302 302 |
303 303 | o 3: 'G'
304 304 |/|
305 305 o | 2: 'F'
306 306 | |
307 307 | o 1: 'E'
308 308 |/
309 309 o 0: 'A'
310 310
311 311 $ cd ..
312 312
313 313 Verify that target is not selected as external rev (issue3085)
314 314
315 315 $ hg clone -q -U a a6
316 316 $ cd a6
317 317 $ hg up -q 6
318 318
319 319 $ echo "I" >> E
320 320 $ hg ci -m "I"
321 321 $ hg merge 7
322 322 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
323 323 (branch merge, don't forget to commit)
324 324 $ hg ci -m "Merge"
325 325 $ echo "J" >> F
326 326 $ hg ci -m "J"
327 327
328 328 $ hg rebase -s 8 -d 7 --collapse --config ui.merge=internal:other
329 329 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
330 330
331 331 $ hg tglog
332 332 @ 8: 'Collapsed revision
333 333 | * I
334 334 | * Merge
335 335 | * J'
336 336 o 7: 'H'
337 337 |
338 338 | o 6: 'G'
339 339 |/|
340 340 o | 5: 'F'
341 341 | |
342 342 | o 4: 'E'
343 343 |/
344 344 | o 3: 'D'
345 345 | |
346 346 | o 2: 'C'
347 347 | |
348 348 | o 1: 'B'
349 349 |/
350 350 o 0: 'A'
351 351
352 352
353 353 $ hg parents
354 354 changeset: 8:9472f4b1d736
355 355 tag: tip
356 356 user: test
357 357 date: Thu Jan 01 00:00:00 1970 +0000
358 358 summary: Collapsed revision
359 359
360 360
361 361 $ cd ..
362 362
363 363 Ensure --continue restores a correct state (issue3046) and phase:
364 364 $ hg clone -q a a7
365 365 $ cd a7
366 366 $ hg up -q 3
367 367 $ echo 'H2' > H
368 368 $ hg ci -A -m 'H2'
369 369 adding H
370 370 $ hg phase --force --secret 8
371 371 $ hg rebase -s 8 -d 7 --config ui.merge=internal:fail
372 372 merging H
373 373 warning: conflicts during merge.
374 374 merging H incomplete! (edit conflicts, then use 'hg resolve --mark')
375 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
375 unresolved conflicts (see hg resolve, then hg rebase --continue)
376 376 [255]
377 377 $ hg resolve --all -t internal:local
378 378 $ hg rebase -c
379 379 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/6215fafa5447-backup.hg (glob)
380 380 $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
381 381 @ 7:draft 'H'
382 382 |
383 383 | o 6:draft 'G'
384 384 |/|
385 385 o | 5:draft 'F'
386 386 | |
387 387 | o 4:draft 'E'
388 388 |/
389 389 | o 3:draft 'D'
390 390 | |
391 391 | o 2:draft 'C'
392 392 | |
393 393 | o 1:draft 'B'
394 394 |/
395 395 o 0:draft 'A'
396 396
397 397
398 398 $ cd ..
@@ -1,268 +1,268 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > tglogp = log -G --template "{rev}:{phase} '{desc}' {branches}\n"
12 12 > EOF
13 13
14 14
15 15 $ hg init a
16 16 $ cd a
17 17
18 18 $ echo A > A
19 19 $ hg ci -Am A
20 20 adding A
21 21
22 22 $ echo B > B
23 23 $ hg ci -Am B
24 24 adding B
25 25
26 26 $ echo C >> A
27 27 $ hg ci -m C
28 28
29 29 $ hg up -q -C 0
30 30
31 31 $ echo D >> A
32 32 $ hg ci -m D
33 33 created new head
34 34
35 35 $ echo E > E
36 36 $ hg ci -Am E
37 37 adding E
38 38
39 39 $ cd ..
40 40
41 41
42 42 Changes during an interruption - continue:
43 43
44 44 $ hg clone -q -u . a a1
45 45 $ cd a1
46 46
47 47 $ hg tglog
48 48 @ 4: 'E'
49 49 |
50 50 o 3: 'D'
51 51 |
52 52 | o 2: 'C'
53 53 | |
54 54 | o 1: 'B'
55 55 |/
56 56 o 0: 'A'
57 57
58 58 Rebasing B onto E:
59 59
60 60 $ hg rebase -s 1 -d 4
61 61 merging A
62 62 warning: conflicts during merge.
63 63 merging A incomplete! (edit conflicts, then use 'hg resolve --mark')
64 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
64 unresolved conflicts (see hg resolve, then hg rebase --continue)
65 65 [255]
66 66
67 67 Force a commit on C during the interruption:
68 68
69 69 $ hg up -q -C 2
70 70
71 71 $ echo 'Extra' > Extra
72 72 $ hg add Extra
73 73 $ hg ci -m 'Extra'
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:secret 'Extra'
81 81 |
82 82 | o 5:draft 'B'
83 83 | |
84 84 | o 4:draft 'E'
85 85 | |
86 86 | o 3:draft 'D'
87 87 | |
88 88 o | 2:draft 'C'
89 89 | |
90 90 o | 1:draft 'B'
91 91 |/
92 92 o 0:draft 'A'
93 93
94 94 Resume the rebasing:
95 95
96 96 $ hg rebase --continue
97 97 merging A
98 98 warning: conflicts during merge.
99 99 merging A incomplete! (edit conflicts, then use 'hg resolve --mark')
100 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
100 unresolved conflicts (see hg resolve, then hg rebase --continue)
101 101 [255]
102 102
103 103 Solve the conflict and go on:
104 104
105 105 $ echo 'conflict solved' > A
106 106 $ rm A.orig
107 107 $ hg resolve -m A
108 108
109 109 $ hg rebase --continue
110 110 warning: new changesets detected on source branch, not stripping
111 111
112 112 $ hg tglogp
113 113 @ 7:draft 'C'
114 114 |
115 115 | o 6:secret 'Extra'
116 116 | |
117 117 o | 5:draft 'B'
118 118 | |
119 119 o | 4:draft 'E'
120 120 | |
121 121 o | 3:draft 'D'
122 122 | |
123 123 | o 2:draft 'C'
124 124 | |
125 125 | o 1:draft 'B'
126 126 |/
127 127 o 0:draft 'A'
128 128
129 129 $ cd ..
130 130
131 131
132 132 Changes during an interruption - abort:
133 133
134 134 $ hg clone -q -u . a a2
135 135 $ cd a2
136 136
137 137 $ hg tglog
138 138 @ 4: 'E'
139 139 |
140 140 o 3: 'D'
141 141 |
142 142 | o 2: 'C'
143 143 | |
144 144 | o 1: 'B'
145 145 |/
146 146 o 0: 'A'
147 147
148 148 Rebasing B onto E:
149 149
150 150 $ hg rebase -s 1 -d 4
151 151 merging A
152 152 warning: conflicts during merge.
153 153 merging A incomplete! (edit conflicts, then use 'hg resolve --mark')
154 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
154 unresolved conflicts (see hg resolve, then hg rebase --continue)
155 155 [255]
156 156
157 157 Force a commit on B' during the interruption:
158 158
159 159 $ hg up -q -C 5
160 160
161 161 $ echo 'Extra' > Extra
162 162 $ hg add Extra
163 163 $ hg ci -m 'Extra'
164 164
165 165 $ hg tglog
166 166 @ 6: 'Extra'
167 167 |
168 168 o 5: 'B'
169 169 |
170 170 o 4: 'E'
171 171 |
172 172 o 3: 'D'
173 173 |
174 174 | o 2: 'C'
175 175 | |
176 176 | o 1: 'B'
177 177 |/
178 178 o 0: 'A'
179 179
180 180 Abort the rebasing:
181 181
182 182 $ hg rebase --abort
183 183 warning: new changesets detected on target branch, can't abort
184 184 [255]
185 185
186 186 $ hg tglog
187 187 @ 6: 'Extra'
188 188 |
189 189 o 5: 'B'
190 190 |
191 191 o 4: 'E'
192 192 |
193 193 o 3: 'D'
194 194 |
195 195 | o 2: 'C'
196 196 | |
197 197 | o 1: 'B'
198 198 |/
199 199 o 0: 'A'
200 200
201 201 $ cd ..
202 202
203 203 Changes during an interruption - abort (again):
204 204
205 205 $ hg clone -q -u . a a3
206 206 $ cd a3
207 207
208 208 $ hg tglogp
209 209 @ 4:draft 'E'
210 210 |
211 211 o 3:draft 'D'
212 212 |
213 213 | o 2:draft 'C'
214 214 | |
215 215 | o 1:draft 'B'
216 216 |/
217 217 o 0:draft 'A'
218 218
219 219 Rebasing B onto E:
220 220
221 221 $ hg rebase -s 1 -d 4
222 222 merging A
223 223 warning: conflicts during merge.
224 224 merging A incomplete! (edit conflicts, then use 'hg resolve --mark')
225 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
225 unresolved conflicts (see hg resolve, then hg rebase --continue)
226 226 [255]
227 227
228 228 Change phase on B and B'
229 229
230 230 $ hg up -q -C 5
231 231 $ hg phase --public 1
232 232 $ hg phase --public 5
233 233 $ hg phase --secret -f 2
234 234
235 235 $ hg tglogp
236 236 @ 5:public 'B'
237 237 |
238 238 o 4:public 'E'
239 239 |
240 240 o 3:public 'D'
241 241 |
242 242 | o 2:secret 'C'
243 243 | |
244 244 | o 1:public 'B'
245 245 |/
246 246 o 0:public 'A'
247 247
248 248 Abort the rebasing:
249 249
250 250 $ hg rebase --abort
251 251 abort: can't abort rebase due to immutable changesets 45396c49d53b
252 252 (see hg help phases for details)
253 253 [255]
254 254
255 255 $ hg tglogp
256 256 @ 5:public 'B'
257 257 |
258 258 o 4:public 'E'
259 259 |
260 260 o 3:public 'D'
261 261 |
262 262 | o 2:secret 'C'
263 263 | |
264 264 | o 1:public 'B'
265 265 |/
266 266 o 0:public 'A'
267 267
268 268 $ cd ..
@@ -1,139 +1,139 b''
1 1 This emulates the effects of an hg pull --rebase in which the remote repo
2 2 already has one local mq patch
3 3
4 4 $ cat >> $HGRCPATH <<EOF
5 5 > [extensions]
6 6 > graphlog=
7 7 > rebase=
8 8 > mq=
9 9 >
10 10 > [phases]
11 11 > publish=False
12 12 >
13 13 > [alias]
14 14 > tglog = log -G --template "{rev}: '{desc}' tags: {tags}\n"
15 15 > EOF
16 16
17 17
18 18 $ hg init a
19 19 $ cd a
20 20 $ hg qinit -c
21 21
22 22 $ echo c1 > c1
23 23 $ hg add c1
24 24 $ hg ci -m C1
25 25
26 26 $ echo r1 > r1
27 27 $ hg add r1
28 28 $ hg ci -m R1
29 29
30 30 $ hg up -q 0
31 31
32 32 $ hg qnew p0.patch
33 33 $ echo p0 > p0
34 34 $ hg add p0
35 35 $ hg qref -m P0
36 36
37 37 $ hg qnew p1.patch
38 38 $ echo p1 > p1
39 39 $ hg add p1
40 40 $ hg qref -m P1
41 41
42 42 $ hg export qtip > p1.patch
43 43
44 44 $ hg up -q -C 1
45 45
46 46 $ hg import p1.patch
47 47 applying p1.patch
48 48
49 49 $ rm p1.patch
50 50
51 51 $ hg up -q -C qtip
52 52
53 53 $ hg rebase
54 54 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
55 55
56 56 $ hg tglog
57 57 @ 3: 'P0' tags: p0.patch qbase qtip tip
58 58 |
59 59 o 2: 'P1' tags: qparent
60 60 |
61 61 o 1: 'R1' tags:
62 62 |
63 63 o 0: 'C1' tags:
64 64
65 65 $ cd ..
66 66
67 67
68 68 $ hg init b
69 69 $ cd b
70 70 $ hg qinit -c
71 71
72 72 $ for i in r0 r1 r2 r3 r4 r5 r6;
73 73 > do
74 74 > echo $i > $i
75 75 > hg ci -Am $i
76 76 > done
77 77 adding r0
78 78 adding r1
79 79 adding r2
80 80 adding r3
81 81 adding r4
82 82 adding r5
83 83 adding r6
84 84
85 85 $ hg qimport -r 1:tip
86 86
87 87 $ hg up -q 0
88 88
89 89 $ for i in r1 r3 r7 r8;
90 90 > do
91 91 > echo $i > $i
92 92 > hg ci -Am branch2-$i
93 93 > done
94 94 adding r1
95 95 created new head
96 96 adding r3
97 97 adding r7
98 98 adding r8
99 99
100 100 $ echo somethingelse > r4
101 101 $ hg ci -Am branch2-r4
102 102 adding r4
103 103
104 104 $ echo r6 > r6
105 105 $ hg ci -Am branch2-r6
106 106 adding r6
107 107
108 108 $ hg up -q qtip
109 109
110 110 $ HGMERGE=internal:fail hg rebase
111 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
111 unresolved conflicts (see hg resolve, then hg rebase --continue)
112 112 [255]
113 113
114 114 $ HGMERGE=internal:local hg resolve --all
115 115
116 116 $ hg rebase --continue
117 117 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
118 118
119 119 $ hg tglog
120 120 @ 8: 'r5' tags: 5.diff qtip tip
121 121 |
122 122 o 7: 'r2' tags: 2.diff qbase
123 123 |
124 124 o 6: 'branch2-r6' tags: qparent
125 125 |
126 126 o 5: 'branch2-r4' tags:
127 127 |
128 128 o 4: 'branch2-r8' tags:
129 129 |
130 130 o 3: 'branch2-r7' tags:
131 131 |
132 132 o 2: 'branch2-r3' tags:
133 133 |
134 134 o 1: 'branch2-r1' tags:
135 135 |
136 136 o 0: 'r0' tags:
137 137
138 138
139 139 $ cd ..
@@ -1,347 +1,347 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 > mq=
6 6 >
7 7 > [mq]
8 8 > plain=true
9 9 >
10 10 > [alias]
11 11 > tglog = log -G --template "{rev}: '{desc}' tags: {tags}\n"
12 12 > EOF
13 13
14 14
15 15 $ hg init a
16 16 $ cd a
17 17 $ hg qinit -c
18 18
19 19 $ echo c1 > f
20 20 $ hg add f
21 21 $ hg ci -m C1
22 22
23 23 $ echo r1 > f
24 24 $ hg ci -m R1
25 25
26 26 $ hg up -q 0
27 27
28 28 $ hg qnew f.patch
29 29 $ echo mq1 > f
30 30 $ hg qref -m P0
31 31
32 32 $ hg qnew f2.patch
33 33 $ echo mq2 > f
34 34 $ hg qref -m P1
35 35
36 36 $ hg tglog
37 37 @ 3: 'P1' tags: f2.patch qtip tip
38 38 |
39 39 o 2: 'P0' tags: f.patch qbase
40 40 |
41 41 | o 1: 'R1' tags:
42 42 |/
43 43 o 0: 'C1' tags: qparent
44 44
45 45
46 46 Rebase - try to rebase on an applied mq patch:
47 47
48 48 $ hg rebase -s 1 -d 3
49 49 abort: cannot rebase onto an applied mq patch
50 50 [255]
51 51
52 52 Rebase - same thing, but mq patch is default dest:
53 53
54 54 $ hg up -q 1
55 55 $ hg rebase
56 56 abort: cannot rebase onto an applied mq patch
57 57 [255]
58 58 $ hg up -q qtip
59 59
60 60 Rebase - generate a conflict:
61 61
62 62 $ hg rebase -s 2 -d 1
63 63 merging f
64 64 warning: conflicts during merge.
65 65 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
66 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
66 unresolved conflicts (see hg resolve, then hg rebase --continue)
67 67 [255]
68 68
69 69 Fix the 1st conflict:
70 70
71 71 $ echo mq1r1 > f
72 72 $ hg resolve -m f
73 73 $ hg rebase -c
74 74 merging f
75 75 warning: conflicts during merge.
76 76 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
77 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
77 unresolved conflicts (see hg resolve, then hg rebase --continue)
78 78 [255]
79 79
80 80 Fix the 2nd conflict:
81 81
82 82 $ echo mq1r1mq2 > f
83 83 $ hg resolve -m f
84 84 $ hg rebase -c
85 85 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
86 86
87 87 $ hg tglog
88 88 @ 3: 'P1' tags: f2.patch qtip tip
89 89 |
90 90 o 2: 'P0' tags: f.patch qbase
91 91 |
92 92 o 1: 'R1' tags: qparent
93 93 |
94 94 o 0: 'C1' tags:
95 95
96 96 $ hg up -q qbase
97 97
98 98 $ cat f
99 99 mq1r1
100 100
101 101 $ cat .hg/patches/f.patch
102 102 # HG changeset patch
103 103 # User test
104 104 # Date ?????????? ? (glob)
105 105 # * (glob)
106 106 # Node ID ???????????????????????????????????????? (glob)
107 107 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
108 108 P0
109 109
110 110 diff -r bac9ed9960d8 -r ???????????? f (glob)
111 111 --- a/f Thu Jan 01 00:00:00 1970 +0000
112 112 +++ b/f ??? ??? ?? ??:??:?? ???? ????? (glob)
113 113 @@ -1,1 +1,1 @@
114 114 -r1
115 115 +mq1r1
116 116
117 117 Update to qtip:
118 118
119 119 $ hg up -q qtip
120 120
121 121 $ cat f
122 122 mq1r1mq2
123 123
124 124 $ cat .hg/patches/f2.patch
125 125 # HG changeset patch
126 126 # User test
127 127 # Date ?????????? ? (glob)
128 128 # * (glob)
129 129 # Node ID ???????????????????????????????????????? (glob)
130 130 # Parent ???????????????????????????????????????? (glob)
131 131 P1
132 132
133 133 diff -r ???????????? -r ???????????? f (glob)
134 134 --- a/f ??? ??? ?? ??:??:?? ???? ????? (glob)
135 135 +++ b/f ??? ??? ?? ??:??:?? ???? ????? (glob)
136 136 @@ -1,1 +1,1 @@
137 137 -mq1r1
138 138 +mq1r1mq2
139 139
140 140 Adding one git-style patch and one normal:
141 141
142 142 $ hg qpop -a
143 143 popping f2.patch
144 144 popping f.patch
145 145 patch queue now empty
146 146
147 147 $ rm -fr .hg/patches
148 148 $ hg qinit -c
149 149
150 150 $ hg up -q 0
151 151
152 152 $ hg qnew --git f_git.patch
153 153 $ echo mq1 > p
154 154 $ hg add p
155 155 $ hg qref --git -m 'P0 (git)'
156 156
157 157 $ hg qnew f.patch
158 158 $ echo mq2 > p
159 159 $ hg qref -m P1
160 160 $ hg qci -m 'save patch state'
161 161
162 162 $ hg qseries -s
163 163 f_git.patch: P0 (git)
164 164 f.patch: P1
165 165
166 166 $ hg -R .hg/patches manifest
167 167 .hgignore
168 168 f.patch
169 169 f_git.patch
170 170 series
171 171
172 172 $ cat .hg/patches/f_git.patch
173 173 P0 (git)
174 174
175 175 diff --git a/p b/p
176 176 new file mode 100644
177 177 --- /dev/null
178 178 +++ b/p
179 179 @@ -0,0 +1,1 @@
180 180 +mq1
181 181
182 182 $ cat .hg/patches/f.patch
183 183 P1
184 184
185 185 diff -r ???????????? p (glob)
186 186 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
187 187 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
188 188 @@ -1,1 +1,1 @@
189 189 -mq1
190 190 +mq2
191 191
192 192
193 193 Rebase the applied mq patches:
194 194
195 195 $ hg rebase -s 2 -d 1
196 196 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
197 197
198 198 $ hg qci -m 'save patch state'
199 199
200 200 $ hg qseries -s
201 201 f_git.patch: P0 (git)
202 202 f.patch: P1
203 203
204 204 $ hg -R .hg/patches manifest
205 205 .hgignore
206 206 f.patch
207 207 f_git.patch
208 208 series
209 209
210 210 $ cat .hg/patches/f_git.patch
211 211 # HG changeset patch
212 212 # User test
213 213 # Date ?????????? ? (glob)
214 214 # * (glob)
215 215 # Node ID ???????????????????????????????????????? (glob)
216 216 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
217 217 P0 (git)
218 218
219 219 diff --git a/p b/p
220 220 new file mode 100644
221 221 --- /dev/null
222 222 +++ b/p
223 223 @@ -0,0 +1,1 @@
224 224 +mq1
225 225
226 226 $ cat .hg/patches/f.patch
227 227 # HG changeset patch
228 228 # User test
229 229 # Date ?????????? ? (glob)
230 230 # * (glob)
231 231 # Node ID ???????????????????????????????????????? (glob)
232 232 # Parent ???????????????????????????????????????? (glob)
233 233 P1
234 234
235 235 diff -r ???????????? -r ???????????? p (glob)
236 236 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
237 237 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
238 238 @@ -1,1 +1,1 @@
239 239 -mq1
240 240 +mq2
241 241
242 242 $ cd ..
243 243
244 244 Rebase with guards
245 245
246 246 $ hg init foo
247 247 $ cd foo
248 248 $ echo a > a
249 249 $ hg ci -Am a
250 250 adding a
251 251
252 252 Create mq repo with guarded patches foo and bar and empty patch:
253 253
254 254 $ hg qinit
255 255 $ echo guarded > guarded
256 256 $ hg add guarded
257 257 $ hg qnew guarded
258 258 $ hg qnew empty-important -m 'important commit message'
259 259 $ echo bar > bar
260 260 $ hg add bar
261 261 $ hg qnew bar
262 262 $ echo foo > foo
263 263 $ hg add foo
264 264 $ hg qnew foo
265 265 $ hg qpop -a
266 266 popping foo
267 267 popping bar
268 268 popping empty-important
269 269 popping guarded
270 270 patch queue now empty
271 271 $ hg qguard guarded +guarded
272 272 $ hg qguard bar +baz
273 273 $ hg qguard foo +baz
274 274 $ hg qselect baz
275 275 number of unguarded, unapplied patches has changed from 1 to 3
276 276 $ hg qpush bar
277 277 applying empty-important
278 278 patch empty-important is empty
279 279 applying bar
280 280 now at: bar
281 281
282 282 $ hg qguard -l
283 283 guarded: +guarded
284 284 empty-important: unguarded
285 285 bar: +baz
286 286 foo: +baz
287 287
288 288 $ hg tglog
289 289 @ 2: 'imported patch bar' tags: bar qtip tip
290 290 |
291 291 o 1: 'important commit message' tags: empty-important qbase
292 292 |
293 293 o 0: 'a' tags: qparent
294 294
295 295 Create new head to rebase bar onto:
296 296
297 297 $ hg up -C 0
298 298 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
299 299 $ echo b > b
300 300 $ hg add b
301 301 $ hg ci -m b
302 302 created new head
303 303 $ hg up -C 2
304 304 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
305 305 $ echo a >> a
306 306 $ hg qref
307 307
308 308 $ hg tglog
309 309 @ 3: '[mq]: bar' tags: bar qtip tip
310 310 |
311 311 | o 2: 'b' tags:
312 312 | |
313 313 o | 1: 'important commit message' tags: empty-important qbase
314 314 |/
315 315 o 0: 'a' tags: qparent
316 316
317 317
318 318 Rebase bar (make sure series order is preserved and empty-important also is
319 319 removed from the series):
320 320
321 321 $ hg qseries
322 322 guarded
323 323 empty-important
324 324 bar
325 325 foo
326 326 $ [ -f .hg/patches/empty-important ]
327 327 $ hg -q rebase -d 2
328 328 $ hg qseries
329 329 guarded
330 330 bar
331 331 foo
332 332 $ [ -f .hg/patches/empty-important ]
333 333 [1]
334 334
335 335 $ hg qguard -l
336 336 guarded: +guarded
337 337 bar: +baz
338 338 foo: +baz
339 339
340 340 $ hg tglog
341 341 @ 2:* '[mq]: bar' tags: bar qbase qtip tip (glob)
342 342 |
343 343 o 1:* 'b' tags: qparent (glob)
344 344 |
345 345 o 0:* 'a' tags: (glob)
346 346
347 347 $ cd ..
@@ -1,430 +1,430 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > graphlog=
4 4 > rebase=
5 5 >
6 6 > [phases]
7 7 > publish=False
8 8 >
9 9 > [alias]
10 10 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
11 11 > EOF
12 12
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 8 changesets with 7 changes to 7 files (+2 heads)
21 21 (run 'hg heads' to see heads, 'hg merge' to merge)
22 22 $ hg up tip
23 23 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24
25 25 $ echo I > I
26 26 $ hg ci -AmI
27 27 adding I
28 28
29 29 $ hg tglog
30 30 @ 8: 'I'
31 31 |
32 32 o 7: 'H'
33 33 |
34 34 | o 6: 'G'
35 35 |/|
36 36 o | 5: 'F'
37 37 | |
38 38 | o 4: 'E'
39 39 |/
40 40 | o 3: 'D'
41 41 | |
42 42 | o 2: 'C'
43 43 | |
44 44 | o 1: 'B'
45 45 |/
46 46 o 0: 'A'
47 47
48 48 $ cd ..
49 49
50 50
51 51 These fail:
52 52
53 53 $ hg clone -q -u . a a1
54 54 $ cd a1
55 55
56 56 $ hg rebase -s 8 -d 7
57 57 nothing to rebase
58 58 [1]
59 59
60 60 $ hg rebase --continue --abort
61 61 abort: cannot use both abort and continue
62 62 [255]
63 63
64 64 $ hg rebase --continue --collapse
65 65 abort: cannot use collapse with continue or abort
66 66 [255]
67 67
68 68 $ hg rebase --continue --dest 4
69 69 abort: abort and continue do not allow specifying revisions
70 70 [255]
71 71
72 72 $ hg rebase --base 5 --source 4
73 73 abort: cannot specify both a source and a base
74 74 [255]
75 75
76 76 $ hg rebase --rev 5 --source 4
77 77 abort: cannot specify both a revision and a source
78 78 [255]
79 79 $ hg rebase --base 5 --rev 4
80 80 abort: cannot specify both a revision and a base
81 81 [255]
82 82
83 83 $ hg rebase
84 84 nothing to rebase
85 85 [1]
86 86
87 87 $ hg up -q 7
88 88
89 89 $ hg rebase --traceback
90 90 nothing to rebase
91 91 [1]
92 92
93 93
94 94 These work:
95 95
96 96 Rebase with no arguments (from 3 onto 8):
97 97
98 98 $ hg up -q -C 3
99 99
100 100 $ hg rebase
101 101 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
102 102
103 103 $ hg tglog
104 104 @ 8: 'D'
105 105 |
106 106 o 7: 'C'
107 107 |
108 108 o 6: 'B'
109 109 |
110 110 o 5: 'I'
111 111 |
112 112 o 4: 'H'
113 113 |
114 114 | o 3: 'G'
115 115 |/|
116 116 o | 2: 'F'
117 117 | |
118 118 | o 1: 'E'
119 119 |/
120 120 o 0: 'A'
121 121
122 122 Try to rollback after a rebase (fail):
123 123
124 124 $ hg rollback
125 125 no rollback information available
126 126 [1]
127 127
128 128 $ cd ..
129 129
130 130
131 131 Rebase with base == '.' => same as no arguments (from 3 onto 8):
132 132
133 133 $ hg clone -q -u 3 a a2
134 134 $ cd a2
135 135
136 136 $ hg rebase --base .
137 137 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
138 138
139 139 $ hg tglog
140 140 @ 8: 'D'
141 141 |
142 142 o 7: 'C'
143 143 |
144 144 o 6: 'B'
145 145 |
146 146 o 5: 'I'
147 147 |
148 148 o 4: 'H'
149 149 |
150 150 | o 3: 'G'
151 151 |/|
152 152 o | 2: 'F'
153 153 | |
154 154 | o 1: 'E'
155 155 |/
156 156 o 0: 'A'
157 157
158 158 $ cd ..
159 159
160 160
161 161 Rebase with dest == branch(.) => same as no arguments (from 3 onto 8):
162 162
163 163 $ hg clone -q -u 3 a a3
164 164 $ cd a3
165 165
166 166 $ hg rebase --dest 'branch(.)'
167 167 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
168 168
169 169 $ hg tglog
170 170 @ 8: 'D'
171 171 |
172 172 o 7: 'C'
173 173 |
174 174 o 6: 'B'
175 175 |
176 176 o 5: 'I'
177 177 |
178 178 o 4: 'H'
179 179 |
180 180 | o 3: 'G'
181 181 |/|
182 182 o | 2: 'F'
183 183 | |
184 184 | o 1: 'E'
185 185 |/
186 186 o 0: 'A'
187 187
188 188 $ cd ..
189 189
190 190
191 191 Specify only source (from 2 onto 8):
192 192
193 193 $ hg clone -q -u . a a4
194 194 $ cd a4
195 195
196 196 $ hg rebase --source 'desc("C")'
197 197 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
198 198
199 199 $ hg tglog
200 200 @ 8: 'D'
201 201 |
202 202 o 7: 'C'
203 203 |
204 204 o 6: 'I'
205 205 |
206 206 o 5: 'H'
207 207 |
208 208 | o 4: 'G'
209 209 |/|
210 210 o | 3: 'F'
211 211 | |
212 212 | o 2: 'E'
213 213 |/
214 214 | o 1: 'B'
215 215 |/
216 216 o 0: 'A'
217 217
218 218 $ cd ..
219 219
220 220
221 221 Specify only dest (from 3 onto 6):
222 222
223 223 $ hg clone -q -u 3 a a5
224 224 $ cd a5
225 225
226 226 $ hg rebase --dest 6
227 227 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
228 228
229 229 $ hg tglog
230 230 @ 8: 'D'
231 231 |
232 232 o 7: 'C'
233 233 |
234 234 o 6: 'B'
235 235 |
236 236 | o 5: 'I'
237 237 | |
238 238 | o 4: 'H'
239 239 | |
240 240 o | 3: 'G'
241 241 |\|
242 242 | o 2: 'F'
243 243 | |
244 244 o | 1: 'E'
245 245 |/
246 246 o 0: 'A'
247 247
248 248 $ cd ..
249 249
250 250
251 251 Specify only base (from 1 onto 8):
252 252
253 253 $ hg clone -q -u . a a6
254 254 $ cd a6
255 255
256 256 $ hg rebase --base 'desc("D")'
257 257 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
258 258
259 259 $ hg tglog
260 260 @ 8: 'D'
261 261 |
262 262 o 7: 'C'
263 263 |
264 264 o 6: 'B'
265 265 |
266 266 o 5: 'I'
267 267 |
268 268 o 4: 'H'
269 269 |
270 270 | o 3: 'G'
271 271 |/|
272 272 o | 2: 'F'
273 273 | |
274 274 | o 1: 'E'
275 275 |/
276 276 o 0: 'A'
277 277
278 278 $ cd ..
279 279
280 280
281 281 Specify source and dest (from 2 onto 7):
282 282
283 283 $ hg clone -q -u . a a7
284 284 $ cd a7
285 285
286 286 $ hg rebase --source 2 --dest 7
287 287 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/*-backup.hg (glob)
288 288
289 289 $ hg tglog
290 290 @ 8: 'D'
291 291 |
292 292 o 7: 'C'
293 293 |
294 294 | o 6: 'I'
295 295 |/
296 296 o 5: 'H'
297 297 |
298 298 | o 4: 'G'
299 299 |/|
300 300 o | 3: 'F'
301 301 | |
302 302 | o 2: 'E'
303 303 |/
304 304 | o 1: 'B'
305 305 |/
306 306 o 0: 'A'
307 307
308 308 $ cd ..
309 309
310 310
311 311 Specify base and dest (from 1 onto 7):
312 312
313 313 $ hg clone -q -u . a a8
314 314 $ cd a8
315 315
316 316 $ hg rebase --base 3 --dest 7
317 317 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/*-backup.hg (glob)
318 318
319 319 $ hg tglog
320 320 @ 8: 'D'
321 321 |
322 322 o 7: 'C'
323 323 |
324 324 o 6: 'B'
325 325 |
326 326 | o 5: 'I'
327 327 |/
328 328 o 4: 'H'
329 329 |
330 330 | o 3: 'G'
331 331 |/|
332 332 o | 2: 'F'
333 333 | |
334 334 | o 1: 'E'
335 335 |/
336 336 o 0: 'A'
337 337
338 338 $ cd ..
339 339
340 340
341 341 Specify only revs (from 2 onto 8)
342 342
343 343 $ hg clone -q -u . a a9
344 344 $ cd a9
345 345
346 346 $ hg rebase --rev 'desc("C")::'
347 347 saved backup bundle to $TESTTMP/a9/.hg/strip-backup/*-backup.hg (glob)
348 348
349 349 $ hg tglog
350 350 @ 8: 'D'
351 351 |
352 352 o 7: 'C'
353 353 |
354 354 o 6: 'I'
355 355 |
356 356 o 5: 'H'
357 357 |
358 358 | o 4: 'G'
359 359 |/|
360 360 o | 3: 'F'
361 361 | |
362 362 | o 2: 'E'
363 363 |/
364 364 | o 1: 'B'
365 365 |/
366 366 o 0: 'A'
367 367
368 368 $ cd ..
369 369
370 370 Test --tool parameter:
371 371
372 372 $ hg init b
373 373 $ cd b
374 374
375 375 $ echo c1 > c1
376 376 $ hg ci -Am c1
377 377 adding c1
378 378
379 379 $ echo c2 > c2
380 380 $ hg ci -Am c2
381 381 adding c2
382 382
383 383 $ hg up -q 0
384 384 $ echo c2b > c2
385 385 $ hg ci -Am c2b
386 386 adding c2
387 387 created new head
388 388
389 389 $ cd ..
390 390
391 391 $ hg clone -q -u . b b1
392 392 $ cd b1
393 393
394 394 $ hg rebase -s 2 -d 1 --tool internal:local
395 395 saved backup bundle to $TESTTMP/b1/.hg/strip-backup/*-backup.hg (glob)
396 396
397 397 $ hg cat c2
398 398 c2
399 399
400 400 $ cd ..
401 401
402 402
403 403 $ hg clone -q -u . b b2
404 404 $ cd b2
405 405
406 406 $ hg rebase -s 2 -d 1 --tool internal:other
407 407 saved backup bundle to $TESTTMP/b2/.hg/strip-backup/*-backup.hg (glob)
408 408
409 409 $ hg cat c2
410 410 c2b
411 411
412 412 $ cd ..
413 413
414 414
415 415 $ hg clone -q -u . b b3
416 416 $ cd b3
417 417
418 418 $ hg rebase -s 2 -d 1 --tool internal:fail
419 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
419 unresolved conflicts (see hg resolve, then hg rebase --continue)
420 420 [255]
421 421
422 422 $ hg resolve -l
423 423 U c2
424 424
425 425 $ hg resolve -m c2
426 426 $ hg rebase -c --tool internal:fail
427 427 tool option will be ignored
428 428 saved backup bundle to $TESTTMP/b3/.hg/strip-backup/*-backup.hg (glob)
429 429
430 430 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now