I've accidentally committed bunch of files locally, but didn't pushed.
So basically what I want to do is to remove this my commit, then push some other changes.
I can remove the commit by Backout-ing, then I've to commit locally so it is actually removed locally.
So my question is following, if I do a push, will my accidental commit and its corresponding revertion log be visible publically ?
It sounds like hg rollback is the command you want.
hg backout <REV> creates a new commit that reverses the changes made in <REV>. Both the original commit and the backout commit will remain in your history. This is one of the few options you have to fix a bad commit after you have pushed it to a public location.
However in this case you have not pushed to the public yet, so there are better solutions.
If the bad commit is the last commit that was done (i.e. your tip) then you can use hg rollback (under the Repository menu in TortoiseHg). This command is like "undo" for commits.
If the bad commit is elsewhere in your history (but still has not been pushed to a public repo), you can also use the mq extension to rewrite that part of your history.
You could use hg strip -r . --keep instead of hg rollback. hg backout would be necessary only if you had pushed your commits.
The simple answer to your question is Yes.
If you perform a Backout, then it will show up in your history.
You want to perform a Strip, as previously suggested.
This is an extension to mercurial.
https://www.mercurial-scm.org/wiki/StripExtension
Related
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
How do I view commits that are about to be pushed?
I'd made a local commit. Pull a change. And no it requires a merge.
I prefer not to merge and would like to undo the commit,
Pull,
Update changes,
Then commit again.
How do I do it since rollback only undo the last command which is pull?
That's really the way Mercurial works, and you shouldnt fight it in the name of a straight linear history, but there are tools that can edit history. Enable the rebase extension and just run hg rebase after your pull. It will move your local commit to the tip automatically in the simple case you described.
How do I view commits that are about to be pushed?
Use hg outgoing. That shows what hg push would have sent to the server. The opposite command is hg incoming, which shows what hg pull would have retrieved.
I'd made a local commit. Pull a change. And no it requires a merge. I prefer not to merge and would like to undo the commit, Pull, Update changes, Then commit again.
Like Mark says, you're looking for the rebase extension. Enable it with
[extensions]
rebase =
in your config file and then run
$ hg pull
$ hg rebase
to move your local work (this can be multiple changesets, not just a single as in your work around!) on top of the changesets you just pulled down.
How do I do it since rollback only undo the last command which is pull?
Please don't use hg rollback as a general undo mechanism. It's a low-level command that should not be used as much as it is, especially not by new users. The rollback command removes the last transaction from the repository — a transaction in Mercurial is typically the last changeset you made or the last changesets (plural) you pulled into the repository.
I want to completely delete a Mercurial commit as if it was never entered in the repository and move back to my prior commit.
Is this possible?
If it was your last commit and you haven't pushed it anywhere, you can do that with rollback. Otherwise, no. Not really. Time to change your passwords.
Edit: It has been pointed out that you can clone from an older revision and merge in the changes you want to keep. That's also true, unless you have pushed it to a repo you don't control. Once you push, your data is very likely to be very hard to get back.
You can try to remove mq info about your commit.
For this you need to go File->Settings->Extensions.
There check mq and restart gui.
After that just right click on unneeded commit and
ModifyHistory->Strip
To edit the history I would use the Histedit Extension extension.
hg histedit 45:c3a3a271d11c
However keep in mind this only makes sense in a situation where you have not yet pushed the commits to the public repository, you own the public repository and/or you can account for all the clones out there. If you receive the following error:
abort: can't rebase immutable changeset 43ab8134e7af
It means that Mecurial thinks this is a public changeset (see phases) that has already been pushed - you can force it to be a draft again doing:
hg phase -f -d 45:c3a3a271d11c
I encounter this fairly often. I make a commit and then pull to push. But then there is something incoming that makes my newly made commit unnecessary. A plain hg rollback isn't enough because it only undoes the pull...
This is the thing to do:
hg strip <rev>
Things are painless when you don't push your changesets anywhere.
If it's more than one commit and/or you already pushed it somewhere else, you can clone your repository and specify the last changeset that should be cloned.
See my answer here how to do this:
Mercurial: Fix a borked history
If you only committed locally and didn't push, you can just create a clone locally (as described in my link) and you're done.
If you already pushed to some remote repository, you would have to replace that with your clone.
Of course it depends if you are able (or allowed) to do this.
You can use "hg backout" to do a reverse merge basically. All options are discussed in the freely available book "Mercurial: The Definitive Guide":
http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html
If using tortoise you can use modify history > strip...
Yes. Unless I am mistaken, as of v2.3 (rel. 2012/08/01) you can use the HisteditExtension with a drop command to drop a commit, along with strip or backout to remove changes.
A simple Google search on the feature: https://www.google.com/webhp#q=histedit+drop
In 2022 I do use evolve extension. It is one of the best extensions for this purpose.
To prune unwanted changeset, if you for example did a quick hack to get the code working:
$ echo 'debug hack' >> file1.c
$ hg commit -m 'debug hack'
Now you have a proper patch you can do hg prune .:
$ hg prune .
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
working directory is now at 2a39221aaebb
1 changesets pruned
If you push the change to the remote repository you will find only obsolescence markers:
$ hg push
searching for changes
no changes found
remote: 1 new obsolescence markers
To check the changes to your local repo you can pull from the remote one:
$ hg pull
pulling from ssh://userid#server/repo
searching for changes
no changes found
I am aware that rollbacks can remove commits from the latest changeset in a local repository. However, is it possible to remove all the latest commits since the previous push without having to re-clone the share repository?
You can use the hg strip command, part of the mq extension:
hg strip REV
This will remove that revision + all its descendants.
Before you try this, make a copy/clone of the repository to experiment in.
You could make a new repo with hg clone:
hg clone -r last_good_changeset localrepo newlocalrepo
If you are using mercurial eclipse, you can rollback once, then shelve those changes, then export the multiple sequential commits as patches, strip those commits, then import those patches in the same order, so in case you had conflicting patches, they overwrite each other in the desired way.
Finally you can unshelve your first rollback. This achieves the same effect as if you were rolling back more than once.
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