I would like to get a summary of commits with the following information
Number of days worked, start day & end day.
Activity summary by day - just number of commits & number of lines changed.
Is there an extension which does this ?
hg help log + hg help diff + hg help revsets + hg help templating hg help dates + bash
Date of first commit|last commit
Initial commit always has rev 0, latest is always tip
hg log -r 0 --template "{date|date}\n"
hg log -r tip --template "{date|date}\n"
Number of days worked: number of days with non-zero number of commits
hg log --template "{date(date,'%d%m%y')}\n" | sort -u | wc -l
Activity summary by day - just number of commits
hg log -r "date('YYYY-MM-DD')" --template "{.}\n" | wc -l
number of lines changed (first ugly draft iteration: "feci quod potui, faciant meliora potentes")
hg diff --stat -r "first(date('YYYY-MM-DD'))" -r "last(date('YYYY-MM-DD'))"
Sample output of such diff
404.php | 4 +-
comments.php | 14 +-----
footer.php | 2 +-
functions.php | 24 +++++++++-
header.php | 2 +-
readme.txt | 38 +++++++++++++++++
screenshot.png | Bin
search.php | 12 +++-
sidebar.php | 45 ++------------------
style.css | 121 +++++++++++++++++++++++++++----------------------------
10 files changed, 139 insertions(+), 123 deletions(-)
Note: YYYY-MM-DD is placeholder, you have to write real datein this format into command
Note 2: Less than hour for preparing and testing results!!!
LazyBadger's answer gives you a way to find out the dates of first and last commits. For a breakdown of number of daily changesets committed and lines of code changed, enable the churn extension that ships with Mercurial. In either global or repository config:
[extensions]
churn=
Then for a breakdown of number of changesets by day, in chronological order:
$ hg churn --template "{date|shortdate}" --sort --changesets
or for lines of code:
$ hg churn --template "{date|shortdate}" --sort
with optional diffstat to show added/removed lines separately:
$ hg churn --template "{date|shortdate}" --sort --diffstat
Check hg help churn for more options, like limiting range of dates or changesets considered.
Related
I created some branch (call it brnch) from default and made some commits there. Now there is a need to cherry-pick all diffs from the branch to some release branch for hotfix. Is something like that possible in mercurial?
^ ^
| |<--- brnch
| - commit3
| |
| - commit2
- |
| |
| - commit1
- |
| |
| |
|--
|
-
default
Is it possible to create a patch from all commmits in the branch brnch (commit1, commit2, commit3) and apply to some another branch (release hot-fix in my case)?
See hg help export and hg help import.
Examples:
hg export branch(brnch) -o brnch.patch # export everything on brnch
hg export -r commit1 -r commit2 -o cherrypick.patch # cherrypick two changesets
hg update <somewhere_else>
hg import brnch.patch # import the revisions in the patch
hg import --no-commit brnch.patch # import (but don't commit) revisions.
hg commit -m hotfix # commit changes as one commit with "hotfix" description.
You can simply achieve that by means of hg rebase.
For simplicity I will assume that you want to see everything from commit1 onward in your brnch see put into your release branch. Thus checkout the release branch and then rebase your brnch commits:
hg update release
hg rebase --source commit1 --collapse --keep --dest . --message "bla bla something fixed"
Alternatively you can give a revision range. If the commits you want to see collapsed are non-linear in the brnch branch, then you will need to resort to graft (which is cherry-picking individual commits) - and you can collapse (hg fold) all grafted changesets subsequently in your release branch, provided you keep them initially in phase draft.
Is there a way to clone a part of a mercurial repo (i.e. clone -r xxx), but keep all changesets prior to the specified revision i.e. not just the ancestors?
For example, given a repo that looks like this:
-- 2 (branch default) -- 5 -- 8 (merge) -- 9 (merge) --
/ / /
0 -- 1 -- 3 (branch foo) ------ 6 -- /
\ /
-- 4 (branch bar) ------ 7 -------------
I would like to clone only the commits prior to the merge, i.e. so the resulting repo looks something like this:
-- 2 (branch default) -- 5
/
0 -- 1 -- 3 (branch foo) ------ 6
\
-- 4 (branch bar) ------ 7
but running
hg clone -r 7 repo repo2
will only give me commits 1, 4, and 7 (branch bar). It appears the only way to get what I'm after is something like this:
hg clone -r 5 repo repo2
cd repo2
hg pull -r 6
hg pull -r 7
Is that correct, or does someone know of a quicker way to do this?
You have to read hg help clone and remember options, which can be used more than once in one clone (-r and -b namely).
You want, in plain words "clone all in default to 5 inclusive and FOO branch and BAR branch"
Translate it into clone
hg clone -r 5 -b foo -b bar <SRC REPO> <DST-REPO>
hg help clone says
-r --rev REV [+] include the specified changeset
This is different than hg help log, for example, which says
-r --rev REV [+] show the specified revision or range
The best you'll be able to do is use -r more than once:
hg clone -r 5 -r 6 -r 7 repo repo2
You can use log and revision sets to determine which other revisions you need to include.
If I use log -k it pulls up two changesets, but when I add --follow or -f it misses one of them. Why would that be?
(I'd thought that --follow could only add changesets to the set returned, i.e., the ones that had modified selected files before their names were changed to the current names.)
The -f option only follows the history through ancestors/descendents of the starting revision.
My guess is that -k (the keyword search) is returning results from two branches in your repo. Therefore, by adding -f / --follow, you are restricting the results to the changesets that are directly related to the starting revision.
I'm back here because I finally get (mostly) what --follow keeps and what it drops. Although Edward was basically right, I was confused after testing out his answer because I'd misunderstood what was meant by "starting revision," and also there are some nuances about the way it follows ancestors/descendants that led to results that didn't fit what I expected.
Here's a repository with a simple branch:
% hg glog --template {rev}
# 2
|
| o 1
|/
o 0
% hg glog --template {rev} -r '0+1+2'
# 2
|
| o 1
|/
o 0
% hg glog --template {rev} -r '1+2+0'
# 2
|
| o 1
|/
o 0
The next examples using --follow illustrate that the "starting revision" that's relevant to --follow is the first one in the specification (not the earliest in the repository or anything like that), and that even the subsequent ordering matters.
Everything is included if we start with the shared ancestor.
% hg glog --template {rev} -r '0+1+2' --follow
# 2
|
| o 1
|/
o 0
If we don't, then the results even depend on the order of later ones. It looks like it can traverse across the graph, but only in one direction (to ancestors or to descendants, but not both in the same call.)
% hg glog --template {rev} -r '1+2+0' --follow
o 1
|
% hg glog --template {rev} -r '1+0+2' --follow
o 1
|
o 0
And it's not just an issue if you're ordering manually. Using the basic primitives, you can wind up with the revisions in different orders, leading to confusing behaviors.
% hg log --template {rev} -r 'all()'
012
% hg log --template {rev} -r 'all()' --follow
012
% hg log --template {rev} -r 'reverse(all())'
210
% hg log --template {rev} -r 'reverse(all())' --follow
20
I still don't have a clear and concise specification in mind for what it does, and I think it's tricky to generate revsets that are "safe" for follow. (Could hg give a warning message when changesets are dropped from the results for this reason?) So when I'm doing tricky processing that depends on --follow, I run without --follow too, comparing to make sure I'm not losing anything.
I think that your expectation is valid, and I have found --follow to be a bit buggy, when combined with other options.
See these confirmed (and somewhat old) bugs:
https://bz.mercurial-scm.org/show_bug.cgi?id=4959 [Marked FIXED as of Jan 2018]
https://bz.mercurial-scm.org/show_bug.cgi?id=5053
For me, a workaround was to use the --rev "follow('my/filename')" revset syntax, rather than the problematic --follow flag.
Maybe give that a shot?
I switched to a branch on my local repo and noticed it gave me message showing x files updated. This surprised me as I didn't know there were any differences on that branch. How do I compare that branch with the default branch to see what has changed?
Use hg diff -r BRANCH1:BRANCH2, where BRANCH1 and BRANCH2 are the names of the branches. This will show you the differences between the heads of the two branches.
You got the message about "x files updated" because there were files changed on the original branch, not necessarily because there were files changed on the other branch. Mercurial shows you the union of the sets of changed files from both branches.
To just list the files with differences, add the --stat option:
hg diff --stat -r BRANCH1:BRANCH2
This gives output like this:
mypath/file1.cpp | 1 -
mypath/file2.cpp | 143 ++++++++++
mypath/file3.cpp | 18 +-
3 files changed, 160 insertions(+), 2 deletions(-)
Or to clean up the output a bit, pipe it through sed to remove everything after the pipe symbols:
hg diff --stat -r BRANCH1:BRANCH2 | sed "s/|.*$//g"
This gives you just a list of the changed files and the summary line at the end:
mypath/file1.cpp
mypath/file2.cpp
mypath/file3.cpp
3 files changed, 160 insertions(+), 2 deletions(-)
To view a diff of branch otherbranch with the current branch:
hg diff -r otherbranch
So there was a new branch created where we made some breaking changes to the codebase.
Now we are going to merge, but before that I want to get a list of all the files that were changed in the branch.
How can I get a list of files? I tried:
hg status --change REV
But i'm not sure if that is what I want, since I want all files changed in this branch and not a specific revision in the branch.
BTW, how can I view the revision numbers?
Try with
$ hg status --rev "branch('your-branch')"
to get the changes between the first and the last changeset on the branch (hg status will implicitly use min(branch('your-branch')) and max(branch('your-branch')) when you give it a range of revisions like this).
Since you'll be merging, you should really look at
$ hg status --rev default:your-branch
to see what is changed between the default branch and your-branch. This shows you the modifications done, and filters out any modifications done on the branch due to merges with default.
This is necessary in case your history looks like this:
your-branch: x --- o --- o --- o --- o --- o --- y
/ / /
default: o --- a --- o --- b --- o --- c --- o --- o --- d
where you've already merged default into your branch a couple of times. Merging default into your branch is normal since you want to regularly integrate the latest stuff from that branch to avoid the branches drifting too far away from each other.
But if a new file was introduced on default and later merged up into B, then you don't really want to see that in the hg status output. You will see it if you do
$ hg status --rev a:y
since the file was not present in a, but is present in y. If you do
$ hg status --rev d:y
then you wont see the file in the output, assuming that it's present in both heads.
You write in a comment that you're working Kiln repository. They mean "clone" when they say "branch", but the above can still be adapted for your case. All changesets will be on the default named branch, but that's okay.
Run the following command in your local clone of the "branch" repository:
$ hg bookmark -r tip mybranch
This marks the current tip as the head of mybranch. Then pull all the changesets from the main repository:
$ hg pull https://you.kilnhg.com/Repo/public/Group/Main
You then mark the new tip as the tip of the main repository:
$ hg bookmark -r tip main
You can now run
$ hg status --rev main:mybranch
to see the changes between main and my-branch. If you want to see what you did on the branch itself, the use
$ hg status --rev "::mybranch - ::main"
The ::mybranch part will select changesets that are ancestors of mybranch — this is all your new work, plus old history from before you branched. We remove the old history with - ::main. In older versions of Mercurial, you would use hg log -r -r mybranch:0 -P main.
In cases like this, I prefer to do a test merge from a newly checked-out copy of the repo. This has the advantage that I can see how many conflicts the merge will produce, and I can keep the merge result because I did it in its own copy.
To view the revision numbers, enable the graphlog extension and run:
$ hg log -b your-branch -G
This gives you a nice ASCII graph. This can be handy to quickly look at the graph, but I recommend using TortoiseHg for a cross-platform log viewer:
I had to merge the default branch into my branch to get some fixes, now the commands above shows also files changed because of merges (this files changed after the merge again in the default branch).
Therefore, to get only the correct files I use something like this:
hg log --rev "branch('my-branch') and not merge()" --template '{files}\n' | sed -e 's/ /\n/g' | sort -u
if you have spaces in file names, you can do it this way:
hg log --rev "branch('my-branch') and not merge()" --template '{rev}\0' | xargs -0 -I # hg status -n --change # | sort -u
And to answer your last question, revisions can be shown this way:
hg log --rev "branch('my-branch') and not merge()" --template '{rev}\n'
TIP: I use a hg-alias for this:
[alias]
_lf = ! $HG log --rev "branch(\"$1\") and not merge()" --template '{rev}\0' | xargs -0 -I # hg status -n --change # | sort -u
With mercurial, if you want to get the list of all the files changed in your current branch (changes done of your changeset) you can use these commands: :
hg log --branch $(hg branch) --stat | grep '|' | awk -F\ '{printf ("%s\n", $1)}' | sort -u
Example result:
api/tests/test_my_app.py
docker/run.sh
api/my_app.py
Explanation of the commands:
hg log --branch $(hg branch) --stat
Show revision history of entire repository or files and output diffstat-style summary of changes
hg branch
Show the current branch name
grep '|'
Search for a text pattern, in this case, it is "|"
awk -F\ '{printf ("%s\n", $1)}'
Space separator denotes each field in a record and prints each one in a new line
sort -u
Sort all the printed lines and delete duplicates