I renamed a few directories in my mercurial repository [not by hg rename command i was not aware of that at that time] just by doing a mv on my linux box , and then I realized that I want the things the way they were before so I did a hg rollback. But it didnt' restore the things to the state they were , how can i get my last commit?
The hg rollback did remove your the latest commit¹. You need to move the directories back with mv, and redo you last commit.
When you encounter the same situation again, you can use hg revert to replace the changes in the working copy by the content of the current revision. But since your current revision is the revision before your last commit, using revert now would also undo the changes of your last commit.
As a rule of thumb never use rollback², since you get the effect of rollback also with the much more safe mq extension.
¹Technically it removed the latest transaction, but it is very likely that your last transaction was a commit.
You want revert. Try
hg revert -a
or specify a directory if you want to revert just that directory.
Related
I use Mercurial, and I immediately push every commit to BitBucket.
I recently made a commit to my local repository, and pushed it to BitBucket via hg push. Later, I realised that I shouldn't have made that commit, so I tried:
$ hg rollback
repository tip rolled back to revision 37 (undo push-response)
But the file in Xcode did not change. I closed the Xcode window and reopened it, but no change. I tried to revert the rollback in Bitbucket, but that didn't work either:
$ hg push ssh://hg#bitbucket.org/myuser/myproject
pushing to ssh://hg#bitbucket.org/myuser/myproject
searching for changes
no changes found
How do I rollback, both locally and in BitBucket? I want the code to go back to the state it was in before the bad commit.
You can't rollback in Bitbucket, you have to strip the change from the repository.
In Bitbucket, go to the repository Settings and then Strip commits. Enter the hash id of the commit and click Preview strip, then if you're happy that it's going to strip the right commit you can confirm it.
Now you can remove or edit the commit in your local copy.
hg rollback isn't recommended these days, if you can fix the commit you can use hg commit --amend to update it before pushing again.
Rollback will remove the commit and leave the changed files in an uncommitted state in your working directory. It appears from the message you got that your rollback succeeded, and I wouldn't expect the file to change in XCopy because it leaves the change in your working directory, but if you look at what the tip of the repository is now your commit should be gone and if you look at the state of your working directory you should have uncommitted changes corresponding to your unwanted change.
You should be able to hg revert any uncommitted changes you don't want.
If the commit is still there, and you want to get rid of it completely and don't want to keep the code at all you can use hg strip to remove it (you may need to activate the strip extension in the mercurial settigs first).
Mercurial - Finding and fixing mistakes
Strip extension
I've searched the docs of Mercurial and still am confused. What I'm wanting to do is just reinstate the last commit I made i.e. I want my project to go back to being exactly the same as it was when I made the last commit. I see hg revert, rollback, etc. and still am not understanding which is correct for this situation. Which should I use?
The hg rollback command is used to undo the last action that modified Mercurial's internal store, usually a pull or commit. So, if you want to undo your last commit hg rollback will work.
But it sounds like you want to undo all your uncommitted changes. You have two options. The hg revert --all command will undo all uncommitted changes. Each changed file is saved/backed-up with a .orig extension before being reverted.
If you don't need to preserve your changes in .orig files, run hg update -C. This clears out all uncomitted changes, without preserving anything.
If you have commited changesets and wish to remove them, I like the strip extension, strip extension. With it, you can remove explicit changesets from your history.
However, strip is an unforgiving command, i.e. if you get it wrong there is no retrieval unless you have a backup of the repo. You might prefer the prune command which comes with the evolve extension. Using prune, you can mark changesets as obsolete and they will no longer normally be visible in logs or tortoise. [You can make them visible by adding --hidden on an hg log command line, or in tortoise by enabling the Filter toolbar (from the view menu) and selecting 'Show/Hide hidden changesets'.]
what would be an equivalent mercurial command (or workflow) for
git reset --mixed HEAD^
or
git reset --soft HEAD^
i.e. I want leave the working tree intact but get the repository back into the state it was before the last commit. Surprisingly I did not find anything useful on stackoverflow or with google.
Note that I cannot use
hg rollback
as I've done some history rewriting using HistEdit after the last commit.
Added to clarify:
After some rebasing and history editing I had ended up with A<--B<--C. Then I used HistEdit to squash B and C together, obtaining A<--C'. Now I want to split up the commit C' (I committed the wrong files in B). I figured the easiest way to do this was to get the repository back to state A (which technically never existed in the repository because of all the rebasing and history editing before hand) and the working tree to the state of C' and then doing two commits.
The right way to replicate git reset --soft HEAD^ (undo the current commit but keep changes in the working copy) is:
hg strip --keep -r .
-1 will only work if the commit you want to strip is the very last commit that entered the repository. . refers to the currently checked out commit, which is the closest equivalent Mercurial has to Git's HEAD.
Note that if . has descendants, those will get stripped away too. If you'd like to keep the commit around, then once you have the commit ID, you can instead:
hg update .^
hg revert --all -r <commit id>
This will update to the commit's parent and then replace the files in the working copy with the versions at that commit.
I believe the more modern and simpler way to do this now is hg uncommit. Note this leaves behind an empty commit which can be useful if you want to reuse the commit message later. If you don't, use hg uncommit --no-keep to not leave the empty commit.
hg uncommit [OPTION]... [FILE]...
uncommit part or all of a local changeset
This command undoes the effect of a local commit, returning the affected
files to their uncommitted state. This means that files modified or
deleted in the changeset will be left unchanged, and so will remain
modified in the working directory.
If no files are specified, the commit will be left empty, unless --no-keep
Suppose you have commit some changes, and then somehow deleted/modified some files by accident.
Which would be better? Using revert oder update?
There are two big differences between running hg update -C and doing hg revert -a
Update will move your parent up to the tip of the head of the branch
Update will no create any backup files
The revert command on the other hand
Creates backups of all reverted files (unless you give --no-backup command)
Does not change your working directories parent changeset.
Now which is better? Depends in which of the things listed above you want.
In your case you want revert -- it alters your working directory without altering the output of the hg parents command. Your parent revision is the "currently checked out revision" and will become the "parent" of your next commit. You don't need to alter that pointer, so just revert.
hg backout tip seem to also revert all your files back to the older version. Is there a way to change it back to EXACTLY like before the commit -- that is, with several files "Modified" but uncommitted -- essentially, as if the "commit" was never done?
(hg rollback is said to be very bad and usually shouldn't be done for version control purpose)
hg rollback does exactly what you are asking for - it undoes the hg commit and you end up in the state you were before you committed.
Of course it's not really in the intention of a version control system to "lose" versions you already committed, but it's handy to revert an accidental commit.
Once you push, of course, there is no tool that will do what you want. That being said, if you have more than one changelist that you want to remove from your local history rather than just undoing their effect with hg backout, then you can use hg strip, which is available as part of the MQ extension package.
You can do the following to get your desired effect:
hg export tip > foo.patch
hg strip tip
hg import --no-commit foo.patch