Mercurial built-in template style description - mercurial

I am trying to tune the output of hg log by defining my own style. In fact, just adding information to the default style would be perfect. Is there a place where I can get the description of the default styles (default, compact, ...) to write my own?

After some research, I finally found the location of the default styles for hg log, located on my ubuntu 14.04 at
/usr/share/mercurial/templates/
You can find there the following files:
map-cmdline.bisect
map-cmdline.changelog
map-cmdline.compact
map-cmdline.default
map-cmdline.phases
map-cmdline.xml
They do not contain any color scheme, but they are allowed me to build my 'patched' version of default.

From other comments elsewhere you can find out where the styles location is by:
hg debuginstall --config ui.editor=cat
Or using a bug if you choose a directory under the template it complains and tells you where they are (probably should for non matching styles), well it does for 1.9.2:
hg in --style paper
If you want to colour the output you could use the color extension now.
add to .hgrc:
[extensions]
color=

If you know how to use the various keywords that Mercurial templating feature understands (see hg help templating for a very complete usage doc), then you can either:
specify your choices by giving a template on the command line, e.g.,
$ hg tip --template "{rev} at {date|isodate}"\n
882 at 2014-12-17 08:50 +0100
or edit an ascii file with the same format and use it with the style option, e.g.,
$ cat ~/mystyle.txt
changeset = "{rev} at {date|isodate}\n"
$ hg tip --style ~/mystyle.txt
882 at 2014-12-17 08:50 +0100

It's strange, but the default templates are hardcoded in mercurial code.
The file map-cmdline.default is never read at runtime, but can be used to exactly replicate mercurial output (and thus to extend it).
Example of how to extend hg log output to include the git commit hash of a git repository cloned via hg-git.
Look for the location of map-cmdline.default:
$ hg debuginstall --config ui.editor=cat | grep "default template"
checking default template (/usr/lib/python2.7/dist-packages/mercurial/templates/map-cmdline.default)
Edit /etc/mercurial/hgrc, pasting a slightly modified version of map-cmdline.default:
...first part of your hgrc...
[templates]
# support "git-commit" line in hg log
changeset_git = '{cset}{cset_git}{branches}{bookmarks}{tags}{parents}{user}{ldate}{ltroubles}{lobsfate}{summary}\n'
cset_git = '{if(gitnode, "git-commit: {label("status.unknown", gitnode|short)}\n")}'
...the rest of 'templates' section of map-cmdline.default...
[templatealias]
...the whole 'templatealias' section of map-cmdline.default...
Example output:
~/git$ hg log --graph
# changeset: 54881:d420062ce3d6
|\ git-commit: 6326d2e53311 <-- new line, only appears in git clones
| | tag: default/pu
| | tag: tip
| | parent: 54879:31a4c8ccc461
| | parent: 54880:691b9814f119
| | user: Junio C Hamano <gitster#pobox.com>
| | date: Sun Mar 25 10:52:08 2018 -0700
| | summary: Merge branch 'jh/partial-clone' into pu

Related

Undoing accidental hg amend on top of Mercurial queue

The following sequence of commands requires that the Mercurial Queues exension be enabled, and also the Evolve extension (for hg amend, alias hg refresh).
This combination of commands messes up the existing Mercurial queue, making the commit corresponding to the pushed patch obsolete, and creating a new commit with exactly the same contents.
This error is in theory quite easy to make: just type hg ref instead of hg qref, but I just made it recently after using Mercurial Queues for years. Regardless, I haven't figured out a clean way to fix this and get back the original state.
Note that a simple hg rollback does work in my example, but I'm not sure it will work in my case, because I've tried other things trying to fix this. In any case, hg rollback isn't something one should rely on.
In summary, how do I undo the hg amend and get back my applied MQ patch?
#!/bin/sh
hg init test
cd test
echo "This is foo" >> foo
hg add
hg ci -m "Add foo"
hg init --mq
echo "Line 2 of foo" >> foo
hg qnew p
hg ci --mq -m "Add patch p"
hg ref
hg log -vG --hidden
# changeset: 2:f7f038d3aab5
| tag: tip
| parent: 0:9d3a95922194
| user: Faheem Mitha <faheem#faheem.info>
| date: Sun Mar 11 16:38:51 2018 +0530
| files: foo
| description:
| [mq]: p
|
|
| x changeset: 1:e467a2433c7f
|/ tag: p
| tag: qbase
| tag: qtip
| user: Faheem Mitha <faheem#faheem.info>
| date: Sun Mar 11 16:38:50 2018 +0530
| obsolete: rewritten using amend as 2:f7f038d3aab5 by Faheem Mitha <faheem#faheem.info> (at 2018-03-11 16:38 +0530)
| obsolete: rewritten by Faheem Mitha <faheem#faheem.info> as f7f038d3aab5 (at 2018-03-11 16:38 +0530)
| files: foo
| description:
| [mq]: p
|
|
o changeset: 0:9d3a95922194
tag: qparent
user: Faheem Mitha <faheem#faheem.info>
date: Sun Mar 11 16:38:50 2018 +0530
files: foo
description:
Add foo
That's not what I get with your test case. I need an additional
echo "Line 3" >> foo
before the hg ref. Also, versioning your mq seems irrelevant here; I think you can remove the hg init --mq and hg ci --mq lines.
hg amend really ought to block that. But if you wanted to manually fix things up, edit .hg/patches/series and replace the obsolete hash with the successor's hash. (Just make sure to use the 20-byte hash, as is given by eg hg log -T '{node}\n').
Warning: when I tried that with your test case and qpopped, something mysteriously un-obsoleted the old head, and it gives a strange warning about the current directory not being a head (despite hg log -r 'head()' listing it.) But at least you have your queue back in a working state.

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!

How can I find frequently changing files in a Mercurial repository?

I'm jumping into a new code base with the intention of making it more stable. What I am struggling to determine though is where most of the turbulence is in the code.
I'm looking for a way that I can find which files within the repository are most frequently being changed so that I can come up with a starting point for some refactoring. It doesn't appear that there is a built-in Mercurial command for this, and Google doesn't seem to have much to offer either (or I'm using the wrong terms.)
At the moment all that comes to mind would be to write a script that would parse the 'files:' line from the hg log -v command and count the files manually. This will work, but I'd be awfully surprised if I'm the first person that has had to do this.
This will do it:
hg log --template "{files % '{file}\n'}" | sort | uniq -c | sort -rn
21 templates/base.html
19 TODO
8 content/about.rst
6 static/screen.css
That shows 21 chngesets touch templates/base.html, the most of my tiny repo.
I'll suggest to move by opposite way
Get list of files
For every file from p.1 execute something like hg log FILENAME --template "+" | wc -m
Here's a version that works with older Mercurial installs:
$ hg grep --files-with-matches --all . | cut -d : -f 1 | sort | uniq -c | sort -rn
21 templates/base.html
19 TODO
8 content/about.rst
6 static/screen.css
If you have colons in your filename you'll need to add --print0 and change the cut invocation too.

In Mercurial (Hg), what is a good way to list all files modified by me since revision 4822?

I may do development work for 2 weeks before one or two features get pushed to all the production servers, and since this is a Ruby on Rails project, many files can be modified.
So using Mercurial as the source control, is there a good way to list all filenames that are modified (or added) by me, between the current version and revision 4822? (the number 4822 is before I do the first hg push, I do an hg out and see that the changeset that will go out is 4823, so I will diff with 4822)
(Update: This is to list files only modified by me, as opposed to the other 38 files modified by my teammates)
Better yet, is there a good way to invoke hg vdiff automatically, so when invoked as
checkdiff Peter 4822
It will do
hg vdiff -r 4822 [... the list of filenames modified by Peter (or me) since 4822]
Maybe use hg log and some nice one-liner?
hg log --user Peter --verbose | grep files | sed -e 's/files://' | tr ' ' '\n' | sort | uniq will give all files modified by you since beginning of repository. Use --rev to limit revision scope.

Mercurial undo merge that has more commits following it?

Have a scenario where we un-intentionally merged a named branch (ABC) into our default branch.
hg rollback is not an option because there have been a couple commits since.
Is there a way to undo this?
You're going to need the Mq extension. If you don't have it turned on, do so by adding this to your Mercurial.ini or .hgrc file.
[extensions]
hgext.mq=
If you're not familiar with it, the Mq extension let's you manipulate history. The good news is, this will allow us to fix your repo. The bad news is that anyone who has a clone of the messed up repo will have to clone it again, because we'll be changing history.
First, go make another clone of your repo to work in, so we don't mess anything up.
Now, find the revision id of the merge changeset (that merged default and your named branch). Write it down. We'll refer to it as changesetM. Now find the revision id of the next changeset. Write it down. We'll refer to it as changesetN.
Once you have those two revision ids, head over to your command prompt and cd into your repo. Then type out the following, replacing changeset[M|N] with the appropriate revision id.:
$ hg qimport -r changesetN:tip
# This will add all of your changes since the merge to the queue
$ hg qpop -a
# This pops them all out of your history.
$ hg strip changesetM
# This removes the merge changeset.
$ hg update -C default
# Make sure we're on the default branch
$ hg qpush -a
# Take the changesets in the queue and push them back onto your history.
$ hg qfinish -a
# Remove changesets from the queue and finalize them as normal changesets.
Essentially, you are rebasing the new changesets on top of the default branch, removing the merge changeset in the process. Once you're done, you'll need to push the changes to a new repository on the server, and have your colleagues clone fresh copies.
Lastly, if you have any other Mercurial questions, also check out kiln.stackexchange.com.
UPDATE
I forgot to mention: If someone has based changes on something that was only in the other branch, it is possible that hg qpush -a will fail. You'll see a foo.txt.rej and foo.txt.orig file laying around. Unfortunately, you'll have to fix this yourself. To fix it, open the original file, the .orig file, and the .rej file and choose the right changes to merge in, saving them in the original file. Once you've merged it in, use hg qrefresh to update that patch to the new, merged patch. From their, you should be able to run hg qpush -a again and continue. If you run into the same error again on another patch, just follow the same process.
If you haven't publish the repo publicly you can do this
hg clone -r (parent1 of bad merge) -r (parent2 of bad merge) old new
and delete the old repo.
I came across the following scenario today:
# changeset: 1728:5d703e1051d3
|\ parent: 1727:1a5f73b5edb4
| | parent: 1720:65ddd0bde225
| | user: nn
| | date: Wed Feb 27 10:35:00 2013 +0100
| | summary: Merge with SomeBranch
| |
| o changeset: 1727:1a5f73b5edb4
| | user: nn
| | date: Wed Feb 27 10:34:30 2013 +0100
| | summary: lorem ipsum
| |
[some more changesets]
| |
o | changeset: 1720:65ddd0bde225
| | branch: SomeBranch
| | user: nn
| | date: Wed Feb 27 07:44:46 2013 +0100
| | summary: lorem ipsum
Where SomeBranch should not have been merged into default. What we did to solve this, was to use the backout command with the parent option like so:
hg backout --rev=1728 --parent=1727
By this you don't undo the merge itself: Looking at a branch graph (either with graph log or in TortoiseHg) you'll still see SomeBranch going into default at r1728. The result of the merge is however undone, meaning that the changeset containing the backout (r1729 in my case) is identical to r1727.