How do I get the current mercurial revision without calling hg? - mercurial

In Git the current revision hash is stored in
.git/refs/heads/master
Is there an equivalent in Mercurial that doesn't require me making a call to hg log -l1? I know I can get the current branch in .hg/branch.
This is to "display" the current hg hash on screen when browsing a web page.

$ hg parents --template="{node}\n"
52b8cee1e59c91b9147635b7f44a3a8896ee0b00
$ hexdump -n 20 -e '1/1 "%02x"' .hg/dirstate
52b8cee1e59c91b9147635b7f44a3a8896ee0b00
But why can't you just call hg parents --template="{node}\n"?

hg id --debug -i -r .

I'm not a mercurial expert, but taking the sledgehammer approach and doing a grep for the current revision hash in .hg yields only one possible, and that is .hg/branchheads.cache.
I believe this caches all the heads of the repository, so it may have multiple entries. By default, I think it will always have two entries, one for the default branch and one for the tip revision number.
I think that branchheads.cache is rebuilt whenever new changesets arrive, so it should always have the correct current revision hash in it.

Related

How to determine the last Mercurial commit that changed file X?

Given a checkout of a Mercurial repository and a filename. How does one determine the last commit that changed that file? Unlike git, care must be taken with branches. The intended semantic here is to follow the history of the branch. Where branches fork from other branches, follow parent branches.
Non-solutions:
shows commits from unmerged branches
hg log -l 1 filename
empty output if the file remains unchanged after branch creation
hg log -l 1 -b . filename
Arguably, this question highlights misuse of branches and bookmarks should be used instead. However that may be, existing history necessiates taking branches into account.
The -f flag tells hg log to follow history of the current or selected changeset, so this should find the first change of a file without looking at changesets that aren't direct ancestors:
hg log -f -l 1 filename

Mercurial revision checkout is working, but according to the log, the revision is not exist

I have some issue with Mercurial. The checkout of a revision is working (via hg clone -r X command, which clones the X. revision), but when i tried to get log for the X. revision, it returns with revision not exist. How can i solve this problem?
Commands i use:
hg clone -r RevisionNumber /path/to/local/repo my_folder
Then:
hg log -r RevisionNumber --template 'my_template'
hg diff -c RevisionNumber
I get:
abort: unknown revision 'RevisionNumber '!
I tried revisioning with number, and with number:hash, neither worked.
My guess here is that you are referencing the changeset by the revision id (your RevisionNumber) that is local to the original repo. Only the changeset identifying hash is globally unique. I'm basing this guess on your statement
I tried revisioning with number, and with number:hash, neither worked.
You should try using only the hash and see if that works.
hg log -r [hash]
(If you do number:hash, hg thinks your are looking for the range of changes between number and hash.)
Explanation: When you clone to a specific revison, Mercurial only includes changesets that direct ancestors of that revision and leaves out all others. The numbering is locally sequential (meaning new numbers are assigned as the changeset arrives at the repo).

How to detect that commits are pushable

In Git it is easy, because remote/branch is pointing to a different commit than branch. How to do it with Mercurial?
If you mean seeing what's different between your local repo and the one you're pushing to, try
hg outgoing
Since Mercurial 2.1, there is also a purely local solution: phases. The draft phase is probably what you are looking for. For details, refer to:
https://www.mercurial-scm.org/wiki/Phases
You may find hg phase <rev> and hg log -r "draft()" interesting.
There is an remotebranch extension that will give you a Git-like setup. It tracks the remote heads for the repositories listed in the [paths] and exposes them as tags named <path>/<branch>. This lets you run
$ hg diff -r foo/default
to see what has changed since the default branch in the foo repository. There is also new revset keywords that let you do things like
$ hg log -r "not pushed()"
to get what
$ hg outgoing
would do, but without any network traffic.
What's the command line call to show all revisions in the draft phase?
hg log --style phases
That will display the log + the phase, since Mercurial 2.7 (2013-08-01).
I'd just use hg outgoing as others are suggesting, but hg summary will tell you too. It may require the --remote option to have it check the remote default server.
If you need to select the changesets for further processing, then you can use the outgoing revset predicate. This lets you re-implement hg outgoing as
hg log -r "outgoing()"
but the real benefit is that you can use this in other contexts, such as
hg strip "outgoing()"

Using Mercurial, how to diff with a fixed revision if commit intermediate states often?

Using Mercurial, say if I do an hg pull and hg up and now the local repo and working directory are both up to date.
What if I commit often, say 1 day later, and then 2 days later, and want to diff with the revision as of right now?
Otherwise, the diff is always comparing to the previous committed version.
I can use pencil and paper and write down the revision number right now, say, 4117, and then 1 day later, 2 days later, and any time before I am sure and push to the remote central repo, do an
hg vdiff -r 4117
(either using vdiff or diff). But instead of remembering this "magic number" 4117, is there a way to make Mercurial somehow remember this number? That way, hg vdiff is to see the difference between minor changes against committed code, but there is a diff that shows all changes before pushing to the remote repo.
(or, if there is command that shows the revision number since your last pull, which should also show 4117, so on bash we can do something like hg vdiff -r `hg --what-is-last-pull` )
Update: does hg out --patch show the diff of what would be pushed to the remote repo? If so, maybe it serves the purpose without caring the "magic number". But how to show the patch diff using kdiff3 or any other diff tools? Also, it seems we can do hg out and if we see 4118, 4119, 4120, then we know if we do hg vdiff -r ___ we should use (4118 - 1) which is 4117.
Update 2: actually, hg out --patch shows the diff between local repo and the remote repo, so it is close, but not exactly the same as the diff between working directory and the local or remote repo.
If you want to mark a revision you can use bookmarks extensions. It is shipped with mercurial. Documentationis available here
In your case,
hg pull -u
hg bookmarks lastpull
..hack..hack..
hg ci -m new-hack
hg diff -r lastpull:tip
hg bookmarks -d lastpull
Do it with multiple clones. When you clone from the remote repo initially use clone -U to create a clone that has no working directory files at all. Then clone again locally, for example:
$ hg clone my-local-clone-with-no-working-files my-working-clone
Do your commits and work in my-working-clone and then at any time you can check the tip in my-local-clone-with-no-working-files to see what the last thing you pulled from the server was. If you want to get fancy you could create a shell alias for:
hg diff -r $(hg -R $(hg root)/../my-local-clone-with-no-working-files id -i -r tip)
which will compare the working directory of the repo in which you run it (my-working-clone) with the tip of whatever you last pulled from the server.
It's worth nothing that this takes no extra disk space because local clones use hardlinks under the covers the the my-local-clone-with-no-working-files has no working directory files.
You can replace pen and paper with a local tag: hg tag -l -r <revision number on paper> tagname. Notice the -l, which makes the tag local, which means it does not get transferred by push and pull. You can also remove this tag by hg tag -l --remove tagname.

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.