Is there any way to delete local commits in Mercurial?
Asked Answered
C

10

226

So I keep making a silly mistake in Mercurial. Often times, I'll start work without doing an "hg pull" and an "hg update." When I try to push my changes, I get an error.

Is there any way to delete my local commits so I can avoid creating multiple heads, branches, etc? I just want to delete my local commits, merge my changes with the tip, and then re-commit. Sounds simple, right? I can't seem to find any way to easily delete local commits so I can cleanly merge with the tip.

Again, I'm only trying to delete local commits made with "hg ci". I don't want to modify files, revert, etc.

Caren answered 26/2, 2010 at 1:43 Comment(2)
Possible duplicate #2139665Panne
It's not a silly mistake, it's normal workflow when several people are working with the same repository simultaneously.Ryannryazan
J
263

Enable the "strip" extension and type the following:

hg strip #changeset# --keep

Where #changeset# is the hash for the changeset you want to remove. This will remove the said changeset including changesets that descend from it and will leave your working directory untouched. If you wish to also revert your committed code changes remove the --keep option.

For more information, check the Strip Extension.

If you get "unkown command 'strip'" you may need to enable it. To do so find the .hgrc or Mercurial.ini file and add the following to it:

[extensions]
strip =

Note that (as Juozas mentioned in his comment) having multiple heads is normal workflow in Mercurial. You should not use the strip command to battle that. Instead, you should merge your head with the incoming head, resolve any conflicts, test, and then push.

The strip command is useful when you really want to get rid of changesets that pollute the branch. In fact, if you're in this question's situation and you want to completely remove all "draft" change sets permanently, check out the top answer, which basically suggests doing:

hg strip 'roots(outgoing())'
Jadejaded answered 1/7, 2011 at 14:44 Comment(2)
@Bharath: You need to enable the extensionJadejaded
Since mercurial 2.8, strip is a standalone extension, so just strip = is fine. WhatsNew for Mercurial 2.8Regionalism
P
115

If you are using Hg Tortoise just activate the extension "strip" in:

  1. File/Settings/Extensions/
  2. Select strip

Then select the bottom revision from where you want to start striping, by doing right click on it, and selecting:

  1. Modify history
  2. Strip

Just like this:

enter image description here

In this example it will erase from the 19th revision to the last one commited(22).

Phonemics answered 28/11, 2014 at 16:22 Comment(5)
File/Settings/Extensions/ I wish I could add more votes. Thank you very much!Brownlee
Argh! I tried this but it seemed to dump all my changes despite not checking off "no backup" or "discard local changes". I wanted to keep those changes, just not commit them! Is there any way to recover them now??Dialectology
I can't seem to find a way to do it properly, but it seems like to keep the content you need to pass --keep and TortoiseHg doesn't give that option. So... you need to do it at the command line with hg strip -r . --keep.Dialectology
from strip help: 'Any stripped changesets are stored in ".hg/strip-backup" as a bundle (see "hg help bundle" and "hg help unbundle"). They can be restored by running "hg unbundle .hg/strip-backup/BUNDLE", where BUNDLE is the bundle file created by the strip.'Dialectology
In the SourceTree it was useful too. Thanks!Neglect
S
23

Modern answer (only relevant after Mercurial 2.1):

Use Phases and mark the revision(s) that you don't want to share as secret (private). That way when you push they won't get sent.

In TortoiseHG you can right click on a commit to change its phase.

Also: You can also use the extension "rebase" to move your local commits to the head of the shared repository after you pull.

Sweetbread answered 20/8, 2013 at 4:27 Comment(1)
Private == secret nowElspet
H
17

As everyone else is pointing out you should probably just pull and then merge the heads, but if you really want to get rid of your commits without any of the EditingHistory tools then you can just hg clone -r your repo to get all but those changes.

This doesn't delete them from the original repository, but it creates a new clone that doesn't have them. Then you can delete the repo you modified (if you'd like).

Hug answered 26/2, 2010 at 3:9 Comment(2)
Does "hg clone -r" delete local changes? I just want to delete local commits to keep things simple.Caren
It doesn't delete them from the cloned repository, but it creates a new clone that doesn't have them. Then you can delete the repo you modified if you'd like.Hug
R
11

I came across this problem too. I made 2 commit and wanted to rollback and delete both commits.

$ hg rollback

But hg rollback just rolls back to the last commit, not the 2 commits. At that time I did not realize this and I changed the code.

When I found hg rollback had just rolled back one commit, I found I could use hg strip #changeset#. So, I used hg log -l 10 to find the latest 10 commits and get the right changeset I wanted to strip.

$ hg log -l 10
changeset:   2499:81a7a8f7a5cd
branch:      component_engine
tag:         tip
user:        myname<[email protected]>
date:        Fri Aug 14 12:22:02 2015 +0800
summary:     get runs from sandbox

changeset:   2498:9e3e1de76127
branch:      component_engine
user:        other_user_name<[email protected]>
date:        Mon Aug 03 09:50:18 2015 +0800
summary:     Set current destination to a copy incoming exchange

......

$ hg strip 2499
abort: local changes found

What does abort: local changes found mean? It means that hg found changes to the code that haven't been committed yet. So, to solve this, you should hg diff to save the code you have changed and hg revert and hg strip #changeset#. Just like this:

$ hg diff > /PATH/TO/SAVE/YOUR/DIFF/FILE/my.diff
$ hg revert file_you_have_changed
$ hg strip #changeset#

After you have done the above, you can patch the diff file and your code can be added back to your project.

$ patch -p1 < /PATH/TO/SAVE/YOUR/DIFF/FILE/my.diff
Restaurateur answered 14/8, 2015 at 7:19 Comment(0)
R
10

You can get around this even more easily with the Rebase extension, just use hg pull --rebase and your commits are automatically re-comitted to the pulled revision, avoiding the branching issue.

Rationality answered 26/2, 2010 at 2:2 Comment(1)
At the expense of having an inaccurate history and possible corruption if you do things wrong.Hug
S
6

hg strip is what you are looking for. It's analogous of git reset if you familiar with git.

Use console:

  1. You need to know the revision number. hg log -l 10. This command shows the last 10 commits. Find commit you are looking for. You need 4 digit number from changeset line changeset: 5888:ba6205914681

  2. Then hg strip -r 5888 --keep. This removes the record of the commit but keeps all files modified and then you could recommit them. (if you want to delete files to just remove --keep hg strip -r 5888

Seasickness answered 3/11, 2017 at 12:37 Comment(0)
P
5

If you are familiar with git you'll be happy to use histedit that works like git rebase -i.

Perigordian answered 29/8, 2014 at 18:0 Comment(0)
V
4

[Hg Tortoise 4.6.1] If it's recent action, you can use "Rollback/Undo" action (Ctrl+U).

HG Tortoise Image

Verticillaster answered 29/4, 2020 at 7:16 Comment(1)
Double check the inclusion of an image.Hirza
J
2

In addition to Samaursa's excelent answer, you can use the evolve extension's prune as a safe and recoverable version of strip that will allow you to go back in case you do anything wrong.

I have these alias on my .hgrc:

 # Prunes all draft changesets on the current repository
 reset-tree = prune -r "outgoing() and not obsolete()"
 # *STRIPS* all draft changesets on current repository. This deletes history.
 force-reset-tree = strip 'roots(outgoing())'

Note that prune also has --keep, just like strip, to keep the working directory intact allowing you to recommit the files.

Jitney answered 25/6, 2020 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.