diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1583,6 +1583,7 @@ ('', 'amend', None, _('amend the parent of the working directory')), ('s', 'secret', None, _('use the secret phase for committing')), ('e', 'edit', None, _('invoke editor on commit messages')), + ('f', 'force', None, _('forcibly close branch from a non-head changeset')), ('i', 'interactive', None, _('use interactive mode')), ] + walkopts + commitopts + commitopts2 + subrepoopts, _('[OPTION]... [FILE]...'), @@ -1675,12 +1676,18 @@ if not bheads: raise error.Abort(_('can only close branch heads')) - elif branch == repo['.'].branch() and repo['.'].node() not in bheads: - raise error.Abort(_('can only close branch heads')) + elif (branch == repo['.'].branch() and repo['.'].node() not in bheads + and not opts.get('force')): + hint = _("use --force to close a non-head changeset") + raise error.Abort(_('can only close branch heads'), hint=hint) elif opts.get('amend'): if (repo['.'].p1().branch() != branch and repo['.'].p2().branch() != branch): raise error.Abort(_('can only close branch heads')) + if opts.get('force'): + # remove 'force' from opts as it can bypass some internal commit + # functions. + del opts['force'] if opts.get('amend'): if ui.configbool('ui', 'commitsubrepos'): diff --git a/tests/test-alias.t b/tests/test-alias.t --- a/tests/test-alias.t +++ b/tests/test-alias.t @@ -120,6 +120,7 @@ --amend amend the parent of the working directory -s --secret use the secret phase for committing -e --edit invoke editor on commit messages + -f --force forcibly close branch from a non-head changeset -i --interactive use interactive mode -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns diff --git a/tests/test-branches.t b/tests/test-branches.t --- a/tests/test-branches.t +++ b/tests/test-branches.t @@ -958,6 +958,7 @@ it should abort: $ hg ci -m "closing branch" --close-branch abort: can only close branch heads + (use --force to close a non-head changeset) [255] $ hg up 0 @@ -972,3 +973,19 @@ @ 0: 9092f1db7931 added a default +Check --force to close a branch from a cset which is not a branch head + + $ hg show stack --config extensions.show= + o 1553 added c + o 5f6d added b + @ 9092 added a + +without --force + $ hg ci -m "branch closed" --close-branch + abort: can only close branch heads + (use --force to close a non-head changeset) + [255] + +with --force + $ hg ci -m "branch closed" --close-branch --force + created new head diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -245,7 +245,7 @@ bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure cat: output, rev, decode, include, exclude, template clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure - commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos + commit: addremove, close-branch, amend, secret, edit, force, interactive, include, exclude, message, logfile, date, user, subrepos config: untrusted, edit, local, global, template copy: after, force, include, exclude, dry-run debugancestor: diff --git a/tests/test-qrecord.t b/tests/test-qrecord.t --- a/tests/test-qrecord.t +++ b/tests/test-qrecord.t @@ -69,6 +69,7 @@ --amend amend the parent of the working directory -s --secret use the secret phase for committing -e --edit invoke editor on commit messages + -f --force forcibly close branch from a non-head changeset -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns -m --message TEXT use text as commit message diff --git a/tests/test-record.t b/tests/test-record.t --- a/tests/test-record.t +++ b/tests/test-record.t @@ -52,6 +52,7 @@ --amend amend the parent of the working directory -s --secret use the secret phase for committing -e --edit invoke editor on commit messages + -f --force forcibly close branch from a non-head changeset -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns -m --message TEXT use text as commit message