Patchwork [2,of,3] commit: add a -M/--reuse-message option to copy a commit message from a

login
register
mail settings
Submitter Tony Tung
Date May 15, 2015, 10:54 p.m.
Message ID <dc122dd80665762d8feb.1431730476@andromeda.dhcp.thefacebook.com>
Download mbox | patch
Permalink /patch/9106/
State Changes Requested
Headers show

Comments

Tony Tung - May 15, 2015, 10:54 p.m.
# HG changeset patch
# User Tony Tung <tonytung@fb.com>
# Date 1429655274 25200
#      Tue Apr 21 15:27:54 2015 -0700
# Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
# Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
commit: add a -M/--reuse-message option to copy a commit message from a
revspec

One way to split up a diff that includes a refactor involves resetting to
the ancestor, and then committing the refactor first.  When committing the
main change, it's helpful to be able to reuse the commit message from the
earlier commit that includes both the refactor and the new functionality.
This makes it easy to grab the commit message.
Sean Farley - May 15, 2015, 11:14 p.m.
Tony Tung <tonytung@fb.com> writes:

> # HG changeset patch
> # User Tony Tung <tonytung@fb.com>
> # Date 1429655274 25200
> #      Tue Apr 21 15:27:54 2015 -0700
> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
> commit: add a -M/--reuse-message option to copy a commit message from a
> revspec
>
> One way to split up a diff that includes a refactor involves resetting to
> the ancestor, and then committing the refactor first.  When committing the
> main change, it's helpful to be able to reuse the commit message from the
> earlier commit that includes both the refactor and the new functionality.
> This makes it easy to grab the commit message.

A big +1 to this. I've been wanting this for a while! You're two for two
today, Tony :-)
Pierre-Yves David - May 16, 2015, 7:06 a.m.
On 05/15/2015 03:54 PM, Tony Tung wrote:
> # HG changeset patch
> # User Tony Tung <tonytung@fb.com>
> # Date 1429655274 25200
> #      Tue Apr 21 15:27:54 2015 -0700
> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
> commit: add a -M/--reuse-message option to copy a commit message from a
> revspec
>
> One way to split up a diff that includes a refactor involves resetting to
> the ancestor, and then committing the refactor first.  When committing the
> main change, it's helpful to be able to reuse the commit message from the
> earlier commit that includes both the refactor and the new functionality.
> This makes it easy to grab the commit message.

My personal opinion is that we do not need this feature as an explicit 
commit flag. There is multiple reason for that.

1) about two years ago, while using mercurial, I felt the need for such 
flag, but it eventually faded. Nowaday I really barely use it. I believe 
my need faded away because of two commands from evolve: "hg fold" the 
removed my need to use "revert+commit" to fold things together. And "hg 
uncommit" who removed my need to use "revert+commit" to redo a commit. 
(you can replace "revert+commit" with "strip -k+commit" too).

2) achieving the same feature is already quite easy thanks to the shell. 
power. one can achieve the same result using `hg commit -m "$(hg log -r 
X -T '{desc}')"`. When I used this on a regular basis, I setup a 'desc' 
command alias and I was about to get -M using: hg ci -m `hg desc X` 
something concise enough for the frequency I needed it.

3) We have to be careful of UI bloat and any option added to commit 
trickle down to a lot of the other command. The amount of different help 
changed in this patch is a good sign of that. The fact we added it on 
rebase, because of the --collapse feature that is already mostly foreign 
to rebase is also a good sign of that.


To conclude. given that (1) we can provide better option for the same 
effect, (2) there is already option to get this done today with 
"reasonable" cost (3) commit is a very critical command regarding UI 
bloat. I do not think the Utility/bloat ratio is good enough for this 
new flag.
Augie Fackler - May 18, 2015, 1:07 a.m.
> On May 16, 2015, at 21:24, Durham Goode <durham@fb.com> wrote:
> 
> We've had this conversation IRL, but putting my response here as well for the communities viewing pleasure.
> 
> On 5/16/15 12:06 AM, Pierre-Yves David wrote:
>> 
>> 
>> On 05/15/2015 03:54 PM, Tony Tung wrote:
>>> # HG changeset patch
>>> # User Tony Tung <tonytung@fb.com>
>>> # Date 1429655274 25200
>>> #      Tue Apr 21 15:27:54 2015 -0700
>>> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
>>> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
>>> commit: add a -M/--reuse-message option to copy a commit message from a
>>> revspec
>>> 
>>> One way to split up a diff that includes a refactor involves resetting to
>>> the ancestor, and then committing the refactor first.  When committing the
>>> main change, it's helpful to be able to reuse the commit message from the
>>> earlier commit that includes both the refactor and the new functionality.
>>> This makes it easy to grab the commit message.
>> 
>> My personal opinion is that we do not need this feature as an explicit commit flag. There is multiple reason for that.
>> 
>> 1) about two years ago, while using mercurial, I felt the need for such flag, but it eventually faded. Nowaday I really barely use it. I believe my need faded away because of two commands from evolve: "hg fold" the removed my need to use "revert+commit" to fold things together. And "hg uncommit" who removed my need to use "revert+commit" to redo a commit. (you can replace "revert+commit" with "strip -k+commit" too).
> If you felt this was useful two years ago, there's probably a ton of people who feel it's useful now and haven't had the two years to learn ways around it.  I think it's a useful command, and it's worth catering towards many different workflows.
> 
> Also, we're a long way from everyone having access to evolve, so I don't think we should block useful features based on it.
>> 
>> 2) achieving the same feature is already quite easy thanks to the shell. power. one can achieve the same result using `hg commit -m "$(hg log -r X -T '{desc}')"`. When I used this on a regular basis, I setup a 'desc' command alias and I was about to get -M using: hg ci -m `hg desc X` something concise enough for the frequency I needed it.
> "hg commit -m "$(hg log -r X -T '{desc}')"" is a pretty poor user experience (not to mention it requires knowledge of bash, log, and templates), and I don't think we should require that users set up aliases to get a good experience.
>> 
>> 3) We have to be careful of UI bloat and any option added to commit trickle down to a lot of the other command. The amount of different help changed in this patch is a good sign of that. The fact we added it on rebase, because of the --collapse feature that is already mostly foreign to rebase is also a good sign of that.
> Sure, UI bloat is bad, but I don't think we should block legitimately useful features because we're worried about an extra line in the help text.  Commit currently has 16 options.  I think we're pretty far from it becoming unreadable.

Fair point. Given how ugly the bashism to replace this is, I think I'm coming around, but with no short flag.

> Whether this option should be on rebase or not, I kind lean towards no there.

I didn't even read far enough into the patch to catch that. I think this flag makes sense only on commit - import and backout also seem silly (unless you've got a use case, which I'm open to hearing, I just can't imagine one offhand...)


> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Sean Farley - May 18, 2015, 1:17 a.m.
Durham Goode <durham@fb.com> writes:

> On 5/16/15 5:43 PM, Augie Fackler wrote:
>> On May 16, 2015, at 3:06 AM, Pierre-Yves David <pierre-yves.david@ens-lyon.org> wrote:
>>
>>>
>>> On 05/15/2015 03:54 PM, Tony Tung wrote:
>>>> # HG changeset patch
>>>> # User Tony Tung <tonytung@fb.com>
>>>> # Date 1429655274 25200
>>>> #      Tue Apr 21 15:27:54 2015 -0700
>>>> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
>>>> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
>>>> commit: add a -M/--reuse-message option to copy a commit message from a
>>>> revspec
>>>>
>>>> One way to split up a diff that includes a refactor involves resetting to
>>>> the ancestor, and then committing the refactor first.  When committing the
>>>> main change, it's helpful to be able to reuse the commit message from the
>>>> earlier commit that includes both the refactor and the new functionality.
>>>> This makes it easy to grab the commit message.
>>> My personal opinion is that we do not need this feature as an explicit commit flag. There is multiple reason for that.
>>>
>>> 1) about two years ago, while using mercurial, I felt the need for such flag, but it eventually faded. Nowaday I really barely use it. I believe my need faded away because of two commands from evolve: "hg fold" the removed my need to use "revert+commit" to fold things together. And "hg uncommit" who removed my need to use "revert+commit" to redo a commit. (you can replace "revert+commit" with "strip -k+commit" too).
>>>
>>> 2) achieving the same feature is already quite easy thanks to the shell. power. one can achieve the same result using `hg commit -m "$(hg log -r X -T '{desc}')"`. When I used this on a regular basis, I setup a 'desc' command alias and I was about to get -M using: hg ci -m `hg desc X` something concise enough for the frequency I needed it.
>>>
>>> 3) We have to be careful of UI bloat and any option added to commit trickle down to a lot of the other command. The amount of different help changed in this patch is a good sign of that. The fact we added it on rebase, because of the --collapse feature that is already mostly foreign to rebase is also a good sign of that.
>>>
>>>
>>> To conclude. given that (1) we can provide better option for the same effect, (2) there is already option to get this done today with "reasonable" cost (3) commit is a very critical command regarding UI bloat. I do not think the Utility/bloat ratio is good enough for this new flag.
>> I’m inclined to agree with marmoute on this one, I’m afraid. This just isn’t something I see done enough to justify the ui complexity (and spending one of our precious short flags on.)
> I see users ask for this on a regular basis.  Their needs usually fall 
> into a few categories:
>
> - They screwed up a commit and their solution is to undo the commit and 
> redo it. They want to use the same commit message as before.
> - They want to split a commit up.  They enter into histedit, choose 
> 'edit', but when they go to make the first commit, they can't reuse the 
> commit message from the original commit.
> - They have a stack of experimental commits and want to redo the stack 
> correctly before sending it out. They want to reuse some of the commit 
> messages from the old stack.
> - They accidentally screwed up their commit message. (hg amend -m 
> usually).  They recover a commit from a bundle and want to amend that 
> commit message into their current commit.
>
> Heck, I myself have needed it twice in the last few days (and resorted 
> to bash-isms to work around it), but I need it pretty much every time I 
> work with complex stacks for hg-crew (usually for point #3 above).  
> Every item I list above has workarounds, but we can't possibly teach all 
> our users the "right" way to do things, so supporting what they find to 
> be the intuitive solution (i need a commit message, so let me copy it 
> from somewhere) is worth it in my opinion.

I'm with Durham on this one. I find myself cursing daily that I can't
reuse a commit message (or, in general, tell Mercurial with some flag
"don't open editor, just accept whatever the action is"). We've had
similar missing features that we've added in the last one, and I see no
reason why this should be different.

For example, histedit didn't have 'roll' until very recently. Why should
rebase and friends lack it?
Matt Mackall - May 18, 2015, 1:57 a.m.
On Fri, 2015-05-15 at 15:54 -0700, Tony Tung wrote:
> # HG changeset patch
> # User Tony Tung <tonytung@fb.com>
> # Date 1429655274 25200
> #      Tue Apr 21 15:27:54 2015 -0700
> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
> commit: add a -M/--reuse-message option to copy a commit message from a
> revspec
> 
> One way to split up a diff that includes a refactor involves resetting to
> the ancestor, and then committing the refactor first.

For future reference, "resetting" is git-speak that I don't understand,
despite having looked at the git-reset manpage countless times. Please
don't make me learn git to understand your commit messages, because git
makes me sad. Please instead use "updating to", "reverting to", or
whatever version of --hard/--soft/--bouncy you mean corresponds to.

I vaguely recall discussing this option with Ryan, perhaps at the
sprint. I understand the value of the feature, but I think it's below
the threshold for UI clutter. 

One way of getting around that is to make a more generically useful
feature with lower UI footprint. For instance, log historically has a
ton of individual options to specify which revisons to show:
--keyword/date/follow/follow-first/only-branch/only-merges/no-merges/limit/user/prune, etc.

We were far past the point where things were cumbersome, the
combinations didn't make sense, and it still wasn't expressive enough
for all the things users wanted, and new things only worked for log.

Now compare that with revsets: basically everything supports revsets,
they're vastly more powerful and expressive, and adding new features to
revsets doesn't clutter the help and implementation of every command. 

So a more "generic" version of this feature might look like this:

 hg commit -u @255 -m @255 -d @255  # copy the metadata from cset 255

..but would have further reaching consequences:

 hg log -d @.  # show commits with the same date as the current one

 hg log -r "files(@bookmark)" # show commits that touch the same files

The per-command implementation would look something like:

  if opts["message"]:
     message = cmdutil.expandopt(repo, "description", opts["message"])

There are a bunch of problems with the precise form of the above,
starting with the fact that we obviously already use "@" for other
things, but I think it illustrates why a generic approach is more
valuable and maintainable.
Durham Goode - May 18, 2015, 5:53 p.m.
On 5/17/15 6:57 PM, Matt Mackall wrote:
> On Fri, 2015-05-15 at 15:54 -0700, Tony Tung wrote:
>> # HG changeset patch
>> # User Tony Tung <tonytung@fb.com>
>> # Date 1429655274 25200
>> #      Tue Apr 21 15:27:54 2015 -0700
>> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
>> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
>> commit: add a -M/--reuse-message option to copy a commit message from a
>> revspec
>>
>> One way to split up a diff that includes a refactor involves resetting to
>> the ancestor, and then committing the refactor first.
> For future reference, "resetting" is git-speak that I don't understand,
> despite having looked at the git-reset manpage countless times. Please
> don't make me learn git to understand your commit messages, because git
> makes me sad. Please instead use "updating to", "reverting to", or
> whatever version of --hard/--soft/--bouncy you mean corresponds to.
>
> I vaguely recall discussing this option with Ryan, perhaps at the
> sprint. I understand the value of the feature, but I think it's below
> the threshold for UI clutter.
>
> One way of getting around that is to make a more generically useful
> feature with lower UI footprint. For instance, log historically has a
> ton of individual options to specify which revisons to show:
> --keyword/date/follow/follow-first/only-branch/only-merges/no-merges/limit/user/prune, etc.
>
> We were far past the point where things were cumbersome, the
> combinations didn't make sense, and it still wasn't expressive enough
> for all the things users wanted, and new things only worked for log.
>
> Now compare that with revsets: basically everything supports revsets,
> they're vastly more powerful and expressive, and adding new features to
> revsets doesn't clutter the help and implementation of every command.
>
> So a more "generic" version of this feature might look like this:
>
>   hg commit -u @255 -m @255 -d @255  # copy the metadata from cset 255
>
> ..but would have further reaching consequences:
>
>   hg log -d @.  # show commits with the same date as the current one
>
>   hg log -r "files(@bookmark)" # show commits that touch the same files
>
> The per-command implementation would look something like:
>
>    if opts["message"]:
>       message = cmdutil.expandopt(repo, "description", opts["message"])
>
> There are a bunch of problems with the precise form of the above,
> starting with the fact that we obviously already use "@" for other
> things, but I think it illustrates why a generic approach is more
> valuable and maintainable.
>
I like the idea of a generic solution.  What about 'hg commit -m 
{255}'?  Templates use {} to indicate "replace this with the desired 
value", so we could do the same in commands and revsets, where appropriate.

Would you be ok if it was only done for commit -m initially?  That seems 
like the 95% case.
Matt Mackall - May 18, 2015, 6:15 p.m.
On Mon, 2015-05-18 at 10:53 -0700, Durham Goode wrote:
> 
> On 5/17/15 6:57 PM, Matt Mackall wrote:
> > On Fri, 2015-05-15 at 15:54 -0700, Tony Tung wrote:
> >> # HG changeset patch
> >> # User Tony Tung <tonytung@fb.com>
> >> # Date 1429655274 25200
> >> #      Tue Apr 21 15:27:54 2015 -0700
> >> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
> >> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
> >> commit: add a -M/--reuse-message option to copy a commit message from a
> >> revspec
> >>
> >> One way to split up a diff that includes a refactor involves resetting to
> >> the ancestor, and then committing the refactor first.
> > For future reference, "resetting" is git-speak that I don't understand,
> > despite having looked at the git-reset manpage countless times. Please
> > don't make me learn git to understand your commit messages, because git
> > makes me sad. Please instead use "updating to", "reverting to", or
> > whatever version of --hard/--soft/--bouncy you mean corresponds to.
> >
> > I vaguely recall discussing this option with Ryan, perhaps at the
> > sprint. I understand the value of the feature, but I think it's below
> > the threshold for UI clutter.
> >
> > One way of getting around that is to make a more generically useful
> > feature with lower UI footprint. For instance, log historically has a
> > ton of individual options to specify which revisons to show:
> > --keyword/date/follow/follow-first/only-branch/only-merges/no-merges/limit/user/prune, etc.
> >
> > We were far past the point where things were cumbersome, the
> > combinations didn't make sense, and it still wasn't expressive enough
> > for all the things users wanted, and new things only worked for log.
> >
> > Now compare that with revsets: basically everything supports revsets,
> > they're vastly more powerful and expressive, and adding new features to
> > revsets doesn't clutter the help and implementation of every command.
> >
> > So a more "generic" version of this feature might look like this:
> >
> >   hg commit -u @255 -m @255 -d @255  # copy the metadata from cset 255
> >
> > ..but would have further reaching consequences:
> >
> >   hg log -d @.  # show commits with the same date as the current one
> >
> >   hg log -r "files(@bookmark)" # show commits that touch the same files
> >
> > The per-command implementation would look something like:
> >
> >    if opts["message"]:
> >       message = cmdutil.expandopt(repo, "description", opts["message"])
> >
> > There are a bunch of problems with the precise form of the above,
> > starting with the fact that we obviously already use "@" for other
> > things, but I think it illustrates why a generic approach is more
> > valuable and maintainable.
> >
> I like the idea of a generic solution.  What about 'hg commit -m 
> {255}'?  Templates use {} to indicate "replace this with the desired 
> value", so we could do the same in commands and revsets, where appropriate.

I'm actually thinking "<foo>", so there's no confusion with templates.

> Would you be ok if it was only done for commit -m initially?  That seems 
> like the 95% case.

Provided it's not open-coded.
Jordi Gutiérrez Hermoso - May 19, 2015, 1:33 p.m.
On Fri, 2015-05-15 at 15:54 -0700, Tony Tung wrote:
> # HG changeset patch
> # User Tony Tung <tonytung@fb.com>
> # Date 1429655274 25200
> #      Tue Apr 21 15:27:54 2015 -0700
> # Node ID dc122dd80665762d8febe2db1a08ce00a63d5ab8
> # Parent  18cadf9d058931ef00e5272d15cb5cf2ebc3a248
> commit: add a -M/--reuse-message option to copy a commit message from a
> revspec

We don't have revspecs. That's a gitism with much very limited
functionality compared to what we do have have: revsets.

On Sat, 2015-05-16 at 00:06 -0700, Pierre-Yves David wrote:
> To conclude. given that (1) we can provide better option for the
> same effect, (2) there is already option to get this done today with
> "reasonable" cost (3) commit is a very critical command regarding UI
> bloat. I do not think the Utility/bloat ratio is good enough for
> this new flag.

I agree. It's already a big problem that `hg help rebase` is so long.
I intend to trim it.

Until `hg amend` lands in core, a simple fix that does not add UI
bloat is `hg commit --logfile .hg/last-message.txt`, perhaps with
--amend. This whole thinking that reusing commit messages has got
something to do with "resets" and "revspecs" seems to be trying to
transpose onto Mercurial a workflow that git's UI imposes.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -285,11 +285,15 @@ 
     """ get the log message according to -m and -l option """
     message = opts.get('message')
     logfile = opts.get('logfile')
-
-    if message and logfile:
-        raise util.Abort(_('options --message and --logfile are mutually '
-                           'exclusive'))
-    if not message and logfile:
+    revspec = opts.get('reuse_message')
+
+    # calculate how many are set.  if more than one are set, we need to abort.
+    num_set = len([x for x in [message, logfile, revspec] if x])
+
+    if num_set > 1:
+        raise util.Abort(_('options --message, --logfile, and --reuse-message '
+                           'are mutually exclusive'))
+    if logfile:
         try:
             if logfile == '-':
                 message = ui.fin.read()
@@ -298,6 +302,18 @@ 
         except IOError, inst:
             raise util.Abort(_("can't read commit message '%s': %s") %
                              (logfile, inst.strerror))
+
+    if revspec:
+        revs = repo.revs(revspec)
+
+        if len(revs) > 1:
+            raise util.Abort(_("revspec %s refers to more than one revision") %
+                             revspec)
+
+        ctx = context.changectx(repo, revs.first())
+
+        message = ctx.description()
+
     return message
 
 def mergeeditform(ctxorbool, baseformname):
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -93,6 +93,8 @@ 
      _('use text as commit message'), _('TEXT')),
     ('l', 'logfile', '',
      _('read commit message from file'), _('FILE')),
+    ('M', 'reuse-message', '',
+     _('use message from REVSPEC'), _('REVSPEC')),
 ]
 
 commitopts2 = [
diff --git a/tests/test-commit.t b/tests/test-commit.t
--- a/tests/test-commit.t
+++ b/tests/test-commit.t
@@ -614,3 +614,41 @@ 
   $ hg co --clean tip
   abort: path contains illegal component: HG8B6C~2/hgrc (glob)
   [255]
+
+setup for -M/--reuse-message tests
+
+  $ rm -rf .hg
+  $ hg init
+  $ echo 'c1' > file
+  $ hg commit -Aqm "commit 1
+  >    message"
+  $ hg log --template '{desc}\n' .
+  commit 1
+     message
+  $ echo 'c2' >> file
+  $ hg commit -m "commit 2
+  >    second line"
+  $ echo 'c3' >> file
+
+attempt to select more than one rev when using -M/--reuse-message
+
+  $ hg commit -M 0..1
+  abort: revspec 0..1 refers to more than one revision
+  [255]
+
+attempt to use -M/--reuse-message along with -m
+
+  $ hg commit -M 0 -m "another message!"
+  abort: options --message, --logfile, and --reuse-message are mutually exclusive
+  [255]
+
+successful -M/--reuse-message
+
+  $ hg commit -M 0
+  $ hg log --template '{desc}\n'
+  commit 1
+     message
+  commit 2
+     second line
+  commit 1
+     message
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -202,7 +202,7 @@ 
   add: include, exclude, subrepos, dry-run
   annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
   clone: noupdate, updaterev, rev, branch, pull, uncompressed, 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, interactive, include, exclude, message, logfile, reuse-message, date, user, subrepos
   diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
   export: output, switch-parent, rev, text, git, nodates
   forget: include, exclude
@@ -218,7 +218,7 @@ 
   update: clean, check, date, rev, tool
   addremove: similarity, subrepos, include, exclude, dry-run
   archive: no-decode, prefix, rev, type, subrepos, include, exclude
-  backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
+  backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, reuse-message, date, user
   bisect: reset, good, bad, skip, extend, command, noupdate
   bookmarks: force, rev, delete, rename, inactive, template
   branch: force, clean
@@ -268,7 +268,7 @@ 
   heads: rev, topo, active, closed, style, template
   help: extension, command, keyword
   identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
-  import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
+  import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, reuse-message, date, user, similarity
   incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
   locate: rev, print0, fullpath, include, exclude
   manifest: rev, all, template
diff --git a/tests/test-mq-qrefresh-interactive.t b/tests/test-mq-qrefresh-interactive.t
--- a/tests/test-mq-qrefresh-interactive.t
+++ b/tests/test-mq-qrefresh-interactive.t
@@ -31,18 +31,19 @@ 
   
   options ([+] can be repeated):
   
-   -e --edit                invoke editor on commit messages
-   -g --git                 use git extended diff format
-   -s --short               refresh only files already in the patch and
-                            specified files
-   -U --currentuser         add/update author field in patch with current user
-   -u --user USER           add/update author field in patch with given user
-   -D --currentdate         add/update date field in patch with current date
-   -d --date DATE           add/update date field in patch with given date
-   -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
-   -l --logfile FILE        read commit message from file
+   -e --edit                  invoke editor on commit messages
+   -g --git                   use git extended diff format
+   -s --short                 refresh only files already in the patch and
+                              specified files
+   -U --currentuser           add/update author field in patch with current user
+   -u --user USER             add/update author field in patch with given user
+   -D --currentdate           add/update date field in patch with current date
+   -d --date DATE             add/update date field in patch with given date
+   -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
+   -l --logfile FILE          read commit message from file
+   -M --reuse-message REVSPEC use message from REVSPEC
   
   (some details hidden, use --verbose to show complete help)
 
@@ -73,19 +74,20 @@ 
   
   options ([+] can be repeated):
   
-   -e --edit                invoke editor on commit messages
-   -g --git                 use git extended diff format
-   -s --short               refresh only files already in the patch and
-                            specified files
-   -U --currentuser         add/update author field in patch with current user
-   -u --user USER           add/update author field in patch with given user
-   -D --currentdate         add/update date field in patch with current date
-   -d --date DATE           add/update date field in patch with given date
-   -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
-   -l --logfile FILE        read commit message from file
-   -i --interactive         interactively select changes to refresh
+   -e --edit                  invoke editor on commit messages
+   -g --git                   use git extended diff format
+   -s --short                 refresh only files already in the patch and
+                              specified files
+   -U --currentuser           add/update author field in patch with current user
+   -u --user USER             add/update author field in patch with given user
+   -D --currentdate           add/update date field in patch with current date
+   -d --date DATE             add/update date field in patch with given date
+   -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
+   -l --logfile FILE          read commit message from file
+   -M --reuse-message REVSPEC use message from REVSPEC
+   -i --interactive           interactively select changes to refresh
   
   (some details hidden, use --verbose to show complete help)
 
diff --git a/tests/test-qrecord.t b/tests/test-qrecord.t
--- a/tests/test-qrecord.t
+++ b/tests/test-qrecord.t
@@ -56,23 +56,24 @@ 
   
   options ([+] can be repeated):
   
-   -A --addremove           mark new/missing files as added/removed before
-                            committing
-      --close-branch        mark a branch as closed, hiding it from the branch
-                            list
-      --amend               amend the parent of the working directory
-   -s --secret              use the secret phase for committing
-   -e --edit                invoke editor on commit messages
-   -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
-   -l --logfile FILE        read commit message from file
-   -d --date DATE           record the specified date as commit date
-   -u --user USER           record the specified user as committer
-   -S --subrepos            recurse into subrepositories
-   -w --ignore-all-space    ignore white space when comparing lines
-   -b --ignore-space-change ignore changes in the amount of white space
-   -B --ignore-blank-lines  ignore changes whose lines are all blank
+   -A --addremove             mark new/missing files as added/removed before
+                              committing
+      --close-branch          mark a branch as closed, hiding it from the branch
+                              list
+      --amend                 amend the parent of the working directory
+   -s --secret                use the secret phase for committing
+   -e --edit                  invoke editor on commit messages
+   -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
+   -l --logfile FILE          read commit message from file
+   -M --reuse-message REVSPEC use message from REVSPEC
+   -d --date DATE             record the specified date as commit date
+   -u --user USER             record the specified user as committer
+   -S --subrepos              recurse into subrepositories
+   -w --ignore-all-space      ignore white space when comparing lines
+   -b --ignore-space-change   ignore changes in the amount of white space
+   -B --ignore-blank-lines    ignore changes whose lines are all blank
   
   (some details hidden, use --verbose to show complete help)
 
@@ -133,20 +134,21 @@ 
   
   options ([+] can be repeated):
   
-   -e --edit                invoke editor on commit messages
-   -g --git                 use git extended diff format
-   -U --currentuser         add "From: <current user>" to patch
-   -u --user USER           add "From: <USER>" to patch
-   -D --currentdate         add "Date: <current date>" to patch
-   -d --date DATE           add "Date: <DATE>" to patch
-   -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
-   -l --logfile FILE        read commit message from file
-   -w --ignore-all-space    ignore white space when comparing lines
-   -b --ignore-space-change ignore changes in the amount of white space
-   -B --ignore-blank-lines  ignore changes whose lines are all blank
-      --mq                  operate on patch repository
+   -e --edit                  invoke editor on commit messages
+   -g --git                   use git extended diff format
+   -U --currentuser           add "From: <current user>" to patch
+   -u --user USER             add "From: <USER>" to patch
+   -D --currentdate           add "Date: <current date>" to patch
+   -d --date DATE             add "Date: <DATE>" to patch
+   -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
+   -l --logfile FILE          read commit message from file
+   -M --reuse-message REVSPEC use message from REVSPEC
+   -w --ignore-all-space      ignore white space when comparing lines
+   -b --ignore-space-change   ignore changes in the amount of white space
+   -B --ignore-blank-lines    ignore changes whose lines are all blank
+      --mq                    operate on patch repository
   
   (some details hidden, use --verbose to show complete help)
 
diff --git a/tests/test-record.t b/tests/test-record.t
--- a/tests/test-record.t
+++ b/tests/test-record.t
@@ -43,23 +43,24 @@ 
   
   options ([+] can be repeated):
   
-   -A --addremove           mark new/missing files as added/removed before
-                            committing
-      --close-branch        mark a branch as closed, hiding it from the branch
-                            list
-      --amend               amend the parent of the working directory
-   -s --secret              use the secret phase for committing
-   -e --edit                invoke editor on commit messages
-   -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
-   -l --logfile FILE        read commit message from file
-   -d --date DATE           record the specified date as commit date
-   -u --user USER           record the specified user as committer
-   -S --subrepos            recurse into subrepositories
-   -w --ignore-all-space    ignore white space when comparing lines
-   -b --ignore-space-change ignore changes in the amount of white space
-   -B --ignore-blank-lines  ignore changes whose lines are all blank
+   -A --addremove             mark new/missing files as added/removed before
+                              committing
+      --close-branch          mark a branch as closed, hiding it from the branch
+                              list
+      --amend                 amend the parent of the working directory
+   -s --secret                use the secret phase for committing
+   -e --edit                  invoke editor on commit messages
+   -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
+   -l --logfile FILE          read commit message from file
+   -M --reuse-message REVSPEC use message from REVSPEC
+   -d --date DATE             record the specified date as commit date
+   -u --user USER             record the specified user as committer
+   -S --subrepos              recurse into subrepositories
+   -w --ignore-all-space      ignore white space when comparing lines
+   -b --ignore-space-change   ignore changes in the amount of white space
+   -B --ignore-blank-lines    ignore changes whose lines are all blank
   
   (some details hidden, use --verbose to show complete help)