mercurial discard all added files prior to a commit - mercurial

Just made the mistake of using addremove to try and remove some files that were deleted without using hg remove
Now have hundreds of files that are going to be added on the next commit
Is there anyway I can quickly remove all these added files without having to resort to a bash script or even worse hg removing or forgetting each file manually?

If you want to just use internal hgcommands, you can do the following:
hg forget "set:added()"
Which will forget any file that's marked as "added" in the working directory. It makes use of the rather powerful filesets feature of Mercurial.
There are additional filters you can use when specifying files, which allows you to easily fix other mistakes. For example, easily re-add removed files but nothing else hg add "set:removed()". The functionality is similar to (tho' thankfully simpler than) mercurial revsets, and can be studied with:
hg help filesets

You do it quite easily on the command line using something along the lines of :
hg status --added --no-status | xargs hg forget
This should forget all files added since the last commit.
May I suggest to add the files you never want to add to a .hgignore file so this won't happen again ?

Related

How to diff two revisions of a file that got renamed in between and Mercurial doesn't know about the renaming?

I accidentally renamed a file outside of Mercurial. When I committed the change, Mercurial treated the change as two unrelated files (ie. a remove and a add). I need to go back to diff the two revisions but I don't know how to do so when Mercurial sees them as two respective files across different revisions. What can I do to diff the files?
You didn't say what operating system you were using. The following will work with bash on Linux:
diff <(hg cat -r rev1 file1) <(hg cat -r rev2 file2)
You can replace diff with another program like vimdiff if you want a visual diff.
If you want to actually fix the history so that Mercurial is aware of the rename (and can use that information in future merges if needed), there's a way to do so documented on the Tips and Tricks page on the Mercurial wiki.
Current contents copied here for ease of use (and in case the link gets broken later):
Steps:
Update your working directory to before you did the rename
Do an actual "hg rename" which will create a new head
Merge that new head into the revision where you did the "manual" rename (not the head revision!)
Then finally merge the head revision into this merge result.
Advice:
Make a clone first and work on that, just in case!
After finishing the steps, use a file compare tool to check that the original and the clone are identical
Check the file history of any moved file to make sure it is now restored
That being said, if all you want to do is compare the contents at the point in time, you can definitely accomplish that without making Mercurial aware of the rename (as mentioned in Stephen Rasku's answer). In fact, you can use a combination of "hg cat" and an external comparison tool to compare any files, not just ones that Mercurial knows about.
Fix history:
Update to first changeset with new-filename, save file outside WC
Update to parent of bad replacement changeset, replace file correctly (with rename tracking), commit, got second head
Rebase all changesets from old anonymous branch on top of fresh good changeset
--close-branch on bad-replacement changeset or delete this unwanted changeset or leave inactive head intact

Rollback of the last command in Mercurial

I just ran:
hg add .*
which matched all ../something files and which was something I certainly did't want! What is the easiest way to undo this command?
Not exactly what I was after, but made my life easier:
hg forget "set:added()"
this unmarks all the files that were added in the working repository. Obviously I also unmarked all the files that were added in preceding commands, so as I said this is not exactly what I was after...
If you've got a lot of uncommitted adds that you don't want to have to do over, you can use a mercurial fileset that only picks out pending adds in subdirectories of the parent directory (use this in the same directory where the erroneous command was issued):
hg forget "set:../** and added()"
Mercurial doesn't remember what path you used to refer to a file, so this will forget all files (under the parent directory) that were just added; but if you were deep in a large repository, it'll limit the scope of what you discard.
Your question is similar to this recent question, but here we have an extra condition on the mistakenly added filenames.
There is not built-in way to undo a hg add command.
The underlying problem is that hg add is manipulating the so-called "dirstate" (short for "working directory state". This is where pending changes such as files scheduled for commit is stored — and this storage is unversioned.
There is an extension, though, that can help you: hg-multiundo will make backups of all files touched by Mercurial, including the dirstate. This means that you can use it to undo things like hg add or even hg revert --no-backup.

How to re-commit last changeset with a different comment?

As I understand it, you can't really fix a comment in Hg. So what I would like to do instead is re-push the exact same changes (or at least "touch" the same files and commit & push again).
The reason this is necessary is because we have a bug tracking and build system that relies on specific comment patterns, and we need to make sure the right files get included in the build, but if I forget to update the bug # in my comment from my last commit, and I accidentally commit and push it under the wrong # because i'm overzealous, how can I re-push those same files again without manually going into each one and adding a space or line break just to create a diff?
To clarify, I can't "rollback" or something; it's already been pushed with the wrong message.
As far as I know, current Mercurial features provide no support for this. After the changeset has been pushed, there's little you can do to un-push it, besides stripping it from the server repo and any other developer's repo.
I guess you you should ask those who set up this workflow in your shop; they should've come up with some exception handlers for it.
We usually just ignore issues like this, and close the bug by hand, making sure the bug links to the correct changeset. If the changeset is really messed up (usually this means bad changes, not a malformed commit message), we resort to stripping.
Since your change has already been pushed you can't use a simple fix, like "hg commit --amend", but you can do something similar. Basically, the following commands re-do the commit with Mercurial's help:
CSET=...the changeset to re-do...
hg up -r "p1($CSET)" # Update the working directory to the parent revision
hg log -r "$CSET" -p > changes.patch
hg import --no-commit changes.patch
hg commit # And use the appropriate commit message.
Then, merge and push.
The only way that I could think of doing this is to commit two more changes, one would be an hg backout of the incorrect revision and the other would be an hg backout of that revision with the corrected comment.
I don't like that idea though and wouldn't recommend it if there was any way to fix the problem in your bug tracking system.

using hg revert to revert a group of files in Mercurial

I'm using Mercurial to read and debug a complex project, and my modify of the project can be divided into different group of files clearly. For example, if I modified four files
src1.cc src1.hh src2.cc src2.hh
It's apparent that I can divide them into two file groups such as group src1 includes src1.cc src1.hh and group src2 includes src2.cc src2.hh.
I'm wondering if I can revert a group of files by a simple command like 'hg revert group-name-alias' instead of listing all the filename of the group, which is a awful idea if I have modified many files?
Any help really appreciated!
From what I can understand of your use-case, you can:
Use patterns in the hg revert command. This means that you can
run hg revert src1* to revert all the first group.
Most probably, though, your stuff is in sub-folders and thankfully
you can specify a parent folder to the revert command.
So say your files are really like: foo/src1.cc, foo/src1.hh,
bar/src2.cc, bar/src2.hh. In that case, you can revert all the
second group with hg revert bar, assuming you're in the top folder.
If you're already in the bar folder, you can run hg revert ..
You can specify several patterns.
Use Mercurial queues if each one of your "file groups" is also
a different unit of work (a different bug fix or feature). This is not
so desirable if all files belong to the same unit of work, though.
No. To the best of my knowledge, Mercurial has no mechanism for grouping files.
You could do some trickery with aliases ([alias] revert-group-name = revert src2.cc src2.hh in ~/.hgrc), but aliases can only be prefixes, and can't perform variable expansions.
If your files are simple enough, you could use shell globbing (hg revert src2*), or a shell variable (GROUP_NAME="src2.cc src2.hh", then hg revert $GROUP_NAME).
You could also consider writing a small Mercurial extension. If you know Python, they don't take very long (my first took me about 30 minutes).
If the filenames meet patterns, you can use that pattern:
hg revert src1*
or
hg revert src1*.*
If those files are in a specific directory, you can do this:
hg revert dir\*
If the directory is more than one level deep and you want to get that directory and all its subdirectories, you can use this version of that commend:
hg revert dir\**\*

How do I unadd a not yet committed file I have added?

I typed in hg add and I am brand new to mercurial and the result of this was a bunch of dll's exe's pdb's etc all got added
Nothing's been committed yet and I basically want to undo the add.
the documentation for hg forget is not very clear not sure if that is want I want
How do I undo the add before the next commit
I do have some real files that need adding so after I can undo the add I will use add with the exclude flag
Thanks
Check out this mercurial tip. To cite the link - if you have accidentally added a file, the way to undo that (changing its status from A back to ?, or unknown) is hg revert. For example, if you just ran hg add and realized that you do not want files foo or bar to be tracked by Mercurial:
hg revert foo bar
Either revert or remove can be used to un-add not yet commited stuff. However, they both have other uses too, so for clarity hg forget was (re-)added in 1.3, and despite its name it might be easier to remember.
If you are using a Unix like system i believe the best option is to run
hg status -an0 | xargs -0 hg revert
Two tips for these sorts of situations:
If nothing has been commited at all, just delete .hg and start over with hg init.
If you do something terrible to your repository and can't seem to figure out how to undo it, (and hg update -C or revert all won't fix), consider cloning the repository at the last good spot.