Mercurial - How do I diff with a previous version? - mercurial

I'm using the command
hg kdiff3 filename
to visualize differences between my current status and what's pushed in the master repository.
If I was to see the differences between a specific revision (say 5 commits back) and the current, how would I do it?

To see the changes between two versions of a file in the repository:
hg kdiff3 -r 4 filename
where the current version is assumed to be the "other" changeset. If you want to compare two past revisions:
hg log filename
hg kdiff3 -r2 -r7 filename
where the revision numbers -r2 -r7 are drawn from the changeset log.

Related

How to get commits since a commit in mercurial?

I'm frequently reviewing our commits since we last merged our dev branch to default (ie, we released a version) and so I want to list the commits since that merge in mercurial. Right now, I am using the date and am using log + grep and a date.
ex:
hg log -r "date('>2017-03-02')"
Is there a way to do this from a commit? Or should I just keep grabbing the date/datetime off the commit for the merge to default and doing what I'm doing?
All revisions in a branch starting with changeset XXX:
hg log -rXXX::
All revision in the whole repo starting with changeset XXX:
hg log -rXXX:
It's even mentioned on the first page of hg help revsets:
- Changesets between tags 1.3 and 1.5 mentioning "bug" that affect
"hgext/*":
hg log -r "1.3::1.5 and keyword(bug) and file('hgext/*')"

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

View a changeset using mercurial

How do I view a changeset of a mercurial repository.
I want to get the same output I get with
git show <commit>
How do I do this with hg?
The git show command for commits shows log message and diff. The equivalent Mercurial command could be:
hg log -p -r <REV>
Remember that in Mercurial can refer to a local revision number, changeset, tag, a rangeset of revision numbers ... see the manual page for details and more options.

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

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.