how to quickly tell which files differ in mercurial revisions - mercurial

This seems like it should be obvious but I can't figure it out.
Suppose I have mercurial revisions 4 and 7 and I want to see which files changed between those revisions. I can do a hg diff -r 4 -r 7 to list the entire set of diffs... is there a way to just list the files that have changed?

hg status --rev 4:7

You can use "hg log" for this.
hg log --verbose --rev=4:7 --style=changelog
Example:
$ hg log -v -r4:7 --style=changelog
2008-08-03 21:40 +0200 XXXXX <XXXXXX.YYYY#xxxxxxxx.com> (475752c35880)
* osinfo.py: new file.
* os-info.py: deleted file.
* os-info.py, osinfo.py:
Rename os-info.py -> osinfo.py.
2008-08-03 21:52 +0200 XXXXXX <XXXXXX.YYYY#xxxxxxxx.com> (babf6df75ff4)
* iterate_file_lines.py, osinfo.py:
Add keyword substitution strings.
2008-08-03 21:53 +0200 XXXXXX <XXXXXX.YYYY#xxxxxxxx.com> (bc6fc22adb8e)
* iterate_file_lines.py:
Remove comment about coding conventions.
2008-08-08 19:43 +0200 XXXXXX <XXXXXX.YYYY#xxxxxxxx.com> (dbea6914b20f)
* .hgignore: new file.
* .hgignore:
Add .hgignore.

Related

How to create patches for all changes to a file in a branch

A number of changes have been made to a file in a branch. Some of the changes were for a feature that now needs to be implemented on the main branch.
How can I create a patch for each revision of the file so that I can choose which changes I wish to apply to my main branch? Ideally I would like each patch to contain the description of the revision too for reference purposes.
You can get a log for just one file by quoting that file in the log command:
hg log FILENAME
and you can get the diff for a certain revision and filename by giving both as argument to log, asking it to give you the patch (I've configured my hg to use the git-style patch format by default - maybe that's needed here, too):
hg log --patch --rev XXX FILENAME
if you want a patch for each revision FILENAME was changed, you could try in bash something like
for rev in $(hg log -T"{rev}\n" FILENAME); do hg log -p -r${rev} FILENAME > FILENAME.${rev}.patch; done
which yields you the typical patches, including the commit message used:
$ cat FILENAME.15.patch
Änderung: 15:441bead3e0b3
Vorgänger: 7:36479da8f266
Nutzer: planetmaker <email#example.org>
Datum: Tue Feb 10 22:58:24 2015 +0100
Zusammenfassung: More boo
diff --git a/FILENAME b/FILENAME
--- a/FILENAME
+++ b/FILENAME
## -1,1 +1,2 ##
foo is boo!
+Even moar booo!

Mercurial: Identify file name after rename

Mercurial tracks the contents of a file throughout renames (hg mv $OLD $NEW), so that hg annotate $NEW also shows up the line-wise changes formerly made to $OLD with their original identification. That works fine.
BUT there seems no straightforward way to find out the name of the $OLD file, to which some given line has belonged within the ancestry of $NEW. hg annot $NEW -r$REV only works down to the rename changeset.
Of course the information is somehow accessible, e. g. by crawling through hg log (without --follow) and identifying the renames with some hg log -r$RENAMEREV -g -p (or by clicking through hg serve's web interface).
But this “workflow” is not only annoying and error-prone, but [most importantly] it isn't non-interactive/scriptable.
My question: Is there a way to get/construct either
some list of the file name history of $NEW (best with respective revision ranges), or
the name of the file in which line $LINE was commited (some kind of filename option for hg annot)?
Ideas in either the hg CLI or Python/hglib appreciated.
Either include the {file_copies} keyword in your hg log template:
$ hg init demo
$ cd demo
$ touch a
$ hg ci -Am 'file a'
adding a
$ hg mv a b
$ hg ci -Am 'moved to file b'
$ hg log -r . -T"{file_copies}\n"
b (a)
The built-in template status will include file copy info when you set the --copies flag:
$ hg log -r 1 -Tstatus --copies
changeset: 1:b37952faaddc
tag: tip
user: Martijn Pieters <mjpieters#fb.com>
date: Sun Jul 31 16:07:04 2016 +0100
summary: moved to file b
files:
A b
a
R a
So file b was taken from a.
See hg help template for more things you can include in log output.

Recover lost files after commit and rollback in Mercurial. (Equivalent of git reflog?)

Commited work. Did a rollback when I wasn't on the tip of the repo. Lost files. Looking for git reflog equivalent to save my work.
Long:
So I finish work, then commit.
$ hg commit -A
[...]
adding media/js/fbfriends.js
removing media/js/streams.js
adding media/js/templetizer.js
[...]
$ hg log
$ hg log
changeset: 10:ce3ad416d9a5
tag: tip
user: Mihai
date: Sat Sep 10 22:34:35 2011 -0700
summary: Save all.
changeset: 9:ceacb7b2192a
user: Mihai
date: Sat Sep 10 22:25:34 2011 -0700
summary: Mootools update.
[...]
Some browsing:
$ hg checkout 8
Okay. Then I wanted to change revision 10. Stupidly, I do:
$ hg rollback
rolling back to revision 9 (undo commit)
$ hg status
[...]
M media/js/mootools.js
R media/js/streams.js
! media/js/fbfriends.js
! media/js/templetizer.js
[...]
WTF? Where did my two files go????
$ hg log
changeset: 9:ceacb7b2192a
tag: tip
user: Mihai
date: Sat Sep 10 22:25:34 2011 -0700
summary: Mootools update.
[...]
Okay, i'll figure out the .orig files:
$ hg revert --all
[...]
undeleting media/js/streams.js
forgetting media/js/templetizer.js
reverting media/js/mootools.js
[...] // media/js/fbfriends.js doesn't even show up
$ hg status
? media/js/mootools.js.orig
$ hg history
changeset: 9:ceacb7b2192a
tag: tip
user: Mihai
date: Sat Sep 10 22:25:34 2011 -0700
summary: Mootools update.
NOOOOOO! I've been royally fscked for being on commit 8 when i did the rollback.
Recovery attempts fail:
$ hg checkout 10
8 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ find -name temp
$ hg checkout 9
30 files updated, 0 files merged, 63 files removed, 0 files unresolved
$ find -name temp
$ hg checkout ce3ad416d9a5
abort: unknown revision 'ce3ad416d9a5'!
$ hg checkout ceacb7b2192a
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ find -name temp
$
But, but.. I pushed it in! It should still be somewhere in .hg? Help?
git reflog, git checkout blah saved me in a couple instances but are there any mercurial equivalents?
EDIT: Made summary clear.
EDIT2: Better title.
Sorry, they are gone.
The help summary for the rollback command is:
roll back the last transaction (dangerous)
and goes on to say:
This command should be used with care. There is only one level of
rollback, and there is no way to undo a rollback. It will also restore the
dirstate at the time of the last transaction, losing any dirstate changes
since that time. This command does not alter the working directory.
Rollback is the only non-extension mercurial command that removes history, and there's been talk about moving it to a disabled-by-default extension like it's similarly destructive cousins strip and purge.
Not that it helps you now, but in the future clone before doing a rollback. Or better yet do a backout instead. Backout adds the inverse of a change, yielding the same resulting tip revision, but with a more accurate history ("I did this", "I undid it").

Change format of hg log -v

When we do hg log -v we see:
changeset: 2639:283fb2da345f
parent: 2638:e06cb712d37b
parent: 2631:d8f619046812
user: joe#pub.com
date: Wed Apr 13 12:29:57 2011 -0400
files: core/src/main/java/com/blah/boards/InvalidRateException.java core/src/main/java/com/blah/boards/InvalidException.java core/src/main/java/com/blah/area/xxx/instructions/AssignInstruction.java core/src/main/java/com/blah/area/xxx/instructions/AutoAssignInstruction.java core/src/main/java/com/blah/area/xxx/instructions/AutoDeliveryInstruction.java
description:
Commiting after merge
Is there a way to output the file in a more readable manner? Something like:
files:
core/src/main/java/com/blah/boards/InvalidRateException.java
core/src/main/java/com/blah/boards/InvalidException.java
core/src/main/java/com/blah/area/xxx/instructions/AssignInstruction.java
core/src/main/java/com/blah/area/xxx/instructions/AutoAssignInstruction.java
core/src/main/java/com/blah/area/xxx/instructions/AutoDeliveryInstruction.java
You can specify your own template via --template option. See hg help templates. You could try e.g.
hg log --template "(...) files:\n{files|stringify|fill76}\n"
If you want just the files list for a single revision you can use hg status --change 2639 which shows the file list prefixed with M, A, R, D prefixed, which you can omit by adding the --no-status flag.
This question is quite old, but anyway, here goes a solution:
hg log -v --template "{files % '{file}\n'}"
Worth checking this: http://www.selenic.com/mercurial/hg.1.html#template-usage

Mercurial keywords extension to expand on every commit

I need to use the hg keyword extension to embed the build date and revision into a source file. Leaving aside the whole "you really don't want to be doing that" argument, how can I do this?
Here's what my source file (lib/foo/version.rb) looks like (which happens to be Ruby, but that's only relevant from the point of view that I don't have a "compile" step in my build which I could do a -DREVISION="$(hg id)" in):
module Foo
VERSION = {
:date => "$Date$",
:changeset => "$Revision$"
}
end
The problem is that $Revision$ and $Date$ are expanded with the changeset and commit date of that file, whereas what I need is the tip changeset and commit date of the whole repository.
I don't see an obvious template I can use in hg help templates, nor does the keyword extension mention anything with global scope. Is what I'm trying to do possible?
You can install a post-commit hook that updates the file:
[hooks]
post-commit = sed -i lib/foo/version.rb \
-e "s|\$Date.*\$|\$Date: $(date)\$|" \
-e "s|\$Version.*\$|\$Version: $(hg id -i)\$|"
You should then probably add the version file to the .hgignore file -- it will change after every commit and thus always be dirty. You could also add a encode filter that will clean up the version file:
[encode]
lib/foo/version.rb = sed -e "s|\$Date.*\$|\$Date\$|" \
-e "s|\$Version.*\$|\$Version\$|"
This script will make Mercurial see the file as clean -- no matter what date and changeset has it really contains, Mercurial will see it as containing un-expanded $Date$ and $Version$ keywords:
$ hg commit -m test
$ hg tip
changeset: 7:df81c9ddc9ad
tag: tip
user: Martin Geisler
date: Wed Apr 06 14:39:26 2011 +0200
summary: test
$ hg status
$ hg cat version.py
date = "$Date$"
version = "$Version$"
$ cat version.py
date = "$Date: Wed Apr 6 14:39:26 CEST 2011$"
version = "$Version: df81c9ddc9ad$"
If you're running your code from a checkout you can invoke hg directly and cache the value. Something like:
module Foo
VERSION = {
:version => system("hg log --template '{note|short}-{latesttag}-{latesttagdistance}' -r .")
}
end
and if you're not running the code from inside a checkout on a system with Mercurial installed, then your deploy script can easily get/use the value -- perhaps by using hg archive to get the tarball to send which then automatically includes a .hg_archive.txt.
I guarantee you there's a prettier way to do this than the keywords extension no matter what your setup is.