How to edit incorrect commit message in Mercurial?

140,079

Solution 1

Update: Mercurial has added --amend which should be the preferred option now.


You can rollback the last commit (but only the last one) with hg rollback and then reapply it.

Important: this permanently removes the latest commit (or pull). So if you've done a hg update that commit is no longer in your working directory then it's gone forever. So make a copy first.

Other than that, you cannot change the repository's history (including commit messages), because everything in there is check-summed. The only thing you could do is prune the history after a given changeset, and then recreate it accordingly.

None of this will work if you have already published your changes (unless you can get hold of all copies), and you also cannot "rewrite history" that include GPG-signed commits (by other people).

Solution 2

Well, I used to do this way:

Imagine, you have 500 commits, and your erroneous commit message is in r.498.

hg qimport -r 498:tip
hg qpop -a
joe .hg/patches/498.diff
(change the comment, after the mercurial header)
hg qpush -a
hg qdelete -r qbase:qtip

Solution 3

Good news: hg 2.2 just added git like --amend option.

and in tortoiseHg, you can use "Amend current revision" by select black arrow on the right of commit button

a

Solution 4

I know this is an old post and you marked the question as answered. I was looking for the same thing recently and I found the histedit extension very useful. The process is explained here:

http://knowledgestockpile.blogspot.com/2010/12/changing-commit-message-of-revision-in.html

Solution 5

Last operation was the commit in question

To change the commit message of the last commit when the last mercurial operation was a commit you can use

$ hg rollback

to roll back the last commit and re-commit it with the new message:

$ hg ci -m 'new message'

But be careful because the rollback command also rolls back following operations:

  • import
    • pull
    • push (with this repository as the destination)
    • unbundle

(see hg help rollback)

Thus, if you are not sure if the last mercurial command was a hg ci, don't use hg rollback.

Change any other commit message

You can use the mq extension, which is distributed with Mercurial, to change the commit message of any commit.

This approach is only useful when there aren't already cloned repositories in the public that contain the changeset you want to rename because doing so alters the changeset hash of it and all following changesets.

That means that you have to be able to remove all existing clones that include the changeset you want to rename, or else pushing/pulling between them wouldn't work.

To use the mq extension you have to explicitly enable it, e.g. under UNIX check your ~/.hgrc, which should contain following lines:

[extensions]
mq=

Say that you want to change revision X - first qimport imports revisions X and following. Now they are registered as a stack of applied patches. Popping (qpop) the complete stack except X makes X available for changes via qrefresh. After the commit message is changed you have to push all patches again (qpop) to re-apply them, i.e. to recreate the following revisions. The stack of patches isn't needed any, thus it can be removed via qfinish.

Following demo script shows all operations in action. In the example the commit message of third changeset is renamed.

# test.sh
cd $(dirname $0)
set -x -e -u
echo INFO: Delete old stuff
rm -rf .hg `seq 5`
echo INFO: Setup repository with 5 revisions
hg init
echo '[ui]' > .hg/hgrc
echo 'username=Joe User <[email protected]>' >> .hg/hgrc
echo 'style = compact' >> .hg/hgrc
echo '[extensions]' >> .hg/hgrc
echo 'mq=' >> .hg/hgrc
for i in `seq 5`; do
  touch $i && hg add $i && hg ci -m "changeset message $i" $i
done
hg log 
echo INFO: Need to rename the commit message on the 3rd revision
echo INFO: Displays all patches
hg qseries
echo INFO: Import all revisions including the 3rd to the last one as patches
hg qimport -r $(hg identify -n -r 'children(2)'):tip
hg qseries
echo INFO: Pop patches
hg qpop -a
hg qseries
hg log 
hg parent
hg commit --amend -m 'CHANGED MESSAGE'
hg log 
echo INFO: Push all remaining patches
hg qpush -a
hg log 
hg qseries
echo INFO: Remove all patches
hg qfinish -a
hg qseries && hg log && hg parent

Copy it to an empty directory an execute it e.g. via:

$ bash test.sh 2>&1 | tee log

The output should include the original changeset message:

+ hg log
[..]
2   53bc13f21b04   2011-08-31 17:26 +0200   juser
  changeset message 3

And the rename operation the changed message:

+ hg log
[..]
2   3ff8a832d057   2011-08-31 17:26 +0200   juser
  CHANGED MESSAGE

(Tested with Mercurial 4.5.2)

Share:
140,079
maxyfc
Author by

maxyfc

01011001 01100101 01110100 00100000 01100001 01101110 01101111 01110100 01101000 01100101 01110010 00100000 01110000 01110010 01101111 01100111 01110010 01100001 01101101 01101101 01100101 01110010 00101110

Updated on July 08, 2022

Comments

  • maxyfc
    maxyfc almost 2 years

    I am currently using TortoiseHg (Mercurial) and accidentally committed an incorrect commit message. How do I go about editing this commit message in the repository?

  • Martin Geisler
    Martin Geisler almost 15 years
    You can also edit the commit message with hg qrefresh -e after using hg qpop to arrive at the right patch.
  • user2649601
    user2649601 over 14 years
    Of course instead of 'joe' you can use any other editor of choice.
  • Mizipzor
    Mizipzor about 14 years
    +1 this is the approach I use when I cant use the simple rollback. Windows users should note that notepad isnt happy about the eol in the diff file.
  • Ry4an Brase
    Ry4an Brase almost 14 years
    I just watched a guy get a commit toasted because he followed this advice. When suggesting someone use rollback please always include a warning that it permanently removes the latest commit (or pull). So if you've done a hg update (like he had) and that commit is no longer in your working directory then it's gone forever.
  • Solomon Duskis
    Solomon Duskis over 13 years
    "r.3" is the third commit, counted from the beginning of history, typically not one of the recent commits. I changed it to a 3-digit to prevent other people from making the same mistake I did. (By the way, to undo 'qimport' you can use 'hg qfinish -a').
  • unexist
    unexist about 13 years
    Really nice extension, thanks for the suggestion!
  • rxgx
    rxgx almost 13 years
    The easiest way to avoid rollback/rollover disasters is to perform a simple change (add or remove spacing) and explain your mistake in the next commit message.
  • maxschlepzig
    maxschlepzig almost 13 years
    Tested it with Mercurial 1.7.5 and your procedure does not work. A qimport prints 'abort: revision <rev> has unmanaged children'. What works is not calling hg up, importing everything from including <rev> to the tip, pop everything, call then hg qrefresh -e and pushing everything - like described in Antonio's answer.
  • maxschlepzig
    maxschlepzig almost 13 years
    I am new to MQs but I think that you have to use hg qfinish -a instead of hg qdelete -r ... because the help to qdelete says 'The patches must not be applied', where in the example the patches are applied (and the hgbook states that 'qbase and qtip identify the “bottom-most” and topmost applied patches').
  • Sled
    Sled almost 13 years
    @rxgx you should post this as a separate answer since it is probably the best answer here.
  • Benbob
    Benbob over 12 years
    I ended up on this page because histedit does not work on merge commits. Just a warning, you can't rename a merge with this.
  • Sergii Volchkov
    Sergii Volchkov over 12 years
    Current versions of the extension even support "message" command specifically for editing commit messages.
  • gw0
    gw0 almost 12 years
    hg qfinish -a works well and also removes files in .hg/patches/.
  • Milos
    Milos almost 12 years
    What do you mean by 'pop everything'?
  • Rune Andersen
    Rune Andersen almost 12 years
    This is what I always do - it is the easiest way!
  • Ken Mason
    Ken Mason about 11 years
    Upvoted. Histedit is the easiest way to do this, once you learn to use histedit.
  • Daniel Sokolowski
    Daniel Sokolowski almost 11 years
    If you get abort: can't rebase immutable changeset 43ab8134e7af you must first flip the commit to draft: hg phase -f -d 45:c3a3a271d11c - see Mecurial Phases for more.
  • jedd.ahyoung
    jedd.ahyoung about 10 years
    Upvoted. This is awesome because it lets you do this for multiple draft changesets - say, for instance, if you put the wrong ticket number in all of your commits! :D
  • Werner
    Werner over 9 years
    This is better-suited as a comment.
  • OZZIE
    OZZIE almost 9 years
    What to do in this scenario..? hg qimport -r 301:tip abort: revision 301 is the root of more than one branch
  • badcompany
    badcompany almost 8 years
    I think qdelete is still needed since I got "abort: source has mq patches applied" message while pushing the commits. After qdelete 'hg push' was successful.
  • Luciano
    Luciano over 7 years
    Doesn't let you commit if you haven't changed the contents of the files though ... nothing changed
  • Joshua Goldberg
    Joshua Goldberg over 7 years
    He means (to rename a revision "rev") something analogous to the answer, but popping all the descendents off the mq stack. Something like: hg up hg qimport -r rev::. hg qpop --all hg qpush hg qrefresh -e (to edit the commit message in an editor) hg qpush --all hg qfinish --all
  • Clonkex
    Clonkex over 6 years
    I'm pretty astounded that it took two whole years to add the warning, honestly. If I had needed to know how to do this before the warning was added I would have followed the advice in this answer and lost work because of it.