We've all been there at some point -- you move a file using something other than Mercurial's hg move
command and commit and push your changes only to realize your mistake much later. Is there any way to later inform Mercurial that there is a relationship between the "old" path and the "new" path?
I've tried playing with --after
but that just seems to error out unless you happen to catch the problem before committing the problem changeset:
> hg move OLD_PATH NEW_PATH --after
OLD_PATH: The system cannot find the file specified
abort: no files to copy
In my particular situation, this change was committed by a coworker across a messy private branch (or two) and then merged to our default
branch and pushed to our main repo, so it's already spread out to the entire team.
Any ideas?
To revert a file to a specific changeset, use hg revert -r CHANGESET FILENAME . This will revert the file without committing it.
hg rollback reverts the last transaction, so you'd be left with unfinished merge, which you have to use hg update -C to get out. If you don't want *b (you have it in another clone), then enable the built-in MQ extension and run hg strip -r <*b> . It will get rid of *b and *merge.
The hg backout command lets you “undo” the effects of an entire changeset in an automated fashion. Because Mercurial's history is immutable, this command does not get rid of the changeset you want to undo. Instead, it creates a new changeset that reverses the effect of the to-be-undone changeset.
First of all, are you sure that the rename wasn't detected? Mercurial will detect moves where the file remains unchanged (i.e. where it wasn't a rename + edit) by default and record it as a rename. Verify that it wasn't actually detected with hg log -f NEW_PATH
.
If it wasn't recorded as a rename, do a branch off the old commit with a proper rename and merge:
hg update -r ORIGINAL_COMMIT # Go to the commit before the rename
hg move OLD_PATH NEW_PATH # Record the rename
hg commit # Commit the rename
hg update default # or whatever your main branch is
hg merge -r tip --tool :other # '-r tip' is technically optional
hg commit # Commit the rename to the main branch
hg log -f NEW_PATH # Verify that it worked
Note that --tool :other
will prioritize the "other" branch (i.e. the new commit) and learn the proper history from there.
Postscript: It is also possible to alter the history after the fact, but for that you need the evolve extension. With that, you can alter a commit after the fact (with hg amend
or hg commit --amend
) and propagate the change through your history (with hg evolve --all
) [1]. However, other members of your team may also need the evolve extension; plus, the shared repository that you push to/pull from needs to be set up for it (as a non-publishing repository). While this is possible, the setup effort, and the training your team may need to become proficient may not be worth it; also, other Mercurial-related tools may not understand it and become confused by it. In short: this is currently an advanced option that you should only use with full understanding and if the alternatives are insufficient.
[1] Note that hg evolve
will not actually modify history, but create a new alternate history, related to the original one via so-called obsolescence markers. The old history can be viewed with hg log --hidden
(or other commands with the --hidden
flag).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With