How to get diff for single changeset? - mercurial

Running hg diff -r XXXX seems to compare that changeset with my local copy. How do I get just the changes for that changeset compared to the one it was built off of, like you would see on BitBucket or GitHub?

hg diff -c XXXX
You can specify -c/--change with a revision to see the changes in that changeset relative to its first parent (source).

Related

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

Diff after committing locally

I just cloned a repo from their remote.
I built the software, changed about 4 files, committed them locally and now want to create a patch that I can show them.
When I run :
hg diff -U8p abc efg pqr > patch_file
I don't see the changes I made. Does hg diff only compare the current files with the last committed files?
How do I get this to work?
To diff the working directory against a particular revision REV, use
hg diff -r REV
To compare two revisions against each other, use
hg diff -r REV1 -r REV2
To figure out which revisions to compare, examine the output of hg log. If you'll be doing this a lot and the base revision is fixed, give it a name (e.g., whatipulled) with
hg tag -r REV whatipulled
You can then specify whatipulled as the revision, instead of a numeric rev id (or a hash).
To export your diffs in a richer format, including commit comments etc., you can also use the following which is designed for this purpose:
hg export -r REV
There's also hg bundle -r REV, which produces a binary file with similar information.
But if you're sending changes back to the parent repo, the best method is to use hg push. It communicates your changesets directly to the parent; you don't even need to know which changesets need pushing. Of course, you must have the right to push to the parent repo.
hg push [ parent_repo_url ]
(If you pulled from it, mercurial should already know the path and you can leave it out).
If the parent repo is on bitbucket and you don't have pu, you can set up your own account on bitbucket, pull/push to that from your local repo, and then issue a "pull request" to the project repo, asking them to pull from you.
All of the above have options to control their behavior, which see.
From hg help diff
If only one revision is specified then that revision is compared to the working directory
In your diff for -r you must to use old tip (latest "not your" changeset) and update to tip (your latest changeset) before diffing.
If some binary data was modified in your changesets, don't forget to use -g option
hg up & hg diff -r <CSET> -g > some.patch
Improved diff for any active changeset and without hand-work for detecting base changeset (for linear history == in single branch)
hg diff -r "parent(min(outgoing()))" -r tip
By default, hg diff compares the currently checked out file with the last commit. You can change this by adding options:
-r REV compares the currently checked out files with a specific revision REV.
-c REV shows the changes made by revision REV
So in your case hg diff -c 123 ... would give you the diff for commit 123.
My guess is that hg outgoing is exactly what you want -- it compares what you've committed locally with what is at the default remote server and shows you a list of those changesets or with -p the commits.
That does, however, shows each changeset separately. If you want to see all the changes combined, you'd have to do hg diff -r HERE -r THERE or since -r HERE is a default, hg diff -r THERE
I see you've asked in a comment "How do I know what THERE is", where THERE is the last changeset remote has, and you can get that answer by doing hg outgoing. If hg outgoing shows it would send changesets 66, 67, and 68, then you want to do hg diff -r 65 to compare what's already there (65) with what's local (68).

Mercurial: Easy way to see changes from last commit

In Mercurial, I can see my current (uncommitted) changes by running
$ hg diff
Fine. But after commit, I sometimes want to see this diff again (i.e., the diff of the last changeset). I know I can achieve this by
$ hg log -l 1
changeset: 1234
tag ...
$ hg diff -c 1234
I'm looking for a way to do this in one line.
Use hg diff -c tip, or hg tip -p (shorter, but works only for tip).
This will work until you pull something, since tip is an alias for the most recent revision to appear in the repo, either by local commit or
pull/push from remote repositories.
You can use relative revision numbers for the --change option:
hg diff -c -1
See https://stackoverflow.com/a/3547662/239247 for more info.
An alternative is to use: hg diff --rev -2:-1
This form has the advantage that it can be used with the status command (e.g. hg st --rev -2:-1), and using it makes it easy to remember what to do when one needs to determine differences between other revision pairs (e.g. hg diff --rev 0:tip).
The answer from Macke is quite helpful, but in my case I didn't want to diff tip.
Thankfully you can also just diff the currently selected comment:
hg diff -c .

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

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.