##// END OF EJS Templates
rebase: add --rev option to rebase...
Pierre-Yves David -
r15270:6cb6064f default
parent child Browse files
Show More
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -15,7 +15,7 b' http://mercurial.selenic.com/wiki/Rebase'
15 '''
15 '''
16
16
17 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
17 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
18 from mercurial import extensions, patch
18 from mercurial import extensions, patch, scmutil
19 from mercurial.commands import templateopts
19 from mercurial.commands import templateopts
20 from mercurial.node import nullrev
20 from mercurial.node import nullrev
21 from mercurial.lock import release
21 from mercurial.lock import release
@@ -34,6 +34,9 b' command = cmdutil.command(cmdtable)'
34 _('rebase from the base of the specified changeset '
34 _('rebase from the base of the specified changeset '
35 '(up to greatest common ancestor of base and dest)'),
35 '(up to greatest common ancestor of base and dest)'),
36 _('REV')),
36 _('REV')),
37 ('r', 'rev', [],
38 _('rebase these revisions'),
39 _('REV')),
37 ('d', 'dest', '',
40 ('d', 'dest', '',
38 _('rebase onto the specified changeset'), _('REV')),
41 _('rebase onto the specified changeset'), _('REV')),
39 ('', 'collapse', False, _('collapse the rebased changesets')),
42 ('', 'collapse', False, _('collapse the rebased changesets')),
@@ -119,6 +122,7 b' def rebase(ui, repo, **opts):'
119 destf = opts.get('dest', None)
122 destf = opts.get('dest', None)
120 srcf = opts.get('source', None)
123 srcf = opts.get('source', None)
121 basef = opts.get('base', None)
124 basef = opts.get('base', None)
125 revf = opts.get('rev', [])
122 contf = opts.get('continue')
126 contf = opts.get('continue')
123 abortf = opts.get('abort')
127 abortf = opts.get('abort')
124 collapsef = opts.get('collapse', False)
128 collapsef = opts.get('collapse', False)
@@ -156,7 +160,13 b' def rebase(ui, repo, **opts):'
156 else:
160 else:
157 if srcf and basef:
161 if srcf and basef:
158 raise util.Abort(_('cannot specify both a '
162 raise util.Abort(_('cannot specify both a '
163 'source and a base'))
164 if revf and basef:
165 raise util.Abort(_('cannot specify both a'
159 'revision and a base'))
166 'revision and a base'))
167 if revf and srcf:
168 raise util.Abort(_('cannot specify both a'
169 'revision and a source'))
160 if detachf:
170 if detachf:
161 if not srcf:
171 if not srcf:
162 raise util.Abort(
172 raise util.Abort(
@@ -167,24 +177,39 b' def rebase(ui, repo, **opts):'
167 cmdutil.bailifchanged(repo)
177 cmdutil.bailifchanged(repo)
168
178
169 if not destf:
179 if not destf:
170 # Destination defaults to the latest revision in the current branch
180 # Destination defaults to the latest revision in the
181 # current branch
171 branch = repo[None].branch()
182 branch = repo[None].branch()
172 dest = repo[branch]
183 dest = repo[branch]
173 else:
184 else:
174 dest = repo[destf]
185 dest = repo[destf]
175
186
187 rebaseset = None
176 if srcf:
188 if srcf:
177 revsetargs = ('(%r)::', srcf)
189 revsetargs = ('(%r)::', srcf)
190 elif revf:
191 rebaseset = scmutil.revrange(repo, revf)
192 if not keepf and rebaseset:
193 try:
194 repo.set('children(%ld) - %ld',
195 rebaseset, rebaseset).next()
196 except StopIteration:
197 pass # empty revset is what we look for
198 else:
199 msg = _("can't remove original changesets with"
200 " unrebased descendants")
201 hint = _('use --keep to keep original changesets')
202 raise util.Abort(msg, hint=hint)
178 else:
203 else:
179 base = basef or '.'
204 base = basef or '.'
180 revsetargs = ('(children(ancestor(%r, %d)) and ::(%r))::',
205 revsetargs = ('(children(ancestor(%r, %d)) and ::(%r))::',
181 base, dest, base)
206 base, dest, base)
182
207 if rebaseset is None:
183 rebaseset = [c.rev() for c in repo.set(*revsetargs)]
208 rebaseset = [c.rev() for c in repo.set(*revsetargs)]
184 if rebaseset:
209 if rebaseset:
185 result = buildstate(repo, dest, rebaseset, detachf)
210 result = buildstate(repo, dest, rebaseset, detachf)
186 else:
211 else:
187 repo.ui.debug(_('base is ancestor of destination'))
212 repo.ui.debug('base is ancestor of destination')
188 result = None
213 result = None
189 if not result:
214 if not result:
190 # Empty state built, nothing to rebase
215 # Empty state built, nothing to rebase
@@ -545,9 +570,9 b' def buildstate(repo, dest, rebaseset, de'
545 detachset = set()
570 detachset = set()
546 roots = list(repo.set('roots(%ld)', rebaseset))
571 roots = list(repo.set('roots(%ld)', rebaseset))
547 if not roots:
572 if not roots:
548 raise util.Abort( _('no matching revisions'))
573 raise util.Abort(_('no matching revisions'))
549 if len(roots) > 1:
574 if len(roots) > 1:
550 raise util.Abort( _("can't rebase multiple roots"))
575 raise util.Abort(_("can't rebase multiple roots"))
551 root = roots[0]
576 root = roots[0]
552
577
553 commonbase = root.ancestor(dest)
578 commonbase = root.ancestor(dest)
@@ -67,7 +67,7 b' These fail:'
67 [255]
67 [255]
68
68
69 $ hg rebase --base 5 --source 4
69 $ hg rebase --base 5 --source 4
70 abort: cannot specify both a revision and a base
70 abort: cannot specify both a source and a base
71 [255]
71 [255]
72
72
73 $ hg rebase
73 $ hg rebase
@@ -269,4 +269,240 b' C onto A - rebase onto an ancestor:'
269 |/
269 |/
270 o 0: 'A'
270 o 0: 'A'
271
271
272 $ cd ..
272
273
274 Test for revset
275
276 We need a bit different graph
277 All destination are B
278
279 $ hg init ah
280 $ cd ah
281 $ hg unbundle $TESTDIR/bundles/rebase-revset.hg
282 adding changesets
283 adding manifests
284 adding file changes
285 added 9 changesets with 9 changes to 9 files (+2 heads)
286 (run 'hg heads' to see heads, 'hg merge' to merge)
287 $ hg tglog
288 o 8: 'I'
289 |
290 o 7: 'H'
291 |
292 o 6: 'G'
293 |
294 | o 5: 'F'
295 | |
296 | o 4: 'E'
297 |/
298 o 3: 'D'
299 |
300 o 2: 'C'
301 |
302 | o 1: 'B'
303 |/
304 o 0: 'A'
305
306 $ cd ..
307
308
309 Simple case with keep:
310
311 Source on have two descendant heads but ask for one
312
313 $ hg clone -q -u . ah ah1
314 $ cd ah1
315 $ hg rebase -r '2::8' -d 1
316 abort: can't remove original changesets with unrebased descendants
317 (use --keep to keep original changesets)
318 [255]
319 $ hg rebase -r '2::8' -d 1 --keep
320 $ hg tglog
321 @ 13: 'I'
322 |
323 o 12: 'H'
324 |
325 o 11: 'G'
326 |
327 o 10: 'D'
328 |
329 o 9: 'C'
330 |
331 | o 8: 'I'
332 | |
333 | o 7: 'H'
334 | |
335 | o 6: 'G'
336 | |
337 | | o 5: 'F'
338 | | |
339 | | o 4: 'E'
340 | |/
341 | o 3: 'D'
342 | |
343 | o 2: 'C'
344 | |
345 o | 1: 'B'
346 |/
347 o 0: 'A'
348
349
350 $ cd ..
351
352 Base on have one descendant heads we ask for but common ancestor have two
353
354 $ hg clone -q -u . ah ah2
355 $ cd ah2
356 $ hg rebase -r '3::8' -d 1
357 abort: can't remove original changesets with unrebased descendants
358 (use --keep to keep original changesets)
359 [255]
360 $ hg rebase -r '3::8' -d 1 --keep
361 $ hg tglog
362 @ 12: 'I'
363 |
364 o 11: 'H'
365 |
366 o 10: 'G'
367 |
368 o 9: 'D'
369 |\
370 | | o 8: 'I'
371 | | |
372 | | o 7: 'H'
373 | | |
374 | | o 6: 'G'
375 | | |
376 | | | o 5: 'F'
377 | | | |
378 | | | o 4: 'E'
379 | | |/
380 | | o 3: 'D'
381 | |/
382 | o 2: 'C'
383 | |
384 o | 1: 'B'
385 |/
386 o 0: 'A'
387
388
389 $ cd ..
390
391 rebase subset
392
393 $ hg clone -q -u . ah ah3
394 $ cd ah3
395 $ hg rebase -r '3::7' -d 1
396 abort: can't remove original changesets with unrebased descendants
397 (use --keep to keep original changesets)
398 [255]
399 $ hg rebase -r '3::7' -d 1 --keep
400 $ hg tglog
401 @ 11: 'H'
402 |
403 o 10: 'G'
404 |
405 o 9: 'D'
406 |\
407 | | o 8: 'I'
408 | | |
409 | | o 7: 'H'
410 | | |
411 | | o 6: 'G'
412 | | |
413 | | | o 5: 'F'
414 | | | |
415 | | | o 4: 'E'
416 | | |/
417 | | o 3: 'D'
418 | |/
419 | o 2: 'C'
420 | |
421 o | 1: 'B'
422 |/
423 o 0: 'A'
424
425
426 $ cd ..
427
428 rebase subset with multiple head
429
430 $ hg clone -q -u . ah ah4
431 $ cd ah4
432 $ hg rebase -r '3::(7+5)' -d 1
433 abort: can't remove original changesets with unrebased descendants
434 (use --keep to keep original changesets)
435 [255]
436 $ hg rebase -r '3::(7+5)' -d 1 --keep
437 $ hg tglog
438 @ 13: 'H'
439 |
440 o 12: 'G'
441 |
442 | o 11: 'F'
443 | |
444 | o 10: 'E'
445 |/
446 o 9: 'D'
447 |\
448 | | o 8: 'I'
449 | | |
450 | | o 7: 'H'
451 | | |
452 | | o 6: 'G'
453 | | |
454 | | | o 5: 'F'
455 | | | |
456 | | | o 4: 'E'
457 | | |/
458 | | o 3: 'D'
459 | |/
460 | o 2: 'C'
461 | |
462 o | 1: 'B'
463 |/
464 o 0: 'A'
465
466
467 $ cd ..
468
469 More advanced tests
470
471 rebase on ancestor with revset
472
473 $ hg clone -q -u . ah ah5
474 $ cd ah5
475 $ hg rebase -r '6::' -d 2
476 saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-backup.hg
477 $ hg tglog
478 @ 8: 'I'
479 |
480 o 7: 'H'
481 |
482 o 6: 'G'
483 |
484 | o 5: 'F'
485 | |
486 | o 4: 'E'
487 | |
488 | o 3: 'D'
489 |/
490 o 2: 'C'
491 |
492 | o 1: 'B'
493 |/
494 o 0: 'A'
495
496 $ cd ..
497
498
499 rebase with multiple root.
500 We rebase E and G on B
501 We would expect heads are I, F if it was supported
502
503 $ hg clone -q -u . ah ah6
504 $ cd ah6
505 $ hg rebase -r '(4+6)::' -d 1
506 abort: can't rebase multiple roots
507 [255]
508 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now