11
votes

Is there a way to edit a commit message in Mercurial on a commit after other commits have occured using TortoiseHg? I've read these posts:

How to edit incorrect commit message in Mercurial?

Mercurial: how to amend the last commit?

and have been able to update a "regular" commit message when it is the latest commit on a branch (using TortoiseHg). However, I haven't been able to figure out how to edit a commit message when other commits have occurred after the one I want to edit. It always edits the last commit.

Based on Ed Cottrell's comment, I did a test where I made two commits without pushing to the central repo, and I still have the same issue - only the last commit message can be edited.

EDIT: I should clarify that I am looking to update a changeset that has been pushed.

3
Have you pushed to a remote repository since the commit in question?elixenide
Yes, so I changed the phase to draft before importing to MQsdoca
That's a different issue; are you trying to change commit messages on patches or on the core repository?elixenide
What my final goal is to update a message on commit where I merged a branch back into trunk (default) branch. Not sure if you consider that a patch or not. However, in my testing, first I'm just trying to get to the point where I can edit a commit message when it is not the last commit on the trunk branch (default).sdoca
I'm asking about patches because you mentioned MQ, which is a patch management system. If you did a simple merge, that's easier to work with, but still a huge pain. You can use the hg rebase extension to move all commits after the one you want to change, then use --amend to change the message, then hg rebase to reattach the other commits. This is really dicey, though, and a bad idea if this not a purely personal repository. You are probably best off just doing a new commit with a corrected message.elixenide

3 Answers

12
votes

Histedit extension (bundled with TortoiseHG now) has a mess command for changing the commit message of historical changesets.

Unfortunately, this command is not supported by the TortoiseHG GUI so you need to run the command from command line.

4
votes

As long as the change in question is local and hasn't been pushed anywhere, it is possible.

The commit message is used to compute the globally unique hash id that is used for all repositories to determine whether or not they already have a changeset. If you change the commit message, you change the unique hash id and every repo will see it as a "new" changeset. All other repositories that had the old changeset will try to get the new one and ask that you merge it with itself.... This is not a good thing, so the short answer to your question is "don't do it".

If you could definitively purge that change from all other repos, so that only the local copy is left you could essentially get to the "draft" state. Note that if any repo has the "old" changeset, it will be pushed to the central repo someday and cause the mess that we are trying to avoid.


If the changeset is still local (e.g. in draft status), you can use hg commit --amend if it is the parent of the working directory.

If there are changes after it, I would use mq and hg qimport all the changes down to and including the one where you want to edit the commit message. hg qpop -a and then hg qpush to get to the patch that represents the changeset you want to edit. Then hg qrefresh -e and make your changes. Then just hg qfin -a and you should be good to go.

3
votes

The advice from Edward is good — if you've pushed your changes to another repository, you should consider them set in stone and not update the commit message or any other aspect of them.

However, we're working on changing this in Mercurial. There is an experimental extension that will allow you to do more extensive history editing and push those edits to other repositories. It is called the Evolve Extension and it enables some behavior that is partly in the core of Mercurial and partly outside core.

When using evolve, you can edit the second-to-last commit message like this

$ hg update .^
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg commit --amend -m 'new commit message'
1 new unstable changesets    
$ hg stabilize
more:[5] old tip changeset
atop:[6] new commit message

The extension allows you to do this as long as the changesets are in the draft phase. To keep them in the draft phase after pushing them somewhere, the repository you push to need to be configured as a non-publishing repository. You can read more about this in the Changeset Evolution Documentation.