I know that the order of hg log can be reversed by calling hg log -r:. Then the oldest commit is topmost and the newest item is at the bottom.
Is something similar possible for hg glog (or hg log -G) from the graphlog extension?
No, you can't reverse it, but you can restrict it to a certain range using the --rev option.
hg glog --rev 0:1
and
hg glog --rev 1:0
both show revision 1 above revision 0, but you're at least seeing the tail end of the output.
You cannot use the -G option as it is used for printing the 'tree' (see --o--o).
What you can use is the predicate 'sort' from hg revsets:
"sort(set[, [-]key... [, ...]])"
Sort set by keys. The default sort order is ascending, specify a key
as "-key" to sort in descending order. The keys can be:
"rev" for the revision number,
"branch" for the branch name,
"desc" for the commit message (description),
"user" for user name ("author" can be used as an alias),
"date" for the commit date "topo" for a reverse topographical sort
e.g. 2: to print the last 10 commits in reverse order:
$ hg log --rev 'sort(last(:,10), -rev)'
Where:
last(:,10) revision set takes the last 10 commits from all commits
sort(revset, -rev) sorts the revision revset in reverse order
e.g. 1 print all changesets not belonging to the base repo in reverse order
$ hg log -r "sort(ancestors(.), -rev) and outgoing('ssh://hg#your/external/repo')"
Where:
ancestors(.) revision set takes all commits from the current branch
and outgoing() results in only keeping the outgoing changesets
Related
Can you help me to create a proper revset for mercurial hg status ?
I would like to list all the files that were changed in the current branch since it was created.
I tried
hg status --rev "branch(foo)"
where foo is the name of my branch, but this also lists files that were changed in the branch from which my branch was created (?).
I don't get how to create a proper revset for this.
I created my branch and made several changes in multiple files. Now I want to reload these files in my application, but only them.
This seems pretty straightforward (see hg help revsets and hg help revisions for where this comes from).
We might start with the set of all commits in a branch, e.g., for branch foo:
-r 'branch(foo)'
Obviously this can produce a dozen, or even a million, revisions; but you want to see what happened between "branch creation"—which needs to examine the parent of the first such revision—and "current status of branch", which needs to examine the last such revision.
The first1 revision of a large set is obtained by first() and the last by last(). However, when various commands are given a revision specifier, they look it up as a single revision, and here a branch name suffices to name the last commit on the branch anyway.
To get the (first) parent of a revision, we use the p1() function (the suffix ^ is only allowed on a literal revision, not a function that returns a revision). Hence the parent of the first revision on branch foo is:
-r 'p1(first(branch(foo)))'
To get a full diff of this against the last commit in the branch:
hg diff -r 'p1(first(branch(foo)))' -r 'foo'
But you don't want a full diff, you want the file names. The command that produces this is hg status, and it has a slightly different syntax:
hg status --rev 'p1(first(branch(foo)))' --rev 'foo'
The status includes the letters at the front, as well as the names: A for newly added files, M for modified files, and so on. Note the use of --rev rather than just -r (in fact, you can use --rev with hg diff as well).
Note that there's a much shorter syntax, ::foo, that gets all the ancestors of the given branch up to and including the last revision in the named branch. However, this gets too many ancestors. You can, however, use p1(first(branch(foo)))::foo as the (entire) argument to --rev, and this also works. so:
hg status --rev 'p1(first(branch(foo)))::foo`
is a slightly shorter way to express this.
Last, note that comparing the first commit in the branch to the last (as would happen with hg status --rev 'first(branch(foo))' --rev foo, for instance) can miss changes made in that first commit on the branch. That's why we use p1 here.
1The first function selects the first in the set, which may not be the same as the numerically-first revision. For instance, suppose the set is made from x | y and a revision in y is numerically lower than a revision in x, or you use reverse(branch(foo)) to put the commits in high-to-low order. In this case, min instead of first would be the function to use.
This this possible? Currently, I first do an hg parents to find the parents, then an hg diff using two revisions. But it would be easier if hg diff had the option to take a single revision and find the parents automatically.
You're looking for the 'change' switch on diff:
-c --change REV change made by revision
you use it like this (for revision 298):
hg diff --change 298
If you use it on a merge changeset (which has two parents), only the first parent is compared. In that case you can use the p2 revset to get the second parent:
hg diff -r 298:p2(298)
hg diff -r 'tip~1'
because
"x~n"
The nth first ancestor of x; "x~0" is x; "x~3" is "x^^^". For n < 0, the nth unambiguous descendent of x.
After pushing changesets to a repository called 'A' how can I see the list of changesets waiting to be applied when I am in 'A'?
Expanding on that,
In repo B I push changesets to repo B
I change to repo B
How can I list the changesets pushed in step 1?
Not sure what you mean by "unapplied" changesets, however here's a couple thoughts.
You can easily see what changesets will be pushed to a repository by doing hg outgoing prior to doing the hg push. This will list all of the changesets that will be pushed using default options.
Similarly you can use hg incoming in the destination repository to show what changesets would be pulled from another repo.
As for "unapplied" changesets, if I assume you mean changesets that are newer than the working directory, you could use hg log -r .:tip, which should (I've not had a chance to test it) show all newer revisions, but not actually all recently-pushed ones.
Edit: I've updated the revision set in the -r option to something that should work. Have a look at revsets on the Mercurial manpage for more possibilities.
$ hg summary
parent: 0:9f47fcf4811f
.
branch: default
commit: (clean)
update: 2 new changesets (update) <<<<<
The update bit tells you what (I think) you want.
I had written a different answer, but I ended up with a better way of doing what is needed here (an even better and definitive –for me– solution is at the end of this post, in the [EDIT] section).
Use hg log.
Specifically, issue an hg sum command first. This will give me:
parent: 189:77e9fd7e4554
<some commit message>
branch: default
commit: (clean)
update: 2 new changesets (update)
To see what those 2 new changesets are made of, I use
hg log -r tip -r 2 -v
Obviously, 2 is to be replaced with the number of changesets that hg sum reports.
This works because tip will refer to the most recent (or "unapplied") changeset. By limiting the output to the 2 latest changes (-l 2), the information is shown only for those changesets that I'm interested in. With -v, the list of files affected by the changeset is also shown.
To make things simpler, I have defined a user command in my .bashrc file:
alias hglog="hg log -r tip -l $1"
This allows me to type hg sum (to get the number of pending/unapplied changesets) and then to type hglog x where x is the number of changesets revealed by hg sum.
There is probably a more complete way of doing this, for instance using custom templates, but I guess it's pushing things too far in terms of sophistication.
[EDIT] (Third iteration)
I have reached the most satisfying answer to this question by expanding on the alias idea so that I no longer have to type hg sum. My .bashrc file now contains this:
show_pending_changesets() {
nb=$(hg sum | grep "update:" | sed 's/update: \([0-9]*\) .*/\1/');
if [ `expr $nb + 1 2> /dev/null` ] ; then
hg log -r tip -v -l $nb
else
echo "Nothing new to report"
fi ;
}
...
alias hgwhatsnew=show_pending_changesets
Explanation: I'm using sed to extract the number of changesets from the last line (which is the one that starts with update:) of the output of hg sum. That number is then fed to hg log. All I have to do then is to type hgw and tab-complete it. HTH
To diff we use:
hg diff -c <xyz>: Show diffs for a given changeset
hg diff -r <xyz>: Show all diffs since a given changeset
But let's say you have changesets 4-5-6-7-8 where changesets 4, 6, 8 were related to a particular area of the system and in one diff you wanted to see the changes made from JUST these three changesets, how would you do this? If file A was modified in changeset 4 and 8, the diff would show the difference between changeset 3 and 8.
If changesets 4,5,6,7,8 are linear in history I don't think that even with revsets you can do that using just -r. However, if the changes in 5 and 7 really are from a different part of the system you can likely get the output you want by adding a -X or a -I. Something like this:
hg diff -r 3::8 -X part/you/do/not/want/**
or
hg diff -r 3::8 -I part/you/do/want/**
If, alternately, you're a little more exact about parenting a changeset as early as possible in history you'd have a topology like this:
[3]---[4]---[6]---[8]---[9]
\ /
------[5]---[7]------
and then you'd get what you want using:
hg diff -r 3::8
(note the double colon which tells the range to follow topology not just numeric range)
How do I get a list of all files affected in a changeset since rev 3456?
Note:
I tried hg log --rev 3456:tip --template "{files}"\n but there are several problems
If a changeset affects multiple files, they all appear on the same line.
This also shows the same file multiple times if a file was involved in many changsets.
hg stat --rev 3456
hg stat --rev 3456:tip to exclude uncommitted changes
There's a previous question that covers the same issue, with the added restriction that the search be restricted to files belonging to 'myself.' You can simply remove the '--user' and it should do what you need.
create a file named "mystyle"
changeset = "{files}"
file="{file}\n"
Then hg log --style mystyle --rev 3456:tip | sort | unique