##// END OF EJS Templates
histedit: add "roll" command to fold commit data and drop message (issue4256)...
Mike Edgar -
r22152:d2a5986c default
parent child Browse files
Show More
@@ -1,931 +1,950
1 1 # histedit.py - interactive history editing for mercurial
2 2 #
3 3 # Copyright 2009 Augie Fackler <raf@durin42.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 """interactive history editing
8 8
9 9 With this extension installed, Mercurial gains one new command: histedit. Usage
10 10 is as follows, assuming the following history::
11 11
12 12 @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42
13 13 | Add delta
14 14 |
15 15 o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42
16 16 | Add gamma
17 17 |
18 18 o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42
19 19 | Add beta
20 20 |
21 21 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
22 22 Add alpha
23 23
24 24 If you were to run ``hg histedit c561b4e977df``, you would see the following
25 25 file open in your editor::
26 26
27 27 pick c561b4e977df Add beta
28 28 pick 030b686bedc4 Add gamma
29 29 pick 7c2fd3b9020c Add delta
30 30
31 31 # Edit history between c561b4e977df and 7c2fd3b9020c
32 32 #
33 33 # Commits are listed from least to most recent
34 34 #
35 35 # Commands:
36 36 # p, pick = use commit
37 37 # e, edit = use commit, but stop for amending
38 38 # f, fold = use commit, but combine it with the one above
39 # r, roll = like fold, but discard this commit's description
39 40 # d, drop = remove commit from history
40 41 # m, mess = edit message without changing commit content
41 42 #
42 43
43 44 In this file, lines beginning with ``#`` are ignored. You must specify a rule
44 45 for each revision in your history. For example, if you had meant to add gamma
45 46 before beta, and then wanted to add delta in the same revision as beta, you
46 47 would reorganize the file to look like this::
47 48
48 49 pick 030b686bedc4 Add gamma
49 50 pick c561b4e977df Add beta
50 51 fold 7c2fd3b9020c Add delta
51 52
52 53 # Edit history between c561b4e977df and 7c2fd3b9020c
53 54 #
54 55 # Commits are listed from least to most recent
55 56 #
56 57 # Commands:
57 58 # p, pick = use commit
58 59 # e, edit = use commit, but stop for amending
59 60 # f, fold = use commit, but combine it with the one above
61 # r, roll = like fold, but discard this commit's description
60 62 # d, drop = remove commit from history
61 63 # m, mess = edit message without changing commit content
62 64 #
63 65
64 66 At which point you close the editor and ``histedit`` starts working. When you
65 67 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
66 68 those revisions together, offering you a chance to clean up the commit message::
67 69
68 70 Add beta
69 71 ***
70 72 Add delta
71 73
72 74 Edit the commit message to your liking, then close the editor. For
73 75 this example, let's assume that the commit message was changed to
74 76 ``Add beta and delta.`` After histedit has run and had a chance to
75 77 remove any old or temporary revisions it needed, the history looks
76 78 like this::
77 79
78 80 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
79 81 | Add beta and delta.
80 82 |
81 83 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
82 84 | Add gamma
83 85 |
84 86 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
85 87 Add alpha
86 88
87 89 Note that ``histedit`` does *not* remove any revisions (even its own temporary
88 90 ones) until after it has completed all the editing operations, so it will
89 91 probably perform several strip operations when it's done. For the above example,
90 92 it had to run strip twice. Strip can be slow depending on a variety of factors,
91 93 so you might need to be a little patient. You can choose to keep the original
92 94 revisions by passing the ``--keep`` flag.
93 95
94 96 The ``edit`` operation will drop you back to a command prompt,
95 97 allowing you to edit files freely, or even use ``hg record`` to commit
96 98 some changes as a separate commit. When you're done, any remaining
97 99 uncommitted changes will be committed as well. When done, run ``hg
98 100 histedit --continue`` to finish this step. You'll be prompted for a
99 101 new commit message, but the default commit message will be the
100 102 original message for the ``edit`` ed revision.
101 103
102 104 The ``message`` operation will give you a chance to revise a commit
103 105 message without changing the contents. It's a shortcut for doing
104 106 ``edit`` immediately followed by `hg histedit --continue``.
105 107
106 108 If ``histedit`` encounters a conflict when moving a revision (while
107 109 handling ``pick`` or ``fold``), it'll stop in a similar manner to
108 110 ``edit`` with the difference that it won't prompt you for a commit
109 111 message when done. If you decide at this point that you don't like how
110 112 much work it will be to rearrange history, or that you made a mistake,
111 113 you can use ``hg histedit --abort`` to abandon the new changes you
112 114 have made and return to the state before you attempted to edit your
113 115 history.
114 116
115 117 If we clone the histedit-ed example repository above and add four more
116 118 changes, such that we have the following history::
117 119
118 120 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
119 121 | Add theta
120 122 |
121 123 o 5 140988835471 2009-04-27 18:04 -0500 stefan
122 124 | Add eta
123 125 |
124 126 o 4 122930637314 2009-04-27 18:04 -0500 stefan
125 127 | Add zeta
126 128 |
127 129 o 3 836302820282 2009-04-27 18:04 -0500 stefan
128 130 | Add epsilon
129 131 |
130 132 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
131 133 | Add beta and delta.
132 134 |
133 135 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
134 136 | Add gamma
135 137 |
136 138 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
137 139 Add alpha
138 140
139 141 If you run ``hg histedit --outgoing`` on the clone then it is the same
140 142 as running ``hg histedit 836302820282``. If you need plan to push to a
141 143 repository that Mercurial does not detect to be related to the source
142 144 repo, you can add a ``--force`` option.
143 145 """
144 146
145 147 try:
146 148 import cPickle as pickle
147 149 pickle.dump # import now
148 150 except ImportError:
149 151 import pickle
150 152 import os
151 153 import sys
152 154
153 155 from mercurial import cmdutil
154 156 from mercurial import discovery
155 157 from mercurial import error
156 158 from mercurial import copies
157 159 from mercurial import context
158 160 from mercurial import hg
159 161 from mercurial import node
160 162 from mercurial import repair
161 163 from mercurial import scmutil
162 164 from mercurial import util
163 165 from mercurial import obsolete
164 166 from mercurial import merge as mergemod
165 167 from mercurial.lock import release
166 168 from mercurial.i18n import _
167 169
168 170 cmdtable = {}
169 171 command = cmdutil.command(cmdtable)
170 172
171 173 testedwith = 'internal'
172 174
173 175 # i18n: command names and abbreviations must remain untranslated
174 176 editcomment = _("""# Edit history between %s and %s
175 177 #
176 178 # Commits are listed from least to most recent
177 179 #
178 180 # Commands:
179 181 # p, pick = use commit
180 182 # e, edit = use commit, but stop for amending
181 183 # f, fold = use commit, but combine it with the one above
184 # r, roll = like fold, but discard this commit's description
182 185 # d, drop = remove commit from history
183 186 # m, mess = edit message without changing commit content
184 187 #
185 188 """)
186 189
187 190 def commitfuncfor(repo, src):
188 191 """Build a commit function for the replacement of <src>
189 192
190 193 This function ensure we apply the same treatment to all changesets.
191 194
192 195 - Add a 'histedit_source' entry in extra.
193 196
194 197 Note that fold have its own separated logic because its handling is a bit
195 198 different and not easily factored out of the fold method.
196 199 """
197 200 phasemin = src.phase()
198 201 def commitfunc(**kwargs):
199 202 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
200 203 try:
201 204 repo.ui.setconfig('phases', 'new-commit', phasemin,
202 205 'histedit')
203 206 extra = kwargs.get('extra', {}).copy()
204 207 extra['histedit_source'] = src.hex()
205 208 kwargs['extra'] = extra
206 209 return repo.commit(**kwargs)
207 210 finally:
208 211 repo.ui.restoreconfig(phasebackup)
209 212 return commitfunc
210 213
211 214 def applychanges(ui, repo, ctx, opts):
212 215 """Merge changeset from ctx (only) in the current working directory"""
213 216 wcpar = repo.dirstate.parents()[0]
214 217 if ctx.p1().node() == wcpar:
215 218 # edition ar "in place" we do not need to make any merge,
216 219 # just applies changes on parent for edition
217 220 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
218 221 stats = None
219 222 else:
220 223 try:
221 224 # ui.forcemerge is an internal variable, do not document
222 225 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
223 226 'histedit')
224 227 stats = mergemod.update(repo, ctx.node(), True, True, False,
225 228 ctx.p1().node())
226 229 finally:
227 230 repo.ui.setconfig('ui', 'forcemerge', '', 'histedit')
228 231 repo.setparents(wcpar, node.nullid)
229 232 repo.dirstate.write()
230 233 # fix up dirstate for copies and renames
231 234 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
232 235 return stats
233 236
234 237 def collapse(repo, first, last, commitopts):
235 238 """collapse the set of revisions from first to last as new one.
236 239
237 240 Expected commit options are:
238 241 - message
239 242 - date
240 243 - username
241 244 Commit message is edited in all cases.
242 245
243 246 This function works in memory."""
244 247 ctxs = list(repo.set('%d::%d', first, last))
245 248 if not ctxs:
246 249 return None
247 250 base = first.parents()[0]
248 251
249 252 # commit a new version of the old changeset, including the update
250 253 # collect all files which might be affected
251 254 files = set()
252 255 for ctx in ctxs:
253 256 files.update(ctx.files())
254 257
255 258 # Recompute copies (avoid recording a -> b -> a)
256 259 copied = copies.pathcopies(base, last)
257 260
258 261 # prune files which were reverted by the updates
259 262 def samefile(f):
260 263 if f in last.manifest():
261 264 a = last.filectx(f)
262 265 if f in base.manifest():
263 266 b = base.filectx(f)
264 267 return (a.data() == b.data()
265 268 and a.flags() == b.flags())
266 269 else:
267 270 return False
268 271 else:
269 272 return f not in base.manifest()
270 273 files = [f for f in files if not samefile(f)]
271 274 # commit version of these files as defined by head
272 275 headmf = last.manifest()
273 276 def filectxfn(repo, ctx, path):
274 277 if path in headmf:
275 278 fctx = last[path]
276 279 flags = fctx.flags()
277 280 mctx = context.memfilectx(repo,
278 281 fctx.path(), fctx.data(),
279 282 islink='l' in flags,
280 283 isexec='x' in flags,
281 284 copied=copied.get(path))
282 285 return mctx
283 286 raise IOError()
284 287
285 288 if commitopts.get('message'):
286 289 message = commitopts['message']
287 290 else:
288 291 message = first.description()
289 292 user = commitopts.get('user')
290 293 date = commitopts.get('date')
291 294 extra = commitopts.get('extra')
292 295
293 296 parents = (first.p1().node(), first.p2().node())
294 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold')
297 editor = None
298 if not commitopts.get('rollup'):
299 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold')
295 300 new = context.memctx(repo,
296 301 parents=parents,
297 302 text=message,
298 303 files=files,
299 304 filectxfn=filectxfn,
300 305 user=user,
301 306 date=date,
302 307 extra=extra,
303 308 editor=editor)
304 309 return repo.commitctx(new)
305 310
306 311 def pick(ui, repo, ctx, ha, opts):
307 312 oldctx = repo[ha]
308 313 if oldctx.parents()[0] == ctx:
309 314 ui.debug('node %s unchanged\n' % ha)
310 315 return oldctx, []
311 316 hg.update(repo, ctx.node())
312 317 stats = applychanges(ui, repo, oldctx, opts)
313 318 if stats and stats[3] > 0:
314 319 raise error.InterventionRequired(_('Fix up the change and run '
315 320 'hg histedit --continue'))
316 321 # drop the second merge parent
317 322 commit = commitfuncfor(repo, oldctx)
318 323 n = commit(text=oldctx.description(), user=oldctx.user(),
319 324 date=oldctx.date(), extra=oldctx.extra())
320 325 if n is None:
321 326 ui.warn(_('%s: empty changeset\n')
322 327 % node.hex(ha))
323 328 return ctx, []
324 329 new = repo[n]
325 330 return new, [(oldctx.node(), (n,))]
326 331
327 332
328 333 def edit(ui, repo, ctx, ha, opts):
329 334 oldctx = repo[ha]
330 335 hg.update(repo, ctx.node())
331 336 applychanges(ui, repo, oldctx, opts)
332 337 raise error.InterventionRequired(
333 338 _('Make changes as needed, you may commit or record as needed now.\n'
334 339 'When you are finished, run hg histedit --continue to resume.'))
335 340
341 def rollup(ui, repo, ctx, ha, opts):
342 rollupopts = opts.copy()
343 rollupopts['rollup'] = True
344 return fold(ui, repo, ctx, ha, rollupopts)
345
336 346 def fold(ui, repo, ctx, ha, opts):
337 347 oldctx = repo[ha]
338 348 hg.update(repo, ctx.node())
339 349 stats = applychanges(ui, repo, oldctx, opts)
340 350 if stats and stats[3] > 0:
341 351 raise error.InterventionRequired(
342 352 _('Fix up the change and run hg histedit --continue'))
343 353 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
344 354 date=oldctx.date(), extra=oldctx.extra())
345 355 if n is None:
346 356 ui.warn(_('%s: empty changeset')
347 357 % node.hex(ha))
348 358 return ctx, []
349 359 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
350 360
351 361 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
352 362 parent = ctx.parents()[0].node()
353 363 hg.update(repo, parent)
354 364 ### prepare new commit data
355 365 commitopts = opts.copy()
356 366 # username
357 367 if ctx.user() == oldctx.user():
358 368 username = ctx.user()
359 369 else:
360 370 username = ui.username()
361 371 commitopts['user'] = username
362 372 # commit message
363 newmessage = '\n***\n'.join(
364 [ctx.description()] +
365 [repo[r].description() for r in internalchanges] +
366 [oldctx.description()]) + '\n'
373 if opts.get('rollup'):
374 newmessage = ctx.description()
375 else:
376 newmessage = '\n***\n'.join(
377 [ctx.description()] +
378 [repo[r].description() for r in internalchanges] +
379 [oldctx.description()]) + '\n'
367 380 commitopts['message'] = newmessage
368 381 # date
369 382 commitopts['date'] = max(ctx.date(), oldctx.date())
370 383 extra = ctx.extra().copy()
371 384 # histedit_source
372 385 # note: ctx is likely a temporary commit but that the best we can do here
373 386 # This is sufficient to solve issue3681 anyway
374 387 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
375 388 commitopts['extra'] = extra
376 389 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
377 390 try:
378 391 phasemin = max(ctx.phase(), oldctx.phase())
379 392 repo.ui.setconfig('phases', 'new-commit', phasemin, 'histedit')
380 393 n = collapse(repo, ctx, repo[newnode], commitopts)
381 394 finally:
382 395 repo.ui.restoreconfig(phasebackup)
383 396 if n is None:
384 397 return ctx, []
385 398 hg.update(repo, n)
386 399 replacements = [(oldctx.node(), (newnode,)),
387 400 (ctx.node(), (n,)),
388 401 (newnode, (n,)),
389 402 ]
390 403 for ich in internalchanges:
391 404 replacements.append((ich, (n,)))
392 405 return repo[n], replacements
393 406
394 407 def drop(ui, repo, ctx, ha, opts):
395 408 return ctx, [(repo[ha].node(), ())]
396 409
397 410
398 411 def message(ui, repo, ctx, ha, opts):
399 412 oldctx = repo[ha]
400 413 hg.update(repo, ctx.node())
401 414 stats = applychanges(ui, repo, oldctx, opts)
402 415 if stats and stats[3] > 0:
403 416 raise error.InterventionRequired(
404 417 _('Fix up the change and run hg histedit --continue'))
405 418 message = oldctx.description()
406 419 commit = commitfuncfor(repo, oldctx)
407 420 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.mess')
408 421 new = commit(text=message, user=oldctx.user(), date=oldctx.date(),
409 422 extra=oldctx.extra(),
410 423 editor=editor)
411 424 newctx = repo[new]
412 425 if oldctx.node() != newctx.node():
413 426 return newctx, [(oldctx.node(), (new,))]
414 427 # We didn't make an edit, so just indicate no replaced nodes
415 428 return newctx, []
416 429
417 430 def findoutgoing(ui, repo, remote=None, force=False, opts={}):
418 431 """utility function to find the first outgoing changeset
419 432
420 433 Used by initialisation code"""
421 434 dest = ui.expandpath(remote or 'default-push', remote or 'default')
422 435 dest, revs = hg.parseurl(dest, None)[:2]
423 436 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
424 437
425 438 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
426 439 other = hg.peer(repo, opts, dest)
427 440
428 441 if revs:
429 442 revs = [repo.lookup(rev) for rev in revs]
430 443
431 444 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
432 445 if not outgoing.missing:
433 446 raise util.Abort(_('no outgoing ancestors'))
434 447 roots = list(repo.revs("roots(%ln)", outgoing.missing))
435 448 if 1 < len(roots):
436 449 msg = _('there are ambiguous outgoing revisions')
437 450 hint = _('see "hg help histedit" for more detail')
438 451 raise util.Abort(msg, hint=hint)
439 452 return repo.lookup(roots[0])
440 453
441 454 actiontable = {'p': pick,
442 455 'pick': pick,
443 456 'e': edit,
444 457 'edit': edit,
445 458 'f': fold,
446 459 'fold': fold,
460 'r': rollup,
461 'roll': rollup,
447 462 'd': drop,
448 463 'drop': drop,
449 464 'm': message,
450 465 'mess': message,
451 466 }
452 467
453 468 @command('histedit',
454 469 [('', 'commands', '',
455 470 _('Read history edits from the specified file.')),
456 471 ('c', 'continue', False, _('continue an edit already in progress')),
457 472 ('k', 'keep', False,
458 473 _("don't strip old nodes after edit is complete")),
459 474 ('', 'abort', False, _('abort an edit in progress')),
460 475 ('o', 'outgoing', False, _('changesets not found in destination')),
461 476 ('f', 'force', False,
462 477 _('force outgoing even for unrelated repositories')),
463 478 ('r', 'rev', [], _('first revision to be edited'))],
464 479 _("ANCESTOR | --outgoing [URL]"))
465 480 def histedit(ui, repo, *freeargs, **opts):
466 481 """interactively edit changeset history
467 482
468 483 This command edits changesets between ANCESTOR and the parent of
469 484 the working directory.
470 485
471 486 With --outgoing, this edits changesets not found in the
472 487 destination repository. If URL of the destination is omitted, the
473 488 'default-push' (or 'default') path will be used.
474 489
475 490 For safety, this command is aborted, also if there are ambiguous
476 491 outgoing revisions which may confuse users: for example, there are
477 492 multiple branches containing outgoing revisions.
478 493
479 494 Use "min(outgoing() and ::.)" or similar revset specification
480 495 instead of --outgoing to specify edit target revision exactly in
481 496 such ambiguous situation. See :hg:`help revsets` for detail about
482 497 selecting revisions.
483 498
484 499 Returns 0 on success, 1 if user intervention is required (not only
485 500 for intentional "edit" command, but also for resolving unexpected
486 501 conflicts).
487 502 """
488 503 lock = wlock = None
489 504 try:
490 505 wlock = repo.wlock()
491 506 lock = repo.lock()
492 507 _histedit(ui, repo, *freeargs, **opts)
493 508 finally:
494 509 release(lock, wlock)
495 510
496 511 def _histedit(ui, repo, *freeargs, **opts):
497 512 # TODO only abort if we try and histedit mq patches, not just
498 513 # blanket if mq patches are applied somewhere
499 514 mq = getattr(repo, 'mq', None)
500 515 if mq and mq.applied:
501 516 raise util.Abort(_('source has mq patches applied'))
502 517
503 518 # basic argument incompatibility processing
504 519 outg = opts.get('outgoing')
505 520 cont = opts.get('continue')
506 521 abort = opts.get('abort')
507 522 force = opts.get('force')
508 523 rules = opts.get('commands', '')
509 524 revs = opts.get('rev', [])
510 525 goal = 'new' # This invocation goal, in new, continue, abort
511 526 if force and not outg:
512 527 raise util.Abort(_('--force only allowed with --outgoing'))
513 528 if cont:
514 529 if util.any((outg, abort, revs, freeargs, rules)):
515 530 raise util.Abort(_('no arguments allowed with --continue'))
516 531 goal = 'continue'
517 532 elif abort:
518 533 if util.any((outg, revs, freeargs, rules)):
519 534 raise util.Abort(_('no arguments allowed with --abort'))
520 535 goal = 'abort'
521 536 else:
522 537 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
523 538 raise util.Abort(_('history edit already in progress, try '
524 539 '--continue or --abort'))
525 540 if outg:
526 541 if revs:
527 542 raise util.Abort(_('no revisions allowed with --outgoing'))
528 543 if len(freeargs) > 1:
529 544 raise util.Abort(
530 545 _('only one repo argument allowed with --outgoing'))
531 546 else:
532 547 revs.extend(freeargs)
533 548 if len(revs) != 1:
534 549 raise util.Abort(
535 550 _('histedit requires exactly one ancestor revision'))
536 551
537 552
538 553 if goal == 'continue':
539 554 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
540 555 parentctx = repo[parentctxnode]
541 556 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
542 557 replacements.extend(repl)
543 558 elif goal == 'abort':
544 559 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
545 560 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
546 561 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
547 562 # check whether we should update away
548 563 parentnodes = [c.node() for c in repo[None].parents()]
549 564 for n in leafs | set([parentctxnode]):
550 565 if n in parentnodes:
551 566 hg.clean(repo, topmost)
552 567 break
553 568 else:
554 569 pass
555 570 cleanupnode(ui, repo, 'created', tmpnodes)
556 571 cleanupnode(ui, repo, 'temp', leafs)
557 572 os.unlink(os.path.join(repo.path, 'histedit-state'))
558 573 return
559 574 else:
560 575 cmdutil.checkunfinished(repo)
561 576 cmdutil.bailifchanged(repo)
562 577
563 578 topmost, empty = repo.dirstate.parents()
564 579 if outg:
565 580 if freeargs:
566 581 remote = freeargs[0]
567 582 else:
568 583 remote = None
569 584 root = findoutgoing(ui, repo, remote, force, opts)
570 585 else:
571 586 rr = list(repo.set('roots(%ld)', scmutil.revrange(repo, revs)))
572 587 if len(rr) != 1:
573 588 raise util.Abort(_('The specified revisions must have '
574 589 'exactly one common root'))
575 590 root = rr[0].node()
576 591
577 592 keep = opts.get('keep', False)
578 593 revs = between(repo, root, topmost, keep)
579 594 if not revs:
580 595 raise util.Abort(_('%s is not an ancestor of working directory') %
581 596 node.short(root))
582 597
583 598 ctxs = [repo[r] for r in revs]
584 599 if not rules:
585 600 rules = '\n'.join([makedesc(c) for c in ctxs])
586 601 rules += '\n\n'
587 602 rules += editcomment % (node.short(root), node.short(topmost))
588 603 rules = ui.edit(rules, ui.username())
589 604 # Save edit rules in .hg/histedit-last-edit.txt in case
590 605 # the user needs to ask for help after something
591 606 # surprising happens.
592 607 f = open(repo.join('histedit-last-edit.txt'), 'w')
593 608 f.write(rules)
594 609 f.close()
595 610 else:
596 611 if rules == '-':
597 612 f = sys.stdin
598 613 else:
599 614 f = open(rules)
600 615 rules = f.read()
601 616 f.close()
602 617 rules = [l for l in (r.strip() for r in rules.splitlines())
603 618 if l and not l[0] == '#']
604 619 rules = verifyrules(rules, repo, ctxs)
605 620
606 621 parentctx = repo[root].parents()[0]
607 622 keep = opts.get('keep', False)
608 623 replacements = []
609 624
610 625
611 626 while rules:
612 627 writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
613 628 action, ha = rules.pop(0)
614 629 ui.debug('histedit: processing %s %s\n' % (action, ha))
615 630 actfunc = actiontable[action]
616 631 parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
617 632 replacements.extend(replacement_)
618 633
619 634 hg.update(repo, parentctx.node())
620 635
621 636 mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
622 637 if mapping:
623 638 for prec, succs in mapping.iteritems():
624 639 if not succs:
625 640 ui.debug('histedit: %s is dropped\n' % node.short(prec))
626 641 else:
627 642 ui.debug('histedit: %s is replaced by %s\n' % (
628 643 node.short(prec), node.short(succs[0])))
629 644 if len(succs) > 1:
630 645 m = 'histedit: %s'
631 646 for n in succs[1:]:
632 647 ui.debug(m % node.short(n))
633 648
634 649 if not keep:
635 650 if mapping:
636 651 movebookmarks(ui, repo, mapping, topmost, ntm)
637 652 # TODO update mq state
638 653 if obsolete._enabled:
639 654 markers = []
640 655 # sort by revision number because it sound "right"
641 656 for prec in sorted(mapping, key=repo.changelog.rev):
642 657 succs = mapping[prec]
643 658 markers.append((repo[prec],
644 659 tuple(repo[s] for s in succs)))
645 660 if markers:
646 661 obsolete.createmarkers(repo, markers)
647 662 else:
648 663 cleanupnode(ui, repo, 'replaced', mapping)
649 664
650 665 cleanupnode(ui, repo, 'temp', tmpnodes)
651 666 os.unlink(os.path.join(repo.path, 'histedit-state'))
652 667 if os.path.exists(repo.sjoin('undo')):
653 668 os.unlink(repo.sjoin('undo'))
654 669
655 670 def gatherchildren(repo, ctx):
656 671 # is there any new commit between the expected parent and "."
657 672 #
658 673 # note: does not take non linear new change in account (but previous
659 674 # implementation didn't used them anyway (issue3655)
660 675 newchildren = [c.node() for c in repo.set('(%d::.)', ctx)]
661 676 if ctx.node() != node.nullid:
662 677 if not newchildren:
663 678 # `ctx` should match but no result. This means that
664 679 # currentnode is not a descendant from ctx.
665 680 msg = _('%s is not an ancestor of working directory')
666 681 hint = _('use "histedit --abort" to clear broken state')
667 682 raise util.Abort(msg % ctx, hint=hint)
668 683 newchildren.pop(0) # remove ctx
669 684 return newchildren
670 685
671 686 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
672 687 action, currentnode = rules.pop(0)
673 688 ctx = repo[currentnode]
674 689
675 690 newchildren = gatherchildren(repo, parentctx)
676 691
677 692 # Commit dirty working directory if necessary
678 693 new = None
679 694 m, a, r, d = repo.status()[:4]
680 695 if m or a or r or d:
681 696 # prepare the message for the commit to comes
682 if action in ('f', 'fold'):
697 if action in ('f', 'fold', 'r', 'roll'):
683 698 message = 'fold-temp-revision %s' % currentnode
684 699 else:
685 700 message = ctx.description()
686 701 editopt = action in ('e', 'edit', 'm', 'mess')
687 702 canonaction = {'e': 'edit', 'm': 'mess', 'p': 'pick'}
688 703 editform = 'histedit.%s' % canonaction.get(action, action)
689 704 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
690 705 commit = commitfuncfor(repo, ctx)
691 706 new = commit(text=message, user=ctx.user(),
692 707 date=ctx.date(), extra=ctx.extra(),
693 708 editor=editor)
694 709 if new is not None:
695 710 newchildren.append(new)
696 711
697 712 replacements = []
698 713 # track replacements
699 714 if ctx.node() not in newchildren:
700 715 # note: new children may be empty when the changeset is dropped.
701 716 # this happen e.g during conflicting pick where we revert content
702 717 # to parent.
703 718 replacements.append((ctx.node(), tuple(newchildren)))
704 719
705 if action in ('f', 'fold'):
720 if action in ('f', 'fold', 'r', 'roll'):
706 721 if newchildren:
707 722 # finalize fold operation if applicable
708 723 if new is None:
709 724 new = newchildren[-1]
710 725 else:
711 726 newchildren.pop() # remove new from internal changes
712 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts,
713 newchildren)
727 foldopts = opts
728 if action in ('r', 'roll'):
729 foldopts = foldopts.copy()
730 foldopts['rollup'] = True
731 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new,
732 foldopts, newchildren)
714 733 replacements.extend(repl)
715 734 else:
716 735 # newchildren is empty if the fold did not result in any commit
717 736 # this happen when all folded change are discarded during the
718 737 # merge.
719 738 replacements.append((ctx.node(), (parentctx.node(),)))
720 739 elif newchildren:
721 740 # otherwise update "parentctx" before proceeding to further operation
722 741 parentctx = repo[newchildren[-1]]
723 742 return parentctx, replacements
724 743
725 744
726 745 def between(repo, old, new, keep):
727 746 """select and validate the set of revision to edit
728 747
729 748 When keep is false, the specified set can't have children."""
730 749 ctxs = list(repo.set('%n::%n', old, new))
731 750 if ctxs and not keep:
732 751 if (not obsolete._enabled and
733 752 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
734 753 raise util.Abort(_('cannot edit history that would orphan nodes'))
735 754 if repo.revs('(%ld) and merge()', ctxs):
736 755 raise util.Abort(_('cannot edit history that contains merges'))
737 756 root = ctxs[0] # list is already sorted by repo.set
738 757 if not root.phase():
739 758 raise util.Abort(_('cannot edit immutable changeset: %s') % root)
740 759 return [c.node() for c in ctxs]
741 760
742 761
743 762 def writestate(repo, parentnode, rules, keep, topmost, replacements):
744 763 fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
745 764 pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
746 765 fp.close()
747 766
748 767 def readstate(repo):
749 768 """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
750 769 """
751 770 fp = open(os.path.join(repo.path, 'histedit-state'))
752 771 return pickle.load(fp)
753 772
754 773
755 774 def makedesc(c):
756 775 """build a initial action line for a ctx `c`
757 776
758 777 line are in the form:
759 778
760 779 pick <hash> <rev> <summary>
761 780 """
762 781 summary = ''
763 782 if c.description():
764 783 summary = c.description().splitlines()[0]
765 784 line = 'pick %s %d %s' % (c, c.rev(), summary)
766 785 # trim to 80 columns so it's not stupidly wide in my editor
767 786 return util.ellipsis(line, 80)
768 787
769 788 def verifyrules(rules, repo, ctxs):
770 789 """Verify that there exists exactly one edit rule per given changeset.
771 790
772 791 Will abort if there are to many or too few rules, a malformed rule,
773 792 or a rule on a changeset outside of the user-given range.
774 793 """
775 794 parsed = []
776 795 expected = set(str(c) for c in ctxs)
777 796 seen = set()
778 797 for r in rules:
779 798 if ' ' not in r:
780 799 raise util.Abort(_('malformed line "%s"') % r)
781 800 action, rest = r.split(' ', 1)
782 801 ha = rest.strip().split(' ', 1)[0]
783 802 try:
784 803 ha = str(repo[ha]) # ensure its a short hash
785 804 except error.RepoError:
786 805 raise util.Abort(_('unknown changeset %s listed') % ha)
787 806 if ha not in expected:
788 807 raise util.Abort(
789 808 _('may not use changesets other than the ones listed'))
790 809 if ha in seen:
791 810 raise util.Abort(_('duplicated command for changeset %s') % ha)
792 811 seen.add(ha)
793 812 if action not in actiontable:
794 813 raise util.Abort(_('unknown action "%s"') % action)
795 814 parsed.append([action, ha])
796 815 missing = sorted(expected - seen) # sort to stabilize output
797 816 if missing:
798 817 raise util.Abort(_('missing rules for changeset %s') % missing[0],
799 818 hint=_('do you want to use the drop action?'))
800 819 return parsed
801 820
802 821 def processreplacement(repo, replacements):
803 822 """process the list of replacements to return
804 823
805 824 1) the final mapping between original and created nodes
806 825 2) the list of temporary node created by histedit
807 826 3) the list of new commit created by histedit"""
808 827 allsuccs = set()
809 828 replaced = set()
810 829 fullmapping = {}
811 830 # initialise basic set
812 831 # fullmapping record all operation recorded in replacement
813 832 for rep in replacements:
814 833 allsuccs.update(rep[1])
815 834 replaced.add(rep[0])
816 835 fullmapping.setdefault(rep[0], set()).update(rep[1])
817 836 new = allsuccs - replaced
818 837 tmpnodes = allsuccs & replaced
819 838 # Reduce content fullmapping into direct relation between original nodes
820 839 # and final node created during history edition
821 840 # Dropped changeset are replaced by an empty list
822 841 toproceed = set(fullmapping)
823 842 final = {}
824 843 while toproceed:
825 844 for x in list(toproceed):
826 845 succs = fullmapping[x]
827 846 for s in list(succs):
828 847 if s in toproceed:
829 848 # non final node with unknown closure
830 849 # We can't process this now
831 850 break
832 851 elif s in final:
833 852 # non final node, replace with closure
834 853 succs.remove(s)
835 854 succs.update(final[s])
836 855 else:
837 856 final[x] = succs
838 857 toproceed.remove(x)
839 858 # remove tmpnodes from final mapping
840 859 for n in tmpnodes:
841 860 del final[n]
842 861 # we expect all changes involved in final to exist in the repo
843 862 # turn `final` into list (topologically sorted)
844 863 nm = repo.changelog.nodemap
845 864 for prec, succs in final.items():
846 865 final[prec] = sorted(succs, key=nm.get)
847 866
848 867 # computed topmost element (necessary for bookmark)
849 868 if new:
850 869 newtopmost = sorted(new, key=repo.changelog.rev)[-1]
851 870 elif not final:
852 871 # Nothing rewritten at all. we won't need `newtopmost`
853 872 # It is the same as `oldtopmost` and `processreplacement` know it
854 873 newtopmost = None
855 874 else:
856 875 # every body died. The newtopmost is the parent of the root.
857 876 newtopmost = repo[sorted(final, key=repo.changelog.rev)[0]].p1().node()
858 877
859 878 return final, tmpnodes, new, newtopmost
860 879
861 880 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
862 881 """Move bookmark from old to newly created node"""
863 882 if not mapping:
864 883 # if nothing got rewritten there is not purpose for this function
865 884 return
866 885 moves = []
867 886 for bk, old in sorted(repo._bookmarks.iteritems()):
868 887 if old == oldtopmost:
869 888 # special case ensure bookmark stay on tip.
870 889 #
871 890 # This is arguably a feature and we may only want that for the
872 891 # active bookmark. But the behavior is kept compatible with the old
873 892 # version for now.
874 893 moves.append((bk, newtopmost))
875 894 continue
876 895 base = old
877 896 new = mapping.get(base, None)
878 897 if new is None:
879 898 continue
880 899 while not new:
881 900 # base is killed, trying with parent
882 901 base = repo[base].p1().node()
883 902 new = mapping.get(base, (base,))
884 903 # nothing to move
885 904 moves.append((bk, new[-1]))
886 905 if moves:
887 906 marks = repo._bookmarks
888 907 for mark, new in moves:
889 908 old = marks[mark]
890 909 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
891 910 % (mark, node.short(old), node.short(new)))
892 911 marks[mark] = new
893 912 marks.write()
894 913
895 914 def cleanupnode(ui, repo, name, nodes):
896 915 """strip a group of nodes from the repository
897 916
898 917 The set of node to strip may contains unknown nodes."""
899 918 ui.debug('should strip %s nodes %s\n' %
900 919 (name, ', '.join([node.short(n) for n in nodes])))
901 920 lock = None
902 921 try:
903 922 lock = repo.lock()
904 923 # Find all node that need to be stripped
905 924 # (we hg %lr instead of %ln to silently ignore unknown item
906 925 nm = repo.changelog.nodemap
907 926 nodes = [n for n in nodes if n in nm]
908 927 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
909 928 for c in roots:
910 929 # We should process node in reverse order to strip tip most first.
911 930 # but this trigger a bug in changegroup hook.
912 931 # This would reduce bundle overhead
913 932 repair.strip(ui, repo, c)
914 933 finally:
915 934 release(lock)
916 935
917 936 def summaryhook(ui, repo):
918 937 if not os.path.exists(repo.join('histedit-state')):
919 938 return
920 939 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
921 940 if rules:
922 941 # i18n: column positioning for "hg summary"
923 942 ui.write(_('hist: %s (histedit --continue)\n') %
924 943 (ui.label(_('%d remaining'), 'histedit.remaining') %
925 944 len(rules)))
926 945
927 946 def extsetup(ui):
928 947 cmdutil.summaryhooks.add('histedit', summaryhook)
929 948 cmdutil.unfinishedstates.append(
930 949 ['histedit-state', False, True, _('histedit in progress'),
931 950 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
@@ -1,261 +1,263
1 1 Test argument handling and various data parsing
2 2 ==================================================
3 3
4 4
5 5 Enable extensions used by this test.
6 6 $ cat >>$HGRCPATH <<EOF
7 7 > [extensions]
8 8 > histedit=
9 9 > EOF
10 10
11 11 Repo setup.
12 12 $ hg init foo
13 13 $ cd foo
14 14 $ echo alpha >> alpha
15 15 $ hg addr
16 16 adding alpha
17 17 $ hg ci -m one
18 18 $ echo alpha >> alpha
19 19 $ hg ci -m two
20 20 $ echo alpha >> alpha
21 21 $ hg ci -m three
22 22 $ echo alpha >> alpha
23 23 $ hg ci -m four
24 24 $ echo alpha >> alpha
25 25 $ hg ci -m five
26 26
27 27 $ hg log --style compact --graph
28 28 @ 4[tip] 08d98a8350f3 1970-01-01 00:00 +0000 test
29 29 | five
30 30 |
31 31 o 3 c8e68270e35a 1970-01-01 00:00 +0000 test
32 32 | four
33 33 |
34 34 o 2 eb57da33312f 1970-01-01 00:00 +0000 test
35 35 | three
36 36 |
37 37 o 1 579e40513370 1970-01-01 00:00 +0000 test
38 38 | two
39 39 |
40 40 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
41 41 one
42 42
43 43
44 44 Run a dummy edit to make sure we get tip^^ correctly via revsingle.
45 45 --------------------------------------------------------------------
46 46
47 47 $ HGEDITOR=cat hg histedit "tip^^"
48 48 pick eb57da33312f 2 three
49 49 pick c8e68270e35a 3 four
50 50 pick 08d98a8350f3 4 five
51 51
52 52 # Edit history between eb57da33312f and 08d98a8350f3
53 53 #
54 54 # Commits are listed from least to most recent
55 55 #
56 56 # Commands:
57 57 # p, pick = use commit
58 58 # e, edit = use commit, but stop for amending
59 59 # f, fold = use commit, but combine it with the one above
60 # r, roll = like fold, but discard this commit's description
60 61 # d, drop = remove commit from history
61 62 # m, mess = edit message without changing commit content
62 63 #
63 64 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 65
65 66 Run on a revision not ancestors of the current working directory.
66 67 --------------------------------------------------------------------
67 68
68 69 $ hg up 2
69 70 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 71 $ hg histedit -r 4
71 72 abort: 08d98a8350f3 is not an ancestor of working directory
72 73 [255]
73 74 $ hg up --quiet
74 75
75 76
76 77 Test that we pick the minimum of a revrange
77 78 ---------------------------------------
78 79
79 80 $ HGEDITOR=cat hg histedit '2::' --commands - << EOF
80 81 > pick eb57da33312f 2 three
81 82 > pick c8e68270e35a 3 four
82 83 > pick 08d98a8350f3 4 five
83 84 > EOF
84 85 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 86 $ hg up --quiet
86 87
87 88 $ HGEDITOR=cat hg histedit 'tip:2' --commands - << EOF
88 89 > pick eb57da33312f 2 three
89 90 > pick c8e68270e35a 3 four
90 91 > pick 08d98a8350f3 4 five
91 92 > EOF
92 93 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 94 $ hg up --quiet
94 95
95 96 Run on a revision not descendants of the initial parent
96 97 --------------------------------------------------------------------
97 98
98 99 Test the message shown for inconsistent histedit state, which may be
99 100 created (and forgotten) by Mercurial earlier than 2.7. This emulates
100 101 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
101 102 temporarily.
102 103
103 104 $ HGEDITOR=cat hg histedit -r 4 --commands - << EOF
104 105 > edit 08d98a8350f3 4 five
105 106 > EOF
106 107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 108 reverting alpha
108 109 Make changes as needed, you may commit or record as needed now.
109 110 When you are finished, run hg histedit --continue to resume.
110 111 [1]
111 112
112 113 $ mv .hg/histedit-state .hg/histedit-state.back
113 114 $ hg update --quiet --clean 2
114 115 $ mv .hg/histedit-state.back .hg/histedit-state
115 116
116 117 $ hg histedit --continue
117 118 abort: c8e68270e35a is not an ancestor of working directory
118 119 (use "histedit --abort" to clear broken state)
119 120 [255]
120 121
121 122 $ hg histedit --abort
122 123 $ hg update --quiet --clean
123 124
124 125 Test that missing revisions are detected
125 126 ---------------------------------------
126 127
127 128 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
128 129 > pick eb57da33312f 2 three
129 130 > pick 08d98a8350f3 4 five
130 131 > EOF
131 132 abort: missing rules for changeset c8e68270e35a
132 133 (do you want to use the drop action?)
133 134 [255]
134 135
135 136 Test that extra revisions are detected
136 137 ---------------------------------------
137 138
138 139 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
139 140 > pick 6058cbb6cfd7 0 one
140 141 > pick c8e68270e35a 3 four
141 142 > pick 08d98a8350f3 4 five
142 143 > EOF
143 144 abort: may not use changesets other than the ones listed
144 145 [255]
145 146
146 147 Test malformed line
147 148 ---------------------------------------
148 149
149 150 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
150 151 > pickeb57da33312f2three
151 152 > pick c8e68270e35a 3 four
152 153 > pick 08d98a8350f3 4 five
153 154 > EOF
154 155 abort: malformed line "pickeb57da33312f2three"
155 156 [255]
156 157
157 158 Test unknown changeset
158 159 ---------------------------------------
159 160
160 161 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
161 162 > pick 0123456789ab 2 three
162 163 > pick c8e68270e35a 3 four
163 164 > pick 08d98a8350f3 4 five
164 165 > EOF
165 166 abort: unknown changeset 0123456789ab listed
166 167 [255]
167 168
168 169 Test unknown command
169 170 ---------------------------------------
170 171
171 172 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
172 173 > coin eb57da33312f 2 three
173 174 > pick c8e68270e35a 3 four
174 175 > pick 08d98a8350f3 4 five
175 176 > EOF
176 177 abort: unknown action "coin"
177 178 [255]
178 179
179 180 Test duplicated changeset
180 181 ---------------------------------------
181 182
182 183 So one is missing and one appear twice.
183 184
184 185 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
185 186 > pick eb57da33312f 2 three
186 187 > pick eb57da33312f 2 three
187 188 > pick 08d98a8350f3 4 five
188 189 > EOF
189 190 abort: duplicated command for changeset eb57da33312f
190 191 [255]
191 192
192 193 Test short version of command
193 194 ---------------------------------------
194 195
195 196 Note: we use varying amounts of white space between command name and changeset
196 197 short hash. This tests issue3893.
197 198
198 199 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
199 200 > pick eb57da33312f 2 three
200 201 > p c8e68270e35a 3 four
201 202 > f 08d98a8350f3 4 five
202 203 > EOF
203 204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 205 reverting alpha
205 206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 207 four
207 208 ***
208 209 five
209 210
210 211
211 212
212 213 HG: Enter commit message. Lines beginning with 'HG:' are removed.
213 214 HG: Leave message empty to abort commit.
214 215 HG: --
215 216 HG: user: test
216 217 HG: branch 'default'
217 218 HG: changed alpha
218 219 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 220 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 221 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
221 222
222 223 $ hg update -q 2
223 224 $ echo x > x
224 225 $ hg add x
225 226 $ hg commit -m'x' x
226 227 created new head
227 228 $ hg histedit -r 'heads(all())'
228 229 abort: The specified revisions must have exactly one common root
229 230 [255]
230 231
231 232 Test that trimming description using multi-byte characters
232 233 --------------------------------------------------------------------
233 234
234 235 $ python <<EOF
235 236 > fp = open('logfile', 'w')
236 237 > fp.write('12345678901234567890123456789012345678901234567890' +
237 238 > '12345') # there are 5 more columns for 80 columns
238 239 >
239 240 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
240 241 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
241 242 >
242 243 > fp.close()
243 244 > EOF
244 245 $ echo xx >> x
245 246 $ hg --encoding utf-8 commit --logfile logfile
246 247
247 248 $ HGEDITOR=cat hg --encoding utf-8 histedit tip
248 249 pick 3d3ea1f3a10b 5 1234567890123456789012345678901234567890123456789012345\xe3\x81\x82... (esc)
249 250
250 251 # Edit history between 3d3ea1f3a10b and 3d3ea1f3a10b
251 252 #
252 253 # Commits are listed from least to most recent
253 254 #
254 255 # Commands:
255 256 # p, pick = use commit
256 257 # e, edit = use commit, but stop for amending
257 258 # f, fold = use commit, but combine it with the one above
259 # r, roll = like fold, but discard this commit's description
258 260 # d, drop = remove commit from history
259 261 # m, mess = edit message without changing commit content
260 262 #
261 263 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1,180 +1,182
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > histedit=
6 6 > EOF
7 7
8 8 $ hg init r
9 9 $ cd r
10 10
11 11 $ for x in a b c d e f ; do
12 12 > echo $x > $x
13 13 > hg add $x
14 14 > hg ci -m $x
15 15 > done
16 16
17 17 $ hg book -r 1 will-move-backwards
18 18 $ hg book -r 2 two
19 19 $ hg book -r 2 also-two
20 20 $ hg book -r 3 three
21 21 $ hg book -r 4 four
22 22 $ hg book -r tip five
23 23 $ hg log --graph
24 24 @ changeset: 5:652413bf663e
25 25 | bookmark: five
26 26 | tag: tip
27 27 | user: test
28 28 | date: Thu Jan 01 00:00:00 1970 +0000
29 29 | summary: f
30 30 |
31 31 o changeset: 4:e860deea161a
32 32 | bookmark: four
33 33 | user: test
34 34 | date: Thu Jan 01 00:00:00 1970 +0000
35 35 | summary: e
36 36 |
37 37 o changeset: 3:055a42cdd887
38 38 | bookmark: three
39 39 | user: test
40 40 | date: Thu Jan 01 00:00:00 1970 +0000
41 41 | summary: d
42 42 |
43 43 o changeset: 2:177f92b77385
44 44 | bookmark: also-two
45 45 | bookmark: two
46 46 | user: test
47 47 | date: Thu Jan 01 00:00:00 1970 +0000
48 48 | summary: c
49 49 |
50 50 o changeset: 1:d2ae7f538514
51 51 | bookmark: will-move-backwards
52 52 | user: test
53 53 | date: Thu Jan 01 00:00:00 1970 +0000
54 54 | summary: b
55 55 |
56 56 o changeset: 0:cb9a9f314b8b
57 57 user: test
58 58 date: Thu Jan 01 00:00:00 1970 +0000
59 59 summary: a
60 60
61 61 $ HGEDITOR=cat hg histedit 1
62 62 pick d2ae7f538514 1 b
63 63 pick 177f92b77385 2 c
64 64 pick 055a42cdd887 3 d
65 65 pick e860deea161a 4 e
66 66 pick 652413bf663e 5 f
67 67
68 68 # Edit history between d2ae7f538514 and 652413bf663e
69 69 #
70 70 # Commits are listed from least to most recent
71 71 #
72 72 # Commands:
73 73 # p, pick = use commit
74 74 # e, edit = use commit, but stop for amending
75 75 # f, fold = use commit, but combine it with the one above
76 # r, roll = like fold, but discard this commit's description
76 77 # d, drop = remove commit from history
77 78 # m, mess = edit message without changing commit content
78 79 #
79 80 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 81 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
81 82 > pick 177f92b77385 2 c
82 83 > drop d2ae7f538514 1 b
83 84 > pick 055a42cdd887 3 d
84 85 > fold e860deea161a 4 e
85 86 > pick 652413bf663e 5 f
86 87 > EOF
87 88 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
88 89 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
89 90 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
90 91 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
91 92 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
92 93 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
93 94 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-backup.hg (glob)
94 95 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-backup.hg (glob)
95 96 $ hg log --graph
96 97 @ changeset: 3:cacdfd884a93
97 98 | bookmark: five
98 99 | tag: tip
99 100 | user: test
100 101 | date: Thu Jan 01 00:00:00 1970 +0000
101 102 | summary: f
102 103 |
103 104 o changeset: 2:59d9f330561f
104 105 | bookmark: four
105 106 | bookmark: three
106 107 | user: test
107 108 | date: Thu Jan 01 00:00:00 1970 +0000
108 109 | summary: d
109 110 |
110 111 o changeset: 1:b346ab9a313d
111 112 | bookmark: also-two
112 113 | bookmark: two
113 114 | user: test
114 115 | date: Thu Jan 01 00:00:00 1970 +0000
115 116 | summary: c
116 117 |
117 118 o changeset: 0:cb9a9f314b8b
118 119 bookmark: will-move-backwards
119 120 user: test
120 121 date: Thu Jan 01 00:00:00 1970 +0000
121 122 summary: a
122 123
123 124 $ HGEDITOR=cat hg histedit 1
124 125 pick b346ab9a313d 1 c
125 126 pick 59d9f330561f 2 d
126 127 pick cacdfd884a93 3 f
127 128
128 129 # Edit history between b346ab9a313d and cacdfd884a93
129 130 #
130 131 # Commits are listed from least to most recent
131 132 #
132 133 # Commands:
133 134 # p, pick = use commit
134 135 # e, edit = use commit, but stop for amending
135 136 # f, fold = use commit, but combine it with the one above
137 # r, roll = like fold, but discard this commit's description
136 138 # d, drop = remove commit from history
137 139 # m, mess = edit message without changing commit content
138 140 #
139 141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 142 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
141 143 > pick b346ab9a313d 1 c
142 144 > pick cacdfd884a93 3 f
143 145 > pick 59d9f330561f 2 d
144 146 > EOF
145 147 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
146 148 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
147 149 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
148 150 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-backup.hg (glob)
149 151
150 152 We expect 'five' to stay at tip, since the tipmost bookmark is most
151 153 likely the useful signal.
152 154
153 155 $ hg log --graph
154 156 @ changeset: 3:c04e50810e4b
155 157 | bookmark: five
156 158 | bookmark: four
157 159 | bookmark: three
158 160 | tag: tip
159 161 | user: test
160 162 | date: Thu Jan 01 00:00:00 1970 +0000
161 163 | summary: d
162 164 |
163 165 o changeset: 2:c13eb81022ca
164 166 | user: test
165 167 | date: Thu Jan 01 00:00:00 1970 +0000
166 168 | summary: f
167 169 |
168 170 o changeset: 1:b346ab9a313d
169 171 | bookmark: also-two
170 172 | bookmark: two
171 173 | user: test
172 174 | date: Thu Jan 01 00:00:00 1970 +0000
173 175 | summary: c
174 176 |
175 177 o changeset: 0:cb9a9f314b8b
176 178 bookmark: will-move-backwards
177 179 user: test
178 180 date: Thu Jan 01 00:00:00 1970 +0000
179 181 summary: a
180 182
@@ -1,382 +1,384
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > histedit=
6 6 > EOF
7 7
8 8 $ initrepo ()
9 9 > {
10 10 > hg init r
11 11 > cd r
12 12 > for x in a b c d e f ; do
13 13 > echo $x > $x
14 14 > hg add $x
15 15 > hg ci -m $x
16 16 > done
17 17 > }
18 18
19 19 $ initrepo
20 20
21 21 log before edit
22 22 $ hg log --graph
23 23 @ changeset: 5:652413bf663e
24 24 | tag: tip
25 25 | user: test
26 26 | date: Thu Jan 01 00:00:00 1970 +0000
27 27 | summary: f
28 28 |
29 29 o changeset: 4:e860deea161a
30 30 | user: test
31 31 | date: Thu Jan 01 00:00:00 1970 +0000
32 32 | summary: e
33 33 |
34 34 o changeset: 3:055a42cdd887
35 35 | user: test
36 36 | date: Thu Jan 01 00:00:00 1970 +0000
37 37 | summary: d
38 38 |
39 39 o changeset: 2:177f92b77385
40 40 | user: test
41 41 | date: Thu Jan 01 00:00:00 1970 +0000
42 42 | summary: c
43 43 |
44 44 o changeset: 1:d2ae7f538514
45 45 | user: test
46 46 | date: Thu Jan 01 00:00:00 1970 +0000
47 47 | summary: b
48 48 |
49 49 o changeset: 0:cb9a9f314b8b
50 50 user: test
51 51 date: Thu Jan 01 00:00:00 1970 +0000
52 52 summary: a
53 53
54 54
55 55 show the edit commands offered
56 56 $ HGEDITOR=cat hg histedit 177f92b77385
57 57 pick 177f92b77385 2 c
58 58 pick 055a42cdd887 3 d
59 59 pick e860deea161a 4 e
60 60 pick 652413bf663e 5 f
61 61
62 62 # Edit history between 177f92b77385 and 652413bf663e
63 63 #
64 64 # Commits are listed from least to most recent
65 65 #
66 66 # Commands:
67 67 # p, pick = use commit
68 68 # e, edit = use commit, but stop for amending
69 69 # f, fold = use commit, but combine it with the one above
70 # r, roll = like fold, but discard this commit's description
70 71 # d, drop = remove commit from history
71 72 # m, mess = edit message without changing commit content
72 73 #
73 74 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 75
75 76 edit the history
76 77 (use a hacky editor to check histedit-last-edit.txt backup)
77 78
78 79 $ EDITED="$TESTTMP/editedhistory"
79 80 $ cat > $EDITED <<EOF
80 81 > pick 177f92b77385 c
81 82 > pick e860deea161a e
82 83 > pick 652413bf663e f
83 84 > pick 055a42cdd887 d
84 85 > EOF
85 86 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
86 87 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
87 88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 89 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 90 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 91
91 92 rules should end up in .hg/histedit-last-edit.txt:
92 93 $ cat .hg/histedit-last-edit.txt
93 94 pick 177f92b77385 c
94 95 pick e860deea161a e
95 96 pick 652413bf663e f
96 97 pick 055a42cdd887 d
97 98
98 99 log after edit
99 100 $ hg log --graph
100 101 @ changeset: 5:07114f51870f
101 102 | tag: tip
102 103 | user: test
103 104 | date: Thu Jan 01 00:00:00 1970 +0000
104 105 | summary: d
105 106 |
106 107 o changeset: 4:8ade9693061e
107 108 | user: test
108 109 | date: Thu Jan 01 00:00:00 1970 +0000
109 110 | summary: f
110 111 |
111 112 o changeset: 3:d8249471110a
112 113 | user: test
113 114 | date: Thu Jan 01 00:00:00 1970 +0000
114 115 | summary: e
115 116 |
116 117 o changeset: 2:177f92b77385
117 118 | user: test
118 119 | date: Thu Jan 01 00:00:00 1970 +0000
119 120 | summary: c
120 121 |
121 122 o changeset: 1:d2ae7f538514
122 123 | user: test
123 124 | date: Thu Jan 01 00:00:00 1970 +0000
124 125 | summary: b
125 126 |
126 127 o changeset: 0:cb9a9f314b8b
127 128 user: test
128 129 date: Thu Jan 01 00:00:00 1970 +0000
129 130 summary: a
130 131
131 132
132 133 put things back
133 134
134 135 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
135 136 > pick 177f92b77385 c
136 137 > pick 07114f51870f d
137 138 > pick d8249471110a e
138 139 > pick 8ade9693061e f
139 140 > EOF
140 141 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
141 142 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 144 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
144 145
145 146 $ hg log --graph
146 147 @ changeset: 5:7eca9b5b1148
147 148 | tag: tip
148 149 | user: test
149 150 | date: Thu Jan 01 00:00:00 1970 +0000
150 151 | summary: f
151 152 |
152 153 o changeset: 4:915da888f2de
153 154 | user: test
154 155 | date: Thu Jan 01 00:00:00 1970 +0000
155 156 | summary: e
156 157 |
157 158 o changeset: 3:10517e47bbbb
158 159 | user: test
159 160 | date: Thu Jan 01 00:00:00 1970 +0000
160 161 | summary: d
161 162 |
162 163 o changeset: 2:177f92b77385
163 164 | user: test
164 165 | date: Thu Jan 01 00:00:00 1970 +0000
165 166 | summary: c
166 167 |
167 168 o changeset: 1:d2ae7f538514
168 169 | user: test
169 170 | date: Thu Jan 01 00:00:00 1970 +0000
170 171 | summary: b
171 172 |
172 173 o changeset: 0:cb9a9f314b8b
173 174 user: test
174 175 date: Thu Jan 01 00:00:00 1970 +0000
175 176 summary: a
176 177
177 178
178 179 slightly different this time
179 180
180 181 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
181 182 > pick 10517e47bbbb d
182 183 > pick 7eca9b5b1148 f
183 184 > pick 915da888f2de e
184 185 > pick 177f92b77385 c
185 186 > EOF
186 187 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
187 188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 190 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 191 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 192 $ hg log --graph
192 193 @ changeset: 5:38b92f448761
193 194 | tag: tip
194 195 | user: test
195 196 | date: Thu Jan 01 00:00:00 1970 +0000
196 197 | summary: c
197 198 |
198 199 o changeset: 4:de71b079d9ce
199 200 | user: test
200 201 | date: Thu Jan 01 00:00:00 1970 +0000
201 202 | summary: e
202 203 |
203 204 o changeset: 3:be9ae3a309c6
204 205 | user: test
205 206 | date: Thu Jan 01 00:00:00 1970 +0000
206 207 | summary: f
207 208 |
208 209 o changeset: 2:799205341b6b
209 210 | user: test
210 211 | date: Thu Jan 01 00:00:00 1970 +0000
211 212 | summary: d
212 213 |
213 214 o changeset: 1:d2ae7f538514
214 215 | user: test
215 216 | date: Thu Jan 01 00:00:00 1970 +0000
216 217 | summary: b
217 218 |
218 219 o changeset: 0:cb9a9f314b8b
219 220 user: test
220 221 date: Thu Jan 01 00:00:00 1970 +0000
221 222 summary: a
222 223
223 224
224 225 keep prevents stripping dead revs
225 226 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
226 227 > pick 799205341b6b d
227 228 > pick be9ae3a309c6 f
228 229 > pick 38b92f448761 c
229 230 > pick de71b079d9ce e
230 231 > EOF
231 232 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
232 233 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 234 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 235 $ hg log --graph
235 236 @ changeset: 7:803ef1c6fcfd
236 237 | tag: tip
237 238 | user: test
238 239 | date: Thu Jan 01 00:00:00 1970 +0000
239 240 | summary: e
240 241 |
241 242 o changeset: 6:ece0b8d93dda
242 243 | parent: 3:be9ae3a309c6
243 244 | user: test
244 245 | date: Thu Jan 01 00:00:00 1970 +0000
245 246 | summary: c
246 247 |
247 248 | o changeset: 5:38b92f448761
248 249 | | user: test
249 250 | | date: Thu Jan 01 00:00:00 1970 +0000
250 251 | | summary: c
251 252 | |
252 253 | o changeset: 4:de71b079d9ce
253 254 |/ user: test
254 255 | date: Thu Jan 01 00:00:00 1970 +0000
255 256 | summary: e
256 257 |
257 258 o changeset: 3:be9ae3a309c6
258 259 | user: test
259 260 | date: Thu Jan 01 00:00:00 1970 +0000
260 261 | summary: f
261 262 |
262 263 o changeset: 2:799205341b6b
263 264 | user: test
264 265 | date: Thu Jan 01 00:00:00 1970 +0000
265 266 | summary: d
266 267 |
267 268 o changeset: 1:d2ae7f538514
268 269 | user: test
269 270 | date: Thu Jan 01 00:00:00 1970 +0000
270 271 | summary: b
271 272 |
272 273 o changeset: 0:cb9a9f314b8b
273 274 user: test
274 275 date: Thu Jan 01 00:00:00 1970 +0000
275 276 summary: a
276 277
277 278
278 279 try with --rev
279 280 $ hg histedit --commands - --rev -2 2>&1 <<EOF | fixbundle
280 281 > pick de71b079d9ce e
281 282 > pick 38b92f448761 c
282 283 > EOF
283 284 abort: may not use changesets other than the ones listed
284 285 $ hg log --graph
285 286 @ changeset: 7:803ef1c6fcfd
286 287 | tag: tip
287 288 | user: test
288 289 | date: Thu Jan 01 00:00:00 1970 +0000
289 290 | summary: e
290 291 |
291 292 o changeset: 6:ece0b8d93dda
292 293 | parent: 3:be9ae3a309c6
293 294 | user: test
294 295 | date: Thu Jan 01 00:00:00 1970 +0000
295 296 | summary: c
296 297 |
297 298 | o changeset: 5:38b92f448761
298 299 | | user: test
299 300 | | date: Thu Jan 01 00:00:00 1970 +0000
300 301 | | summary: c
301 302 | |
302 303 | o changeset: 4:de71b079d9ce
303 304 |/ user: test
304 305 | date: Thu Jan 01 00:00:00 1970 +0000
305 306 | summary: e
306 307 |
307 308 o changeset: 3:be9ae3a309c6
308 309 | user: test
309 310 | date: Thu Jan 01 00:00:00 1970 +0000
310 311 | summary: f
311 312 |
312 313 o changeset: 2:799205341b6b
313 314 | user: test
314 315 | date: Thu Jan 01 00:00:00 1970 +0000
315 316 | summary: d
316 317 |
317 318 o changeset: 1:d2ae7f538514
318 319 | user: test
319 320 | date: Thu Jan 01 00:00:00 1970 +0000
320 321 | summary: b
321 322 |
322 323 o changeset: 0:cb9a9f314b8b
323 324 user: test
324 325 date: Thu Jan 01 00:00:00 1970 +0000
325 326 summary: a
326 327
327 328 Verify that revsetalias entries work with histedit:
328 329 $ cat >> $HGRCPATH <<EOF
329 330 > [revsetalias]
330 331 > grandparent(ARG) = p1(p1(ARG))
331 332 > EOF
332 333 $ echo extra commit >> c
333 334 $ hg ci -m 'extra commit to c'
334 335 $ HGEDITOR=cat hg histedit 'grandparent(.)'
335 336 pick ece0b8d93dda 6 c
336 337 pick 803ef1c6fcfd 7 e
337 338 pick 9c863c565126 8 extra commit to c
338 339
339 340 # Edit history between ece0b8d93dda and 9c863c565126
340 341 #
341 342 # Commits are listed from least to most recent
342 343 #
343 344 # Commands:
344 345 # p, pick = use commit
345 346 # e, edit = use commit, but stop for amending
346 347 # f, fold = use commit, but combine it with the one above
348 # r, roll = like fold, but discard this commit's description
347 349 # d, drop = remove commit from history
348 350 # m, mess = edit message without changing commit content
349 351 #
350 352 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 353
352 354 should also work if a commit message is missing
353 355 $ BUNDLE="$TESTDIR/missing-comment.hg"
354 356 $ hg init missing
355 357 $ cd missing
356 358 $ hg unbundle $BUNDLE
357 359 adding changesets
358 360 adding manifests
359 361 adding file changes
360 362 added 3 changesets with 3 changes to 1 files
361 363 (run 'hg update' to get a working copy)
362 364 $ hg co tip
363 365 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
364 366 $ hg log --graph
365 367 @ changeset: 2:bd22688093b3
366 368 | tag: tip
367 369 | user: Robert Altman <robert.altman@telventDTN.com>
368 370 | date: Mon Nov 28 16:40:04 2011 +0000
369 371 | summary: Update file.
370 372 |
371 373 o changeset: 1:3b3e956f9171
372 374 | user: Robert Altman <robert.altman@telventDTN.com>
373 375 | date: Mon Nov 28 16:37:57 2011 +0000
374 376 |
375 377 o changeset: 0:141947992243
376 378 user: Robert Altman <robert.altman@telventDTN.com>
377 379 date: Mon Nov 28 16:35:28 2011 +0000
378 380 summary: Checked in text file
379 381
380 382 $ hg histedit 0
381 383 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 384 $ cd ..
@@ -1,185 +1,347
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > histedit=
6 6 > EOF
7 7
8 8 $ initrepo ()
9 9 > {
10 10 > hg init $1
11 11 > cd $1
12 12 > for x in a b c d e f ; do
13 13 > echo $x$x$x$x$x > $x
14 14 > hg add $x
15 15 > done
16 16 > hg ci -m 'Initial commit'
17 17 > for x in a b c d e f ; do
18 18 > echo $x > $x
19 19 > hg ci -m $x
20 20 > done
21 21 > echo 'I can haz no commute' > e
22 22 > hg ci -m 'does not commute with e'
23 23 > cd ..
24 24 > }
25 25
26 26 $ initrepo r
27 27 $ cd r
28 28 Initial generation of the command files
29 29
30 30 $ EDITED="$TESTTMP/editedhistory"
31 31 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
32 32 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
33 33 $ hg log --template 'fold {node|short} {rev} {desc}\n' -r 7 >> $EDITED
34 34 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
35 35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
36 36 $ cat $EDITED
37 37 pick 65a9a84f33fd 3 c
38 38 pick 00f1c5383965 4 d
39 39 fold 39522b764e3d 7 does not commute with e
40 40 pick 7b4e2f4b7bcd 5 e
41 41 pick 500cac37a696 6 f
42 42
43 43 log before edit
44 44 $ hg log --graph
45 45 @ changeset: 7:39522b764e3d
46 46 | tag: tip
47 47 | user: test
48 48 | date: Thu Jan 01 00:00:00 1970 +0000
49 49 | summary: does not commute with e
50 50 |
51 51 o changeset: 6:500cac37a696
52 52 | user: test
53 53 | date: Thu Jan 01 00:00:00 1970 +0000
54 54 | summary: f
55 55 |
56 56 o changeset: 5:7b4e2f4b7bcd
57 57 | user: test
58 58 | date: Thu Jan 01 00:00:00 1970 +0000
59 59 | summary: e
60 60 |
61 61 o changeset: 4:00f1c5383965
62 62 | user: test
63 63 | date: Thu Jan 01 00:00:00 1970 +0000
64 64 | summary: d
65 65 |
66 66 o changeset: 3:65a9a84f33fd
67 67 | user: test
68 68 | date: Thu Jan 01 00:00:00 1970 +0000
69 69 | summary: c
70 70 |
71 71 o changeset: 2:da6535b52e45
72 72 | user: test
73 73 | date: Thu Jan 01 00:00:00 1970 +0000
74 74 | summary: b
75 75 |
76 76 o changeset: 1:c1f09da44841
77 77 | user: test
78 78 | date: Thu Jan 01 00:00:00 1970 +0000
79 79 | summary: a
80 80 |
81 81 o changeset: 0:1715188a53c7
82 82 user: test
83 83 date: Thu Jan 01 00:00:00 1970 +0000
84 84 summary: Initial commit
85 85
86 86
87 87 edit the history
88 88 $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle
89 89 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 90 merging e
91 91 warning: conflicts during merge.
92 92 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
93 93 Fix up the change and run hg histedit --continue
94 94
95 95 fix up
96 96 $ echo 'I can haz no commute' > e
97 97 $ hg resolve --mark e
98 98 (no more unresolved files)
99 99 $ cat > cat.py <<EOF
100 100 > import sys
101 101 > print open(sys.argv[1]).read()
102 102 > print
103 103 > print
104 104 > EOF
105 105 $ HGEDITOR="python cat.py" hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
106 106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107 d
108 108 ***
109 109 does not commute with e
110 110
111 111
112 112
113 113 HG: Enter commit message. Lines beginning with 'HG:' are removed.
114 114 HG: Leave message empty to abort commit.
115 115 HG: --
116 116 HG: user: test
117 117 HG: branch 'default'
118 118 HG: changed d
119 119 HG: changed e
120 120
121 121
122 122
123 123 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 124 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
125 125 merging e
126 126 warning: conflicts during merge.
127 127 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
128 128 Fix up the change and run hg histedit --continue
129 129
130 130 just continue this time
131 131 $ hg revert -r 'p1()' e
132 132 $ hg resolve --mark e
133 133 (no more unresolved files)
134 134 $ hg histedit --continue 2>&1 | fixbundle
135 135 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
136 136 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 137
138 138 log after edit
139 139 $ hg log --graph
140 140 @ changeset: 5:d9cf42e54966
141 141 | tag: tip
142 142 | user: test
143 143 | date: Thu Jan 01 00:00:00 1970 +0000
144 144 | summary: f
145 145 |
146 146 o changeset: 4:10486af2e984
147 147 | user: test
148 148 | date: Thu Jan 01 00:00:00 1970 +0000
149 149 | summary: d
150 150 |
151 151 o changeset: 3:65a9a84f33fd
152 152 | user: test
153 153 | date: Thu Jan 01 00:00:00 1970 +0000
154 154 | summary: c
155 155 |
156 156 o changeset: 2:da6535b52e45
157 157 | user: test
158 158 | date: Thu Jan 01 00:00:00 1970 +0000
159 159 | summary: b
160 160 |
161 161 o changeset: 1:c1f09da44841
162 162 | user: test
163 163 | date: Thu Jan 01 00:00:00 1970 +0000
164 164 | summary: a
165 165 |
166 166 o changeset: 0:1715188a53c7
167 167 user: test
168 168 date: Thu Jan 01 00:00:00 1970 +0000
169 169 summary: Initial commit
170 170
171 171
172 172 contents of e
173 173 $ hg cat e
174 174 I can haz no commute
175 175
176 176 manifest
177 177 $ hg manifest
178 178 a
179 179 b
180 180 c
181 181 d
182 182 e
183 183 f
184 184
185 185 $ cd ..
186
187 Repeat test using "roll", not "fold". "roll" folds in changes but drops message
188
189 $ initrepo r2
190 $ cd r2
191
192 Initial generation of the command files
193
194 $ EDITED="$TESTTMP/editedhistory.2"
195 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
196 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
197 $ hg log --template 'roll {node|short} {rev} {desc}\n' -r 7 >> $EDITED
198 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
199 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
200 $ cat $EDITED
201 pick 65a9a84f33fd 3 c
202 pick 00f1c5383965 4 d
203 roll 39522b764e3d 7 does not commute with e
204 pick 7b4e2f4b7bcd 5 e
205 pick 500cac37a696 6 f
206
207 log before edit
208 $ hg log --graph
209 @ changeset: 7:39522b764e3d
210 | tag: tip
211 | user: test
212 | date: Thu Jan 01 00:00:00 1970 +0000
213 | summary: does not commute with e
214 |
215 o changeset: 6:500cac37a696
216 | user: test
217 | date: Thu Jan 01 00:00:00 1970 +0000
218 | summary: f
219 |
220 o changeset: 5:7b4e2f4b7bcd
221 | user: test
222 | date: Thu Jan 01 00:00:00 1970 +0000
223 | summary: e
224 |
225 o changeset: 4:00f1c5383965
226 | user: test
227 | date: Thu Jan 01 00:00:00 1970 +0000
228 | summary: d
229 |
230 o changeset: 3:65a9a84f33fd
231 | user: test
232 | date: Thu Jan 01 00:00:00 1970 +0000
233 | summary: c
234 |
235 o changeset: 2:da6535b52e45
236 | user: test
237 | date: Thu Jan 01 00:00:00 1970 +0000
238 | summary: b
239 |
240 o changeset: 1:c1f09da44841
241 | user: test
242 | date: Thu Jan 01 00:00:00 1970 +0000
243 | summary: a
244 |
245 o changeset: 0:1715188a53c7
246 user: test
247 date: Thu Jan 01 00:00:00 1970 +0000
248 summary: Initial commit
249
250
251 edit the history
252 $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle
253 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 merging e
255 warning: conflicts during merge.
256 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
257 Fix up the change and run hg histedit --continue
258
259 fix up
260 $ echo 'I can haz no commute' > e
261 $ hg resolve --mark e
262 (no more unresolved files)
263 $ hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
264 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 merging e
268 warning: conflicts during merge.
269 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
270 Fix up the change and run hg histedit --continue
271
272 just continue this time
273 $ hg revert -r 'p1()' e
274 $ hg resolve --mark e
275 (no more unresolved files)
276 $ hg histedit --continue 2>&1 | fixbundle
277 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
279
280 log after edit
281 $ hg log --graph
282 @ changeset: 5:e7c4f5d4eb75
283 | tag: tip
284 | user: test
285 | date: Thu Jan 01 00:00:00 1970 +0000
286 | summary: f
287 |
288 o changeset: 4:803d1bb561fc
289 | user: test
290 | date: Thu Jan 01 00:00:00 1970 +0000
291 | summary: d
292 |
293 o changeset: 3:65a9a84f33fd
294 | user: test
295 | date: Thu Jan 01 00:00:00 1970 +0000
296 | summary: c
297 |
298 o changeset: 2:da6535b52e45
299 | user: test
300 | date: Thu Jan 01 00:00:00 1970 +0000
301 | summary: b
302 |
303 o changeset: 1:c1f09da44841
304 | user: test
305 | date: Thu Jan 01 00:00:00 1970 +0000
306 | summary: a
307 |
308 o changeset: 0:1715188a53c7
309 user: test
310 date: Thu Jan 01 00:00:00 1970 +0000
311 summary: Initial commit
312
313
314 contents of e
315 $ hg cat e
316 I can haz no commute
317
318 manifest
319 $ hg manifest
320 a
321 b
322 c
323 d
324 e
325 f
326
327 description is taken from rollup target commit
328
329 $ hg log --debug --rev 4
330 changeset: 4:803d1bb561fceac3129ec778db9da249a3106fc3
331 phase: draft
332 parent: 3:65a9a84f33fdeb1ad5679b3941ec885d2b24027b
333 parent: -1:0000000000000000000000000000000000000000
334 manifest: 4:b068a323d969f22af1296ec6a5ea9384cef437ac
335 user: test
336 date: Thu Jan 01 00:00:00 1970 +0000
337 files: d e
338 extra: branch=default
339 extra: histedit_source=00f1c53839651fa5c76d423606811ea5455a79d0,39522b764e3d26103f08bd1fa2ccd3e3d7dbcf4e
340 description:
341 d
342
343
344
345 done with repo r2
346
347 $ cd ..
@@ -1,366 +1,410
1 1 Test histedit extension: Fold commands
2 2 ======================================
3 3
4 4 This test file is dedicated to testing the fold command in non conflicting
5 5 case.
6 6
7 7 Initialization
8 8 ---------------
9 9
10 10
11 11 $ . "$TESTDIR/histedit-helpers.sh"
12 12
13 13 $ cat >> $HGRCPATH <<EOF
14 14 > [alias]
15 15 > logt = log --template '{rev}:{node|short} {desc|firstline}\n'
16 16 > [extensions]
17 17 > histedit=
18 18 > EOF
19 19
20 20
21 21 Simple folding
22 22 --------------------
23 23 $ initrepo ()
24 24 > {
25 25 > hg init r
26 26 > cd r
27 27 > for x in a b c d e f ; do
28 28 > echo $x > $x
29 29 > hg add $x
30 30 > hg ci -m $x
31 31 > done
32 32 > }
33 33
34 34 $ initrepo
35 35
36 36 log before edit
37 37 $ hg logt --graph
38 38 @ 5:652413bf663e f
39 39 |
40 40 o 4:e860deea161a e
41 41 |
42 42 o 3:055a42cdd887 d
43 43 |
44 44 o 2:177f92b77385 c
45 45 |
46 46 o 1:d2ae7f538514 b
47 47 |
48 48 o 0:cb9a9f314b8b a
49 49
50 50
51 51 $ hg histedit 177f92b77385 --commands - 2>&1 <<EOF | fixbundle
52 52 > pick e860deea161a e
53 53 > pick 652413bf663e f
54 54 > fold 177f92b77385 c
55 55 > pick 055a42cdd887 d
56 56 > EOF
57 57 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
58 58 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 59 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 60 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
61 61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 62 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 64
65 65 log after edit
66 66 $ hg logt --graph
67 67 @ 4:9c277da72c9b d
68 68 |
69 69 o 3:6de59d13424a f
70 70 |
71 71 o 2:ee283cb5f2d5 e
72 72 |
73 73 o 1:d2ae7f538514 b
74 74 |
75 75 o 0:cb9a9f314b8b a
76 76
77 77
78 78 post-fold manifest
79 79 $ hg manifest
80 80 a
81 81 b
82 82 c
83 83 d
84 84 e
85 85 f
86 86
87 87
88 88 check histedit_source
89 89
90 90 $ hg log --debug --rev 3
91 91 changeset: 3:6de59d13424a8a13acd3e975514aed29dd0d9b2d
92 92 phase: draft
93 93 parent: 2:ee283cb5f2d5955443f23a27b697a04339e9a39a
94 94 parent: -1:0000000000000000000000000000000000000000
95 95 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
96 96 user: test
97 97 date: Thu Jan 01 00:00:00 1970 +0000
98 98 files+: c f
99 99 extra: branch=default
100 100 extra: histedit_source=a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3,177f92b773850b59254aa5e923436f921b55483b
101 101 description:
102 102 f
103 103 ***
104 104 c
105 105
106 106
107 107
108 rollup will fold without preserving the folded commit's message
109
110 $ hg histedit d2ae7f538514 --commands - 2>&1 <<EOF | fixbundle
111 > pick d2ae7f538514 b
112 > roll ee283cb5f2d5 e
113 > pick 6de59d13424a f
114 > pick 9c277da72c9b d
115 > EOF
116 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
117 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
118 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
122
123 log after edit
124 $ hg logt --graph
125 @ 3:c4a9eb7989fc d
126 |
127 o 2:8e03a72b6f83 f
128 |
129 o 1:391ee782c689 b
130 |
131 o 0:cb9a9f314b8b a
132
133
134 description is taken from rollup target commit
135
136 $ hg log --debug --rev 1
137 changeset: 1:391ee782c68930be438ccf4c6a403daedbfbffa5
138 phase: draft
139 parent: 0:cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
140 parent: -1:0000000000000000000000000000000000000000
141 manifest: 1:b5e112a3a8354e269b1524729f0918662d847c38
142 user: test
143 date: Thu Jan 01 00:00:00 1970 +0000
144 files+: b e
145 extra: branch=default
146 extra: histedit_source=d2ae7f538514cd87c17547b0de4cea71fe1af9fb,ee283cb5f2d5955443f23a27b697a04339e9a39a
147 description:
148 b
149
150
151
108 152 check saving last-message.txt
109 153
110 154 $ cat > $TESTTMP/abortfolding.py <<EOF
111 155 > from mercurial import util
112 156 > def abortfolding(ui, repo, hooktype, **kwargs):
113 157 > ctx = repo[kwargs.get('node')]
114 158 > if set(ctx.files()) == set(['c', 'd', 'f']):
115 159 > return True # abort folding commit only
116 160 > ui.warn('allow non-folding commit\\n')
117 161 > EOF
118 162 $ cat > .hg/hgrc <<EOF
119 163 > [hooks]
120 164 > pretxncommit.abortfolding = python:$TESTTMP/abortfolding.py:abortfolding
121 165 > EOF
122 166
123 167 $ cat > $TESTTMP/editor.sh << EOF
124 168 > echo "==== before editing"
125 169 > cat \$1
126 170 > echo "===="
127 171 > echo "check saving last-message.txt" >> \$1
128 172 > EOF
129 173
130 174 $ rm -f .hg/last-message.txt
131 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 6de59d13424a --commands - 2>&1 <<EOF | fixbundle
132 > pick 6de59d13424a f
133 > fold 9c277da72c9b d
175 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 8e03a72b6f83 --commands - 2>&1 <<EOF | fixbundle
176 > pick 8e03a72b6f83 f
177 > fold c4a9eb7989fc d
134 178 > EOF
135 179 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
136 180 allow non-folding commit
137 181 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
138 182 ==== before editing
139 183 f
140 184 ***
141 185 c
142 186 ***
143 187 d
144 188
145 189
146 190
147 191 HG: Enter commit message. Lines beginning with 'HG:' are removed.
148 192 HG: Leave message empty to abort commit.
149 193 HG: --
150 194 HG: user: test
151 195 HG: branch 'default'
152 196 HG: changed c
153 197 HG: changed d
154 198 HG: changed f
155 199 ====
156 200 transaction abort!
157 201 rollback completed
158 202 abort: pretxncommit.abortfolding hook failed
159 203
160 204 $ cat .hg/last-message.txt
161 205 f
162 206 ***
163 207 c
164 208 ***
165 209 d
166 210
167 211
168 212
169 213 check saving last-message.txt
170 214
171 215 $ cd ..
172 216
173 217 folding and creating no new change doesn't break:
174 218 -------------------------------------------------
175 219
176 220 folded content is dropped during a merge. The folded commit should properly disappear.
177 221
178 222 $ mkdir fold-to-empty-test
179 223 $ cd fold-to-empty-test
180 224 $ hg init
181 225 $ printf "1\n2\n3\n" > file
182 226 $ hg add file
183 227 $ hg commit -m '1+2+3'
184 228 $ echo 4 >> file
185 229 $ hg commit -m '+4'
186 230 $ echo 5 >> file
187 231 $ hg commit -m '+5'
188 232 $ echo 6 >> file
189 233 $ hg commit -m '+6'
190 234 $ hg logt --graph
191 235 @ 3:251d831eeec5 +6
192 236 |
193 237 o 2:888f9082bf99 +5
194 238 |
195 239 o 1:617f94f13c0f +4
196 240 |
197 241 o 0:0189ba417d34 1+2+3
198 242
199 243
200 244 $ hg histedit 1 --commands - << EOF
201 245 > pick 617f94f13c0f 1 +4
202 246 > drop 888f9082bf99 2 +5
203 247 > fold 251d831eeec5 3 +6
204 248 > EOF
205 249 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 250 merging file
207 251 warning: conflicts during merge.
208 252 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
209 253 Fix up the change and run hg histedit --continue
210 254 [1]
211 255 There were conflicts, we keep P1 content. This
212 256 should effectively drop the changes from +6.
213 257 $ hg status
214 258 M file
215 259 ? file.orig
216 260 $ hg resolve -l
217 261 U file
218 262 $ hg revert -r 'p1()' file
219 263 $ hg resolve --mark file
220 264 (no more unresolved files)
221 265 $ hg histedit --continue
222 266 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 267 saved backup bundle to $TESTTMP/*-backup.hg (glob)
224 268 $ hg logt --graph
225 269 @ 1:617f94f13c0f +4
226 270 |
227 271 o 0:0189ba417d34 1+2+3
228 272
229 273
230 274 $ cd ..
231 275
232 276
233 277 Test fold through dropped
234 278 -------------------------
235 279
236 280
237 281 Test corner case where folded revision is separated from its parent by a
238 282 dropped revision.
239 283
240 284
241 285 $ hg init fold-with-dropped
242 286 $ cd fold-with-dropped
243 287 $ printf "1\n2\n3\n" > file
244 288 $ hg commit -Am '1+2+3'
245 289 adding file
246 290 $ echo 4 >> file
247 291 $ hg commit -m '+4'
248 292 $ echo 5 >> file
249 293 $ hg commit -m '+5'
250 294 $ echo 6 >> file
251 295 $ hg commit -m '+6'
252 296 $ hg logt -G
253 297 @ 3:251d831eeec5 +6
254 298 |
255 299 o 2:888f9082bf99 +5
256 300 |
257 301 o 1:617f94f13c0f +4
258 302 |
259 303 o 0:0189ba417d34 1+2+3
260 304
261 305 $ hg histedit 1 --commands - << EOF
262 306 > pick 617f94f13c0f 1 +4
263 307 > drop 888f9082bf99 2 +5
264 308 > fold 251d831eeec5 3 +6
265 309 > EOF
266 310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 311 merging file
268 312 warning: conflicts during merge.
269 313 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
270 314 Fix up the change and run hg histedit --continue
271 315 [1]
272 316 $ cat > file << EOF
273 317 > 1
274 318 > 2
275 319 > 3
276 320 > 4
277 321 > 5
278 322 > EOF
279 323 $ hg resolve --mark file
280 324 (no more unresolved files)
281 325 $ hg commit -m '+5.2'
282 326 created new head
283 327 $ echo 6 >> file
284 328 $ HGEDITOR=cat hg histedit --continue
285 329 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
286 330 +4
287 331 ***
288 332 +5.2
289 333 ***
290 334 +6
291 335
292 336
293 337
294 338 HG: Enter commit message. Lines beginning with 'HG:' are removed.
295 339 HG: Leave message empty to abort commit.
296 340 HG: --
297 341 HG: user: test
298 342 HG: branch 'default'
299 343 HG: changed file
300 344 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
301 345 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
302 346 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-backup.hg (glob)
303 347 $ hg logt -G
304 348 @ 1:10c647b2cdd5 +4
305 349 |
306 350 o 0:0189ba417d34 1+2+3
307 351
308 352 $ hg export tip
309 353 # HG changeset patch
310 354 # User test
311 355 # Date 0 0
312 356 # Thu Jan 01 00:00:00 1970 +0000
313 357 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
314 358 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
315 359 +4
316 360 ***
317 361 +5.2
318 362 ***
319 363 +6
320 364
321 365 diff -r 0189ba417d34 -r 10c647b2cdd5 file
322 366 --- a/file Thu Jan 01 00:00:00 1970 +0000
323 367 +++ b/file Thu Jan 01 00:00:00 1970 +0000
324 368 @@ -1,3 +1,6 @@
325 369 1
326 370 2
327 371 3
328 372 +4
329 373 +5
330 374 +6
331 375 $ cd ..
332 376
333 377
334 378 Folding with initial rename (issue3729)
335 379 ---------------------------------------
336 380
337 381 $ hg init fold-rename
338 382 $ cd fold-rename
339 383 $ echo a > a.txt
340 384 $ hg add a.txt
341 385 $ hg commit -m a
342 386 $ hg rename a.txt b.txt
343 387 $ hg commit -m rename
344 388 $ echo b >> b.txt
345 389 $ hg commit -m b
346 390
347 391 $ hg logt --follow b.txt
348 392 2:e0371e0426bc b
349 393 1:1c4f440a8085 rename
350 394 0:6c795aa153cb a
351 395
352 396 $ hg histedit 1c4f440a8085 --commands - 2>&1 << EOF | fixbundle
353 397 > pick 1c4f440a8085 rename
354 398 > fold e0371e0426bc b
355 399 > EOF
356 400 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 401 reverting b.txt
358 402 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
359 403 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
360 404 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
361 405
362 406 $ hg logt --follow b.txt
363 407 1:cf858d235c76 rename
364 408 0:6c795aa153cb a
365 409
366 410 $ cd ..
@@ -1,462 +1,463
1 1 $ . "$TESTDIR/histedit-helpers.sh"
2 2
3 3 Enable obsolete
4 4
5 5 $ cat > ${TESTTMP}/obs.py << EOF
6 6 > import mercurial.obsolete
7 7 > mercurial.obsolete._enabled = True
8 8 > EOF
9 9
10 10 $ cat >> $HGRCPATH << EOF
11 11 > [ui]
12 12 > logtemplate= {rev}:{node|short} {desc|firstline}
13 13 > [phases]
14 14 > publish=False
15 15 > [extensions]'
16 16 > histedit=
17 17 > rebase=
18 18 >
19 19 > obs=${TESTTMP}/obs.py
20 20 > EOF
21 21
22 22 $ hg init base
23 23 $ cd base
24 24
25 25 $ for x in a b c d e f ; do
26 26 > echo $x > $x
27 27 > hg add $x
28 28 > hg ci -m $x
29 29 > done
30 30
31 31 $ hg log --graph
32 32 @ 5:652413bf663e f
33 33 |
34 34 o 4:e860deea161a e
35 35 |
36 36 o 3:055a42cdd887 d
37 37 |
38 38 o 2:177f92b77385 c
39 39 |
40 40 o 1:d2ae7f538514 b
41 41 |
42 42 o 0:cb9a9f314b8b a
43 43
44 44
45 45 $ HGEDITOR=cat hg histedit 1
46 46 pick d2ae7f538514 1 b
47 47 pick 177f92b77385 2 c
48 48 pick 055a42cdd887 3 d
49 49 pick e860deea161a 4 e
50 50 pick 652413bf663e 5 f
51 51
52 52 # Edit history between d2ae7f538514 and 652413bf663e
53 53 #
54 54 # Commits are listed from least to most recent
55 55 #
56 56 # Commands:
57 57 # p, pick = use commit
58 58 # e, edit = use commit, but stop for amending
59 59 # f, fold = use commit, but combine it with the one above
60 # r, roll = like fold, but discard this commit's description
60 61 # d, drop = remove commit from history
61 62 # m, mess = edit message without changing commit content
62 63 #
63 64 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 65 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
65 66 > pick 177f92b77385 2 c
66 67 > drop d2ae7f538514 1 b
67 68 > pick 055a42cdd887 3 d
68 69 > fold e860deea161a 4 e
69 70 > pick 652413bf663e 5 f
70 71 > EOF
71 72 saved backup bundle to $TESTTMP/base/.hg/strip-backup/96e494a2d553-backup.hg (glob)
72 73 $ hg log --graph --hidden
73 74 @ 8:cacdfd884a93 f
74 75 |
75 76 o 7:59d9f330561f d
76 77 |
77 78 o 6:b346ab9a313d c
78 79 |
79 80 | x 5:652413bf663e f
80 81 | |
81 82 | x 4:e860deea161a e
82 83 | |
83 84 | x 3:055a42cdd887 d
84 85 | |
85 86 | x 2:177f92b77385 c
86 87 | |
87 88 | x 1:d2ae7f538514 b
88 89 |/
89 90 o 0:cb9a9f314b8b a
90 91
91 92 $ hg debugobsolete
92 93 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob)
93 94 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 {'date': '* *', 'user': 'test'} (glob)
94 95 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
95 96 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
96 97 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 {'date': '* *', 'user': 'test'} (glob)
97 98
98 99
99 100 Ensure hidden revision does not prevent histedit
100 101 -------------------------------------------------
101 102
102 103 create an hidden revision
103 104
104 105 $ hg histedit 6 --commands - << EOF
105 106 > pick b346ab9a313d 6 c
106 107 > drop 59d9f330561f 7 d
107 108 > pick cacdfd884a93 8 f
108 109 > EOF
109 110 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
110 111 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 112 $ hg log --graph
112 113 @ 9:c13eb81022ca f
113 114 |
114 115 o 6:b346ab9a313d c
115 116 |
116 117 o 0:cb9a9f314b8b a
117 118
118 119 check hidden revision are ignored (6 have hidden children 7 and 8)
119 120
120 121 $ hg histedit 6 --commands - << EOF
121 122 > pick b346ab9a313d 6 c
122 123 > pick c13eb81022ca 8 f
123 124 > EOF
124 125 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
125 126
126 127
127 128
128 129 Test that rewriting leaving instability behind is allowed
129 130 ---------------------------------------------------------------------
130 131
131 132 $ hg up '.^'
132 133 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 134 $ hg log -r 'children(.)'
134 135 9:c13eb81022ca f (no-eol)
135 136 $ hg histedit -r '.' --commands - <<EOF
136 137 > edit b346ab9a313d 6 c
137 138 > EOF
138 139 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
139 140 adding c
140 141 Make changes as needed, you may commit or record as needed now.
141 142 When you are finished, run hg histedit --continue to resume.
142 143 [1]
143 144 $ echo c >> c
144 145 $ hg histedit --continue
145 146 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 147
147 148 $ hg log -r 'unstable()'
148 149 9:c13eb81022ca f (no-eol)
149 150
150 151 stabilise
151 152
152 153 $ hg rebase -r 'unstable()' -d .
153 154 $ hg up tip -q
154 155
155 156 Test dropping of changeset on the top of the stack
156 157 -------------------------------------------------------
157 158
158 159 Nothing is rewritten below, the working directory parent must be change for the
159 160 dropped changeset to be hidden.
160 161
161 162 $ cd ..
162 163 $ hg clone base droplast
163 164 updating to branch default
164 165 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 166 $ cd droplast
166 167 $ hg histedit -r '40db8afa467b' --commands - << EOF
167 168 > pick 40db8afa467b 10 c
168 169 > drop b449568bf7fc 11 f
169 170 > EOF
170 171 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
171 172 $ hg log -G
172 173 @ 10:40db8afa467b c
173 174 |
174 175 o 0:cb9a9f314b8b a
175 176
176 177
177 178 With rewritten ancestors
178 179
179 180 $ echo e > e
180 181 $ hg add e
181 182 $ hg commit -m g
182 183 $ echo f > f
183 184 $ hg add f
184 185 $ hg commit -m h
185 186 $ hg histedit -r '40db8afa467b' --commands - << EOF
186 187 > pick 47a8561c0449 12 g
187 188 > pick 40db8afa467b 10 c
188 189 > drop 1b3b05f35ff0 13 h
189 190 > EOF
190 191 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
191 192 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 193 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 194 $ hg log -G
194 195 @ 15:ee6544123ab8 c
195 196 |
196 197 o 14:269e713e9eae g
197 198 |
198 199 o 0:cb9a9f314b8b a
199 200
200 201 $ cd ../base
201 202
202 203
203 204
204 205 Test phases support
205 206 ===========================================
206 207
207 208 Check that histedit respect immutability
208 209 -------------------------------------------
209 210
210 211 $ cat >> $HGRCPATH << EOF
211 212 > [ui]
212 213 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
213 214 > EOF
214 215
215 216 $ hg ph -pv '.^'
216 217 phase changed for 2 changesets
217 218 $ hg log -G
218 219 @ 11:b449568bf7fc (draft) f
219 220 |
220 221 o 10:40db8afa467b (public) c
221 222 |
222 223 o 0:cb9a9f314b8b (public) a
223 224
224 225 $ hg histedit -r '.~2'
225 226 abort: cannot edit immutable changeset: cb9a9f314b8b
226 227 [255]
227 228
228 229
229 230 Prepare further testing
230 231 -------------------------------------------
231 232
232 233 $ for x in g h i j k ; do
233 234 > echo $x > $x
234 235 > hg add $x
235 236 > hg ci -m $x
236 237 > done
237 238 $ hg phase --force --secret .~2
238 239 $ hg log -G
239 240 @ 16:ee118ab9fa44 (secret) k
240 241 |
241 242 o 15:3a6c53ee7f3d (secret) j
242 243 |
243 244 o 14:b605fb7503f2 (secret) i
244 245 |
245 246 o 13:7395e1ff83bd (draft) h
246 247 |
247 248 o 12:6b70183d2492 (draft) g
248 249 |
249 250 o 11:b449568bf7fc (draft) f
250 251 |
251 252 o 10:40db8afa467b (public) c
252 253 |
253 254 o 0:cb9a9f314b8b (public) a
254 255
255 256 $ cd ..
256 257
257 258 simple phase conservation
258 259 -------------------------------------------
259 260
260 261 Resulting changeset should conserve the phase of the original one whatever the
261 262 phases.new-commit option is.
262 263
263 264 New-commit as draft (default)
264 265
265 266 $ cp -r base simple-draft
266 267 $ cd simple-draft
267 268 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
268 269 > edit b449568bf7fc 11 f
269 270 > pick 6b70183d2492 12 g
270 271 > pick 7395e1ff83bd 13 h
271 272 > pick b605fb7503f2 14 i
272 273 > pick 3a6c53ee7f3d 15 j
273 274 > pick ee118ab9fa44 16 k
274 275 > EOF
275 276 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
276 277 adding f
277 278 Make changes as needed, you may commit or record as needed now.
278 279 When you are finished, run hg histedit --continue to resume.
279 280 [1]
280 281 $ echo f >> f
281 282 $ hg histedit --continue
282 283 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 284 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 285 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 286 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
286 287 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 288 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 289 $ hg log -G
289 290 @ 22:12e89af74238 (secret) k
290 291 |
291 292 o 21:636a8687b22e (secret) j
292 293 |
293 294 o 20:ccaf0a38653f (secret) i
294 295 |
295 296 o 19:11a89d1c2613 (draft) h
296 297 |
297 298 o 18:c1dec7ca82ea (draft) g
298 299 |
299 300 o 17:087281e68428 (draft) f
300 301 |
301 302 o 10:40db8afa467b (public) c
302 303 |
303 304 o 0:cb9a9f314b8b (public) a
304 305
305 306 $ cd ..
306 307
307 308
308 309 New-commit as draft (default)
309 310
310 311 $ cp -r base simple-secret
311 312 $ cd simple-secret
312 313 $ cat >> .hg/hgrc << EOF
313 314 > [phases]
314 315 > new-commit=secret
315 316 > EOF
316 317 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
317 318 > edit b449568bf7fc 11 f
318 319 > pick 6b70183d2492 12 g
319 320 > pick 7395e1ff83bd 13 h
320 321 > pick b605fb7503f2 14 i
321 322 > pick 3a6c53ee7f3d 15 j
322 323 > pick ee118ab9fa44 16 k
323 324 > EOF
324 325 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
325 326 adding f
326 327 Make changes as needed, you may commit or record as needed now.
327 328 When you are finished, run hg histedit --continue to resume.
328 329 [1]
329 330 $ echo f >> f
330 331 $ hg histedit --continue
331 332 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 333 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 334 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 335 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 336 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 337 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 338 $ hg log -G
338 339 @ 22:12e89af74238 (secret) k
339 340 |
340 341 o 21:636a8687b22e (secret) j
341 342 |
342 343 o 20:ccaf0a38653f (secret) i
343 344 |
344 345 o 19:11a89d1c2613 (draft) h
345 346 |
346 347 o 18:c1dec7ca82ea (draft) g
347 348 |
348 349 o 17:087281e68428 (draft) f
349 350 |
350 351 o 10:40db8afa467b (public) c
351 352 |
352 353 o 0:cb9a9f314b8b (public) a
353 354
354 355 $ cd ..
355 356
356 357
357 358 Changeset reordering
358 359 -------------------------------------------
359 360
360 361 If a secret changeset is put before a draft one, all descendant should be secret.
361 362 It seems more important to present the secret phase.
362 363
363 364 $ cp -r base reorder
364 365 $ cd reorder
365 366 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
366 367 > pick b449568bf7fc 11 f
367 368 > pick 3a6c53ee7f3d 15 j
368 369 > pick 6b70183d2492 12 g
369 370 > pick b605fb7503f2 14 i
370 371 > pick 7395e1ff83bd 13 h
371 372 > pick ee118ab9fa44 16 k
372 373 > EOF
373 374 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
374 375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 377 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 378 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 379 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
379 380 $ hg log -G
380 381 @ 21:558246857888 (secret) k
381 382 |
382 383 o 20:28bd44768535 (secret) h
383 384 |
384 385 o 19:d5395202aeb9 (secret) i
385 386 |
386 387 o 18:21edda8e341b (secret) g
387 388 |
388 389 o 17:5ab64f3a4832 (secret) j
389 390 |
390 391 o 11:b449568bf7fc (draft) f
391 392 |
392 393 o 10:40db8afa467b (public) c
393 394 |
394 395 o 0:cb9a9f314b8b (public) a
395 396
396 397 $ cd ..
397 398
398 399 Changeset folding
399 400 -------------------------------------------
400 401
401 402 Folding a secret changeset with a draft one turn the result secret (again,
402 403 better safe than sorry). Folding between same phase changeset still works
403 404
404 405 Note that there is a few reordering in this series for more extensive test
405 406
406 407 $ cp -r base folding
407 408 $ cd folding
408 409 $ cat >> .hg/hgrc << EOF
409 410 > [phases]
410 411 > new-commit=secret
411 412 > EOF
412 413 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
413 414 > pick 7395e1ff83bd 13 h
414 415 > fold b449568bf7fc 11 f
415 416 > pick 6b70183d2492 12 g
416 417 > fold 3a6c53ee7f3d 15 j
417 418 > pick b605fb7503f2 14 i
418 419 > fold ee118ab9fa44 16 k
419 420 > EOF
420 421 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
421 422 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
422 423 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
423 424 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 425 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 426 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 427 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
427 428 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 429 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 430 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 431 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
431 432 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 433 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 434 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/58019c66f35f-backup.hg (glob)
434 435 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/83d1858e070b-backup.hg (glob)
435 436 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/859969f5ed7e-backup.hg (glob)
436 437 $ hg log -G
437 438 @ 19:f9daec13fb98 (secret) i
438 439 |
439 440 o 18:49807617f46a (secret) g
440 441 |
441 442 o 17:050280826e04 (draft) h
442 443 |
443 444 o 10:40db8afa467b (public) c
444 445 |
445 446 o 0:cb9a9f314b8b (public) a
446 447
447 448 $ hg co 18
448 449 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
449 450 $ echo wat >> wat
450 451 $ hg add wat
451 452 $ hg ci -m 'add wat'
452 453 created new head
453 454 $ hg merge 19
454 455 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 456 (branch merge, don't forget to commit)
456 457 $ hg ci -m 'merge'
457 458 $ echo not wat > wat
458 459 $ hg ci -m 'modify wat'
459 460 $ hg histedit 17
460 461 abort: cannot edit history that contains merges
461 462 [255]
462 463 $ cd ..
@@ -1,144 +1,147
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > histedit=
4 4 > EOF
5 5
6 6 $ initrepos ()
7 7 > {
8 8 > hg init r
9 9 > cd r
10 10 > for x in a b c ; do
11 11 > echo $x > $x
12 12 > hg add $x
13 13 > hg ci -m $x
14 14 > done
15 15 > cd ..
16 16 > hg clone r r2 | grep -v updating
17 17 > cd r2
18 18 > for x in d e f ; do
19 19 > echo $x > $x
20 20 > hg add $x
21 21 > hg ci -m $x
22 22 > done
23 23 > cd ..
24 24 > hg init r3
25 25 > cd r3
26 26 > for x in g h i ; do
27 27 > echo $x > $x
28 28 > hg add $x
29 29 > hg ci -m $x
30 30 > done
31 31 > cd ..
32 32 > }
33 33
34 34 $ initrepos
35 35 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 36
37 37 show the edit commands offered by outgoing
38 38 $ cd r2
39 39 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
40 40 pick 055a42cdd887 3 d
41 41 pick e860deea161a 4 e
42 42 pick 652413bf663e 5 f
43 43
44 44 # Edit history between 055a42cdd887 and 652413bf663e
45 45 #
46 46 # Commits are listed from least to most recent
47 47 #
48 48 # Commands:
49 49 # p, pick = use commit
50 50 # e, edit = use commit, but stop for amending
51 51 # f, fold = use commit, but combine it with the one above
52 # r, roll = like fold, but discard this commit's description
52 53 # d, drop = remove commit from history
53 54 # m, mess = edit message without changing commit content
54 55 #
55 56 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 57 $ cd ..
57 58
58 59 show the error from unrelated repos
59 60 $ cd r3
60 61 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
61 62 abort: repository is unrelated
62 63 [1]
63 64 $ cd ..
64 65
65 66 show the error from unrelated repos
66 67 $ cd r3
67 68 $ HGEDITOR=cat hg histedit --force --outgoing ../r
68 69 comparing with ../r
69 70 searching for changes
70 71 warning: repository is unrelated
71 72 pick 2a4042b45417 0 g
72 73 pick 68c46b4927ce 1 h
73 74 pick 51281e65ba79 2 i
74 75
75 76 # Edit history between 2a4042b45417 and 51281e65ba79
76 77 #
77 78 # Commits are listed from least to most recent
78 79 #
79 80 # Commands:
80 81 # p, pick = use commit
81 82 # e, edit = use commit, but stop for amending
82 83 # f, fold = use commit, but combine it with the one above
84 # r, roll = like fold, but discard this commit's description
83 85 # d, drop = remove commit from history
84 86 # m, mess = edit message without changing commit content
85 87 #
86 88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 89 $ cd ..
88 90
89 91 test sensitivity to branch in URL:
90 92
91 93 $ cd r2
92 94 $ hg -q update 2
93 95 $ hg -q branch foo
94 96 $ hg commit -m 'create foo branch'
95 97 $ HGEDITOR=cat hg histedit --outgoing '../r#foo' | grep -v comparing | grep -v searching
96 98 pick f26599ee3441 6 create foo branch
97 99
98 100 # Edit history between f26599ee3441 and f26599ee3441
99 101 #
100 102 # Commits are listed from least to most recent
101 103 #
102 104 # Commands:
103 105 # p, pick = use commit
104 106 # e, edit = use commit, but stop for amending
105 107 # f, fold = use commit, but combine it with the one above
108 # r, roll = like fold, but discard this commit's description
106 109 # d, drop = remove commit from history
107 110 # m, mess = edit message without changing commit content
108 111 #
109 112 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 113
111 114 test to check number of roots in outgoing revisions
112 115
113 116 $ hg -q outgoing -G --template '{node|short}({branch})' '../r'
114 117 @ f26599ee3441(foo)
115 118
116 119 o 652413bf663e(default)
117 120 |
118 121 o e860deea161a(default)
119 122 |
120 123 o 055a42cdd887(default)
121 124
122 125 $ HGEDITOR=cat hg -q histedit --outgoing '../r'
123 126 abort: there are ambiguous outgoing revisions
124 127 (see "hg help histedit" for more detail)
125 128 [255]
126 129
127 130 $ hg -q update -C 2
128 131 $ echo aa >> a
129 132 $ hg -q commit -m 'another head on default'
130 133 $ hg -q outgoing -G --template '{node|short}({branch})' '../r#default'
131 134 @ 3879dc049647(default)
132 135
133 136 o 652413bf663e(default)
134 137 |
135 138 o e860deea161a(default)
136 139 |
137 140 o 055a42cdd887(default)
138 141
139 142 $ HGEDITOR=cat hg -q histedit --outgoing '../r#default'
140 143 abort: there are ambiguous outgoing revisions
141 144 (see "hg help histedit" for more detail)
142 145 [255]
143 146
144 147 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now