Sourcetree with Mercurial. Undo commit that has not been pushed - mercurial

I have a Mercurial repository and have made a commit but not pushed it.
I want to undo the commit
I looked at the help here but the menu option "Reset Master to this commit " does not appear for me.
I think the command would be hg rollback.
Is there a menu option in Sourcetree to do this?

hg rollback is deprecated. The current recommendation is to use hg commit --amend.
From http://www.selenic.com/mercurial/hg.1.html#commit:
The --amend flag can be used to amend the parent of the working directory with a new commit that contains the changes in the parent in addition to those currently reported by hg status, if there are any. The old commit is stored in a backup bundle in .hg/strip-backup (see hg help bundle and hg help unbundle on how to restore it).
Message, user and date are taken from the amended commit unless specified. When a message isn't specified on the command line, the editor will open with the message of the amended commit.
According to http://www.sourcetreeapp.com/update/ReleaseNotes.html, Sourcetree is capable of amending a commit since version 1.9.0, but an older thread in answers.atlassian.com suggests using the strip feature in this case and it seems like it is a good solution.
From that thread (before amend was supported):
In Mercurial, you can 'strip' commits, which SourceTree exposes in the log view context menu. If you right-click a commit and choose 'Strip from here', it will destroy that commit at all of its children. However, if you check the box 'Do not modify working copy', you can keep all the changes, and they will become uncommited changes which you can then commit again. So this is similar to the idea of 'amend last commit' if you use it on the latest commit and check the 'Do not modify working copy' box (very important!), then commit again, although Mercurial does this a bit differently.

Related

Why are mercurial log results hidden behind --removed when file wasn't removed?

I've got a strange situation with Mercurial where some commits don't show up in hg log results or TortoiseHG file history. Here are some simplified details.
At the command line, if I type hg log file.txt I get, say, 8 commits showing up. The recent changes to that file on this branch don't show up. The changes on this branch are the result of a few squashed commit ranges from another branch, but no file removals.
If I type hg log --removed file.txt instead, all the commits I expect to see are there.
For the record, typing hg log -r "removes(file.txt)" shows nothing, not surprising since the file has never been removed.
My colleague sees the same issue when looking at their history. The changes are public in a shared repository.
Does anyone have any clues as to what would cause this?
Full disclosure: the changes ported from the other branch were compressed on the original branch, popped off into the patch queue and reapplied onto the new branch. I didn't think this would matter. Also, probably unrelated, these same commits were ported to a different branch via grafting. Interestingly, the graft commits DO show up in the commit log without --removed, though the original commits don't!
Mercurial 3.9.2.
TortoiseHg 4.6.1.
Windows 10.
The documentation(hg log --help) says that:
For performance reasons, 'hg log FILE' may omit duplicate changes made
on branches and will not show removals or mode changes. To see all such
changes, use the --removed switch.
As your changes on the files are the results of squashed commits (how did you squashed them by the way?), it is possible that they have been omitted by this heuristic.

How to reinstate most recent commit in Mercurial?

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'.]

Edit Mercurial Earlier Commit Message - TortoiseHg

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.
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.
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.
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.

TortoiseHG : Removing commit

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

How do you delete a commit in Mercurial?

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