# HG changeset patch # User Gilles Moris # Date 1284107298 -7200 # Node ID 52971985be14f12930a9809d375b97e1ee77d21a # Parent 61c0df2b089a4fb98dcf11bda60eba449f898db2 backout: provide linear backout as a default (without --merge option) This changes backouts changeset to retain linear history, .e. it is committed as a child of the working directory parent, not the reverted changeset parent. The default behavior was previously to just commit a reverted change as a child of the backed out changeset - thus creating a new head. Most of the time, you would use the --merge option, as it does not make sense to keep this dangling head as is. The previous behavior could be obtained by using 'hg update --clean .' after a 'hg backout --merge'. The --merge option itself is not affected by this change. There is also still an autocommit of the backout if a merge is not needed, i.e. in case the backout is the parent of the working directory. Previously we had (pwd = parent of the working directory): pwd older backout auto merge backout --merge auto commit With the new linear approach: pwd older backout auto commit backout --merge auto commit auto: commit done by the backout command merge: backout also already committed but explicit merge and commit needed commit: user need to commit the update/merge diff -r 61c0df2b089a -r 52971985be14 mercurial/commands.py --- a/mercurial/commands.py Mon Oct 11 10:07:42 2010 -0500 +++ b/mercurial/commands.py Fri Sep 10 10:28:18 2010 +0200 @@ -204,17 +204,26 @@ def backout(ui, repo, node=None, rev=None, **opts): '''reverse effect of earlier changeset - Commit the backed out changes as a new changeset. The new - changeset is a child of the backed out changeset. - - If you backout a changeset other than the tip, a new head is - created. This head will be the new tip and you should merge this - backout changeset with another head. - + The backout command merges the reverse effect of the reverted + changeset into the working directory. + + With the --merge option, it first commits the reverted changes + as a new changeset. This new changeset is a child of the reverted + changeset. The --merge option remembers the parent of the working directory before starting the backout, then merges the new head with that - changeset afterwards. This saves you from doing the merge by hand. - The result of this merge is not committed, as with a normal merge. + changeset afterwards. + This will result in an explicit merge in the history. + + If you backout a changeset other than the original parent of the + working directory, the result of this merge is not committed, + as with a normal merge. Otherwise, no merge is needed and the + commit is automatic. + + Note that the default behavior (without --merge) has changed in + version 1.7. To restore the previous default behavior, use + :hg:`backout --merge` and then :hg:`update --clean .` to get rid of + the ongoing merge. See :hg:`help dates` for a list of formats valid for -d/--date. @@ -268,6 +277,9 @@ revert_opts['rev'] = hex(parent) revert_opts['no_backup'] = None revert(ui, repo, **revert_opts) + if not opts.get('merge') and op1 != node: + return hg.update(repo, op1) + commit_opts = opts.copy() commit_opts['addremove'] = False if not commit_opts['message'] and not commit_opts['logfile']: @@ -279,17 +291,12 @@ return '%d:%s' % (repo.changelog.rev(node), short(node)) ui.status(_('changeset %s backs out changeset %s\n') % (nice(repo.changelog.tip()), nice(node))) - if op1 != node: + if opts.get('merge') and op1 != node: hg.clean(repo, op1, show_stats=False) - if opts.get('merge'): - ui.status(_('merging with changeset %s\n') - % nice(repo.changelog.tip())) - hg.merge(repo, hex(repo.changelog.tip())) - else: - ui.status(_('the backout changeset is a new head - ' - 'do not forget to merge\n')) - ui.status(_('(use "backout --merge" ' - 'if you want to auto-merge)\n')) + ui.status(_('merging with changeset %s\n') + % nice(repo.changelog.tip())) + return hg.merge(repo, hex(repo.changelog.tip())) + return 0 def bisect(ui, repo, rev=None, extra=None, command=None, reset=None, good=None, bad=None, skip=None, noupdate=None): diff -r 61c0df2b089a -r 52971985be14 tests/test-backout.t --- a/tests/test-backout.t Mon Oct 11 10:07:42 2010 -0500 +++ b/tests/test-backout.t Fri Sep 10 10:28:18 2010 +0200 @@ -39,7 +39,7 @@ $ hg rm a $ hg commit -d '1 0' -m b - $ hg backout -d '2 0' --merge tip + $ hg backout -d '2 0' tip adding a changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372 $ cat a @@ -131,12 +131,26 @@ $ echo 1 > b $ hg commit -d '2 0' -A -m c adding b + +without --merge $ hg backout -d '3 0' 1 reverting a + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg locate b + b + $ hg update -C tip + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg locate b + b + +with --merge + $ hg backout --merge -d '3 0' 1 + reverting a created new head changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5 - the backout changeset is a new head - do not forget to merge - (use "backout --merge" if you want to auto-merge) + merging with changeset 3:3202beb76721 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) $ hg locate b b $ hg update -C tip @@ -220,14 +234,28 @@ $ echo branch2 > file2 $ hg ci -d '2 0' -Am file2 adding file2 - $ hg backout -d '3 0' -r 1 -m 'backout on branch1' + +without --merge + $ hg backout -r 1 + removing file1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg branch + branch2 + $ hg status -A + R file1 + C default + C file2 + +with --merge + $ hg update -qC + $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' removing file1 created new head changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3 - the backout changeset is a new head - do not forget to merge - (use "backout --merge" if you want to auto-merge) - -XXX maybe backout shouldn't suggest a merge here as it is a different branch? + merging with changeset 3:d4e8f6db59fb + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg update -q -C 2 on branch2 with branch1 not merged, so file1 should still exist: