Make Mercurial not to commit anything, unless the filenames are explicitly specified - mercurial

according to Mercurial's commit help message:
If a list of files is omitted, all changes reported by "hg status" will be
committed.
Is there an easy way to change this behavior?
I'd like Mercurial not to commit any changes, unless the files are explicitly specified.
edit
I am on Linux and I am using the command line.

This seems to do the trick:
$ hg commit -X *
nothing changed
It doesn't do anything because all files are excluded, but if you give any files, those will be included.
You could alias it:
[alias]
xcommit = commit -X *
then:
$ hg status
M a
M b
$ hg xcommit -m 'no files specified'
nothing changed
$ hg xcommit -m 'picking a' a
$ hg status
M b
Personally I wouldn't want to get used to this type of workflow. It's usually just as easy to:
work in smaller chunks so your changes reflect a single changeset
for the times when you forget and you're on a coding spree, use something like hg record
for the really few times when the above two don't fit, use -I/-X for that single commit

if you are using GUI like tortoiseHg you can select the files you need to commit. http://tortoisehg.bitbucket.io/

Related

Why does "hg status" show changed files when "hg diff -g" doesn't? (One parent)

I have a repository where:
> hg st
shows that my working directory has some uncommitted changes, while
> hg diff
> hg diff -g
> hg diff --git
display nothing.
I read here: 4.10. hg status shows changed files but hg diff doesn't! the following:
hg status reports when file contents or flags have changed relative to either parent. hg diff only reports changed contents relative to the first parent. You can see flag information with the --git option to hg diff and deltas relative to the other parent with -r.
However, if I run hg parents it shows only one parent (the tip). As I mention above, I have also tried hg diff --git and it still displays nothing.
Note:
The above is on Mercurial version 2.0.1
hg status only shows M next to a regular file.
hg diff and hg diff -g print nothing
The filesystem is NFS.
hg parents prints only one parent
Some excerpts from Mercurial in daily use (Mercurial: the definitive guide) (copying here because there seems to be no way to give a convinient link to the end of the page):
The default output of the hg diff command is backwards compatible with the regular diff command, but this has some drawbacks.
The output of hg diff above obscures the fact that we simply renamed a file. The hg diff command accepts an option, --git or -g, to use a newer diff format that displays such information in a more readable form.
This option also helps with a case that can otherwise be confusing: a file that appears to be modified according to hg status, but for which hg diff prints nothing. This situation can arise if we change the file's execute permissions.
The normal diff command pays no attention to file permissions, which is why hg diff prints nothing by default. If we supply it with the -g option, it tells us what really happened.
To summarize, hg diff command misses several kinds of information on changes: attributes, permissions, file names, etc. These changes may exist even if you have a single parent. And hg status correctly takes into account all changes. To see what has happened, use hg diff -g. It's the answer to the question 'what happens'.
Seems like backwards compatibility is the 'why'. I'm not sure, but I suppose that the 'normal diff' is some widespread or built-in Unix/Linux tool (judging from the fact that both hg and git come from that world).
In these situations (it happens a lot to my team), I find that this command will fix about anything:
hg debugrebuilddirstate
or
hg debugrebuilddirstate -r tip
It's lightly documented in the help documentation, but basically I believe it clears out the "dirstate" file which caches information about working-directory files. The next time you hg stat it will refresh it from scratch.
One caveat: if you've added or removed files, that information will be lost when the dirstate is rebuilt.
If you have ignorews or ignoreblanklines set in .hgrc then hg status will show it as changed but hg diff won't (assuming the changes are only whitespace of course).
I just deleted the files that showed up as modified (make a backup if needed) which caused all the files to show up with an ! next to it when I ran
hg st
After that I ran the following command to revert the files (which were already checked in):
hg revert --all --no-backup
and that fixed the problem
In my case something was broken with hg. (same permissions and hg diff -g shows nothing).
I fixed issue with next way:
I cloned repository again in separate folder
I removed everything from this folder except .hg
I moved from old (broken) place everything except .hg to new place
So after this step i have repository which cloned with current version of mercurial + exactly same files.
After this steps i received same (empty) results for commands: hg st and hg diff -g

tortoisemerge with Hg reports all lines as changed

I'd like to use TortoiseMerge with Mercurial to resolve conflicts, but its reporting every line in theirs and mine as added as though its not comparing properly
here is my mercurial.ini:
[ui]
merge = TortoiseMerge
[merge-tools]
TortoiseMerge.executable=C:\Program Files\TortoiseSVN\bin\TortoiseMerge.exe
TortoiseMerge.args=/mine:$local /theirs:$other /base:$base -o /merged:$output
I'm using Hg 1.7.5
What's going on?
Update: When using KDiff or BeyondCompare, the base is always empty.
Thanks
Your setup appears correct.
This is symptomatic of having no copy of the file in the base revision, in which case Mercurial acts as if the file was present but empty.
There are a couple ways of figuring out what's going on here. If there are no copies or renames involved, you should be able to simply do:
$ hg log -r "ancestor(p1(), p2())"
..to determine the ancestor of the merge, then:
$ hg manifest -r <rev> | grep <your file>
..to determine if the file was in fact present.
Alternately, you can run 'hg merge --debug' or 'hg update --debug' to see what changeset and file it's choosing for the merge (including rename/copy details).
If you find that the file is present in the common ancestor Mercurial chooses, then you should report a bug (including your debug output) at:
https://www.mercurial-scm.org/wiki/BugTracker

Discard all and get clean copy of latest revision?

I'm moving a build process to use mercurial and want to get the working directory back to the state of the tip revision. Earlier runs of the build process will have modified some files and added some files that I don't want to commit, so I have local changes and files that aren't added to the repository.
What's the easiest way to discard all that and get a clean working directory that has the latest revision?
Currently I'm doing this:
hg revert --all
<build command here to delete the contents of the working directory, except the .hg folder.>
hg pull
hg update -r MY_BRANCH
but it seems like there should be a simpler way.
I want to do the equivalent of deleting the repo, doing a fresh clone, and an update. But the repo is too big for that to be fast enough.
Those steps should be able to be shortened down to:
hg pull
hg update -r MY_BRANCH -C
The -C flag tells the update command to discard all local changes before updating.
However, this might still leave untracked files in your repository. It sounds like you want to get rid of those as well, so I would use the purge extension for that:
hg pull
hg update -r MY_BRANCH -C
hg purge
In any case, there is no single one command you can ask Mercurial to perform that will do everything you want here, except if you change the process to that "full clone" method that you say you can't do.
hg up -C
This will remove all the changes and update to the latest head in the current branch.
And you can turn on purge extension to be able to remove all unversioned files too.
To delete untracked on *nix without the purge extension you can use
hg pull
hg update -r MY_BRANCH -C
hg status -un|xargs rm
Which is using
update -r --rev REV revision
update -C --clean discard uncommitted changes (no backup)
status -u --unknown show only unknown (not tracked) files
status -n --no-status hide status prefix
hg status will show you all the new files, and then you can just rm them.
Normally I want to get rid of ignored and unversioned files, so:
hg status -iu # to show
hg status -iun0 | xargs -r0 rm # to destroy
And then follow that with:
hg update -C -r xxxxx
which puts all the versioned files in the right state for revision xxxx
To follow the Stack Overflow tradition of telling you that you don't want to do this, I often find that this "Nuclear Option" has destroyed stuff I care about.
The right way to do it is to have a 'make clean' option in your build process, and maybe a 'make reallyclean' and 'make distclean' too.
If you're looking for a method that's easy, then you might want to try this.
I for myself can hardly remember commandlines for all of my tools, so I tend to do it using the UI:
1. First, select "commit"
2. Then, display ignored files. If you have uncommitted changes, hide them.
3. Now, select all of them and click "Delete Unversioned".
Done. It's a procedure that is far easier to remember than commandline stuff.

In Mercurial (hg), how do you see a list of files that will be pushed if an "hg push" is issued?

We can see all the changesets and the files involved using
hg outgoing -v
but the filenames are all scattered in the list of changesets.
Is there a way to just see a list of all the files that will go out if hg push is issued?
First, create a file with this content:
changeset = "{files}"
file = "{file}\n"
Let's say you call it out-style.txt and put it in your home directory. Then you can give this command:
hg -q outgoing --style ~/out-style.txt | sort -u
A somewhat under-appreciated feature: hg status can show information about changes in file status between arbitrary changesets. This can be used to get a list of files changed between revisions X and Y:
hg status --rev X:Y
In this case, we can use hg outgoing, to find the first outgoing changeset X and then do
hg status --rev X:
to see the files changes since revision X. You can combine this into a single line in your shell:
hg status --rev $(hg outgoing -q --template '{node}' -l 1):
I usually use
hg outgoing -v | grep files
It makes the listing shorter, but doesnt sort. But thus far I havent been in a situation where I want to push so much (and at the same time check the files) that its been a problem.
[Edit]
To do what you want:
Use cut to remove the files: part
For changesets with more than one touched file, use tr to put them on separate lines
Finally sort the resulting output with sort
Like so:
hg outgoing -v |grep files: |cut -c 14- |tr ' ' '\n' |sort -u
You can put this in ~/outgoingfiles.sh or something to have it nice and ready.
I use Torgoise Hg, which is a shell extension that has a "synchronize" view allowing you to see outgoing files before you push them. It's convenient for commits as well, and other things.
A simple hg out will also solve this.
It will list all committed but yet to push checkins.

Undo a remove action in Mercurial

Suppose that I have made some changes in the working directory and accidentally marked several files (that include some of the modified ones) for removal. How do I unmark the files for removal without losing the changes I have made?
Just hg add the files.
I don't know why you're getting some many answers that modify the working directory. If you've accidentally marked some files for removal you can undo it with add.
ry4an#four:~/hgtest$ hg status --all
M another_file
C a_file
ry4an#four:~/hgtest$ hg remove --after --force *
ry4an#four:~/hgtest$ hg status --all
R a_file
R another_file
ry4an#four:~/hgtest$ hg add *
ry4an#four:~/hgtest$ hg status --all
M another_file
C a_file
That said, don't use --force with hg remove or ever really. Also try to get in the habit of using hg forget instead of hg remove --after,
there are two options using hg revert :
hg revert -a
which will go back to the previous revision and put all your changes in new files with .orig appended to the names
hg revert [names of files to unremove] to just revert those files
i'd probably go with the latter
hg revert
I'm pretty sure Mercurial even makes backups of your changes by default.
If the file exists, (likely if you've marked it for removal with hg forget or if you've modified it then hg removed it), do hg add [file] to add it back with any changes made after the last commit and before forgetting the file.
If the file does not exist (likely if the file was unmodified and you've marked the file for removal using hg remove), do hg revert [file] to revert it back to its state in the parent of the working directory.
I had the exact same problem. hg add is the inverse to hg forget (just as the opposite is true). However, attempting to re-add the directory itself did not work. Instead, I had to use hg add on each file:
hg st | egrep "^R" | sed -e "s/R //" | xargs hg add
Hope that helps. Note that in my case, there was nothing I legitimately wanted to remove. If you have files you definitely want to remove, adjust the grep accordingly.
Following your comment to jk, I checked hg forget. It seems to be just a shortcut for hg remove -Af, meaning that this is the real opposite of hg add.
Following that, if you've used hg remove -Af, then you should be able to revert that using hg add (I just tried it and seems to work).
The markers are stored in .hg/dirstate file. All you need to do i to get a one from before issuing hg remove -Af. It may look like this (not tested):
hg clone bad-repo orig-repo
cp orig-repo/.hg/dirstate bad-repo/.hg/dirstate
cd bad-repo
hg status
The last command should show the status from before removing files.
I removed a bunch of unmodified files:
hg remove *
This is what I had to do to get them back:
hg revert --all
Nothing else worked. Not hg add not hg add * nor hg revert *