I'm looking for a counter-part of git commit --amend
in Mercurial, i.e. a way to modify the commit which my working copy is linked to. The requirements for this amend-procedure are:
if possible, it should not require any extensions. It must not require non-default extensions, i.e. extensions which do not come with an official Mercurial installation.
if the commit to amend is one head of my current branch, no new head should be created. If the commit is not head, a new head may be created.
the procedure should be safe in a way that if for whatever reasons the amending fails, I want to have the same working copy and repository state restored as before the amending. With other words, if the amending itself can fail, there should be a fail-safe procedure to restore the working copy and repository state. I'm referring to "failures" which lie in the nature of the amend-procedure (like e.g. conflicts), not to file-system-related problems (like access restrictions, not being able to lock a file for writing, ...)
Update (1):
- the procedure must be automatable, so it can be performed by a GUI client without any user interaction required.
Update (2):
- files in the working directory must not be touched (there may be file system locks on certain modified files). This especially means, that a possible approach may at no point require a clean working directory.
Assuming that you have not yet propagated your changes, here is what you can do.
Add to your .hgrc:
In your repository:
Of course you need not start with revision zero or pop all patches, for the last just one pop (
hg qpop
) suffices (see below).remove the last entry in the
.hg/patches/series
file, or the patches you do not like. Reordering is possible too.hg qpush -a; hg qfinish -a
.diff
files (unapplied patches) still in .hg/patches (should be one in your case).If you don't want to take back all of your patch, you can edit it by using
hg qimport -r0:tip
(or similar), then edit stuff and usehg qrefresh
to merge the changes into the topmost patch on your stack. Readhg help qrefresh
.By editing
.hg/patches/series
, you can even remove several patches, or reorder some. If your last revision is 99, you may just usehg qimport -r98:tip; hg qpop; [edit series file]; hg qpush -a; hg qfinish -a
.Of course, this procedure is highly discouraged and risky. Make a backup of everything before you do this!
As a sidenote, I've done it zillions of times on private-only repositories.
I'm tuning into what krtek has written. More specifically solution 1:
Assumptions:
Solution:
hg rollback
to undo the last commitThe rollback really undoes the last operation. Its way of working is quite simple: normal operations in HG will only append to files; this includes a commit. Mercurial keeps track of the file lengths of the last transaction and can therefore completely undo one step by truncating the files back to their old lengths.
You have 3 options to edit commits in Mercurial:
hg strip --keep --rev -1
undo the last (1) commit(s), so you can do it again (see this answer for more information).Using the MQ extension, which is shipped with Mercurial
Even if it isn't shipped with Mercurial, the Histedit extension is worth mentioning
You can also have a look on the Editing History page of the Mercurial wiki.
In short, editing history is really hard and discouraged. And if you've already pushed your changes, there's barely nothing you can do, except if you have total control of all the other clones.
I'm not really familiar with the
git commit --amend
command, but AFAIK, Histedit is what seems to be the closest approach, but sadly it isn't shipped with Mercurial. MQ is really complicated to use, but you can do nearly anything with it.GUI equivalent for
hg commit --amend
:This also works from TortoiseHG's GUI (I'm using v2.5):
Swich to the 'Commit' view or, in the workbench view, select the 'working directory' entry. The 'Commit' button has an option named 'Amend current revision' (click the button's drop-down arrow to find it).
Caveat emptor:
More info about this on the THG dev channel
Recent versions of Mercurial include the
evolve
extension which provides thehg amend
command. This allows amending a commit without losing the pre-amend history in your version control.See https://www.mercurial-scm.org/doc/evolution/user-guide.html#example-3-amend-a-changeset-with-evolve for a complete description of the
evolve
extension.With the release of Mercurial 2.2, you can use the
--amend
option withhg commit
to update the last commit with the current working directoryFrom the command line reference:
The great thing is that this mechanism is "safe", because it relies on the relatively new "Phases" feature to prevent updates that would change history that's already been made available outside of the local repository.