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

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.

Related

Mercurial, check if a particular version of a file has existed in the history before?

To somewhat elaborate on the title question, is there a way to have Mercurial search through the repository history for a particular version of a given file, and show all of the revisions (or just the most recent one) that contain that version?
For example, let's say that the current working revision is, say, 300 and a file was reverted to an earlier version (say, revision 200). I don't know this - all I can easily see is "how different" the new file is from the 300 version. How can I find out all of the possible revisions that it could have been reverted to?
And if Mercurial cannot do this natively, is there another tool that can? (TortoiseHG?)
I don't think this is possible with any of hg's built-in functionality, but you can get something like it with judicious xargs and md5sum application:
hg log --template "{rev}\\n" | xargs -I "{}" /bin/bash -c 'echo $(hg cat -r {} <filename> | md5sum) {}'
This will give you a list of md5 checksums with the revision number, which when you sort it will give you the revisions sharing versions of the file.

Customising hg log output

(Mercurial newbie)
I'm trying to get hg log to give me the full changeset description, but without the file listing given by the -v option. Basically, I want the default output but with the full description rather than just the first line.
I've played about with templates, but can't see a way to do what seems like it should be a very simple change. Am I missing a built-in solution?
hg log --template ... or ... --style ...
with hand-made template or style.
Just write it
PS: Hint - use {desc} keyword
I don't think what you want is built in, but the log is formatted so:
Powershell:
hg log -v | where {$_ -notmatch "files:"}
*Nix:
hg log -v | grep -v "files:"
achieves what you want I think.

Is there a way to see the most recent Mercurial revision for each file in a directory?

When you do hg log on a file, only the revisions that underwent changes are listed. I'd like to see what the most recent revision for all of the files in a directory is. (Think hg blame at a file level rather than a line level.)
I had thought that hg log -l 1 * might work, but it just shows the most recent revision across all of the files.
Here's the kind of output I'd like to see:
> hg blame --files
foo: 15
bar: 2
baz: 15
README: 1
Another alternative is to use a combination of hg status and hg log, like this:
for FILE in $(hg status -nA); do
hg log -l1 --template '{rev}\t' "$FILE"
echo $FILE
done
I suspect that if you want to use hg directly to do this, you'll need to write an extension (but I'm by no means an expert here). But would something like this work, if you're willing to use a script?
for x in *; do
highest=`hg blame "$x" 2>/dev/null | cut -d : -f 1 | sort -nr | head -n1`
if [ "$highest" ]; then echo "$x: $highest" ; fi
done
The obvious downside here is that this is pretty slow.

How to list commiters sorted by number of commits (commit count)?

In mercurial, how do you list commiters sorted by number of commits (commit count).
Using git, you can do something like this :
git shortlog -ns
What is the equivalent command for mercurial ?
There is no pure Mercurial solution, but you can do something like:
hg log --template "{author|person}\n" | sort | uniq -c | sort -nr
If you want to be able to type hg shortlog, you can add the following to your .hgrc or mercurial.ini:
[alias]
shortlog = !hg log --template "{author|person}\n" | sort | uniq -c | sort -nr
The churn extension can draw you a nice histogram with the information. Add
[extensions]
churn =
to your Mercurial configuration file and run
$ hg churn -c
to get a histogram like this:
mpm#selenic.com 3234 *************************
thomas#intevation.de 974 ********
pmezard#gmail.com 939 *******
That historgram is from the Mercurial repository itself.
I've made a script for Roundup to build list of project contributors by years based on Mercurial history. It is cross-platform, public domain and should be easy to customize for your own purpose.

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.