hg log - How to get the last 5 log entries? - mercurial

I have a Mercurial project that has hundreds of commits.
When I want to look at the most recent entries I type
hg log
and then wait for everything to print out and then scroll back to the top.
How do I print out just the 5 most-recent entries?

Use the limit parameter: hg log --limit 5

In completion of the Michael Markert response you can use the shortversion
hg log -l 10
In addition if you want you can define via the option -b that you want only last commit from the current branch.
You can also do
hg log -l 10 -b [your branch]
for check 10 last commit from the branch you want
Of course you can go further with -d like this :
hg log -l 1 -d "feb 2015 to apr 2015"
This will give you last 10 commits within this date range (3 char for each months)
And goes on..
Full example and option are available in this link :
Here

Related

Some hg changesets not merging after graft

I have two hg branches (dev and stable) that aren't merging like I'd expect.
On stable: I grafted in a one-line commit from dev.
On dev: Changed that one line that was grafted, committed change.
On stable: merged dev into stable (no conflicts).
However after this merge stable still has the grafted version of the line (step 1). Not the latest changes to that same line from dev (step 2). Why is this?
The file looks like:
This
file
to
be
merged
Changesets:
Changes "to" to "might" on dev
Grafts changeset 1 to stable
Changes "might" back to "to" on dev
Merges dev into stable. Result is "might" (not "to" like I'd expect to see from changeset 3).
Sorry about the delay here: As soon as you shrank the reproducer to the five commits, I knew what was going on, but I wanted to write my own reproducer before answering, and the priority of this dropped a lot. 😀 The script I used, mktest.hg, to create the commits, the graft, and the merge, appears at the end of this answer.
The key issue here is the way merge actually works in Mercurial. It uses the same algorithm as Git does: that is, it completely ignores any of the branch information, and completely ignores any timing information. It looks only at three specific commits, as found by examining the commit graph, as shown in your image. Here's a text variant via my own reproducer:
$ cd test-hg-graft/
$ cat file.txt
This
file
might
be
merged
$ hg lga
# 4:b027441200d2:draft stable tip Chris Torek
|\ merge dev into stable (9 minutes ago)
| |
| o 3:01c6cc386a08:draft stable Chris Torek
| | back to "to" on stable (9 minutes ago)
| |
| o 2:ad954507e465:draft stable Chris Torek
| | s/to/might/ (9 minutes ago)
| |
o | 1:f7521e4f0941:draft dev Chris Torek
|/ s/to/might/ (9 minutes ago)
|
o 0:a163d2c4874b:draft stable Chris Torek
initial (9 minutes ago)
The lga alias is one I stole borrowed copied from someone else:
lga = log -G --style ~/.hgstuff/map-cmdline.lg
where map-cmdline.lg is in the link above. It's just log -G (aka glog) with a more-compact format.
What's going on
When we run:
hg merge dev
Mercurial locates three specific commits:
The current commit on stable, -r3 in this case (the SHA ID will vary), is one of the two endpoint commits.
The target commit on dev is the result of resolving dev to a revision. We can do this ourselves with hg id -r dev for instance:
$ hg id -r dev
f7521e4f0941 (dev)
$ hg id -n -r dev
1
Note that we can do the same thing with # to identify our current revision, although hg summary spills everything out more conveniently.
Last (or in some sense first, though we need the other two to get here), Mercurial locates a merge base commit from these two commits. The merge base is the first commit in the graph that is reachable from both of the other inputs to the merge. In our particular case, that's rev zero, since we split the branches apart right after -r0.
Technically, the merge base is the output of a Lowest Common Ancestor algorithm as run on the Directed Acyclic Graph. See Wikipedia for some examples. There can be more than one LCA; Mercurial picks one at (apparent) random for this case. In our case there is only one LCA though.
Having found the merge base, Mercurial now runs the equivalent of two diff operations:
hg diff -r 0 -r 3
to see what we changed, and:
hg diff -r 0 -r 1
to see what they changed, since the merge base snapshot.1 If we do this ourselves, we see what Mercurial sees:
$ hg diff -r 0 -r 3
$ hg diff -r 0 -r 1
diff --git a/file.txt b/file.txt
--- a/file.txt
+++ b/file.txt
## -1,5 +1,5 ##
This
file
-to
+might
be
merged
(I have my hg diff configured with git = true so that I get diffs that I can feed to Git—long ago I was doing a lot of conversion work here.)
As far as Mercurial is concerned, then, we did nothing on our branch. So it combines do nothing with make this change to file.txt and comes up with this one change to file.txt. That one change is applied to the files from the merge base commit. The resulting files—well, file, singular, in this case—are the ones that are ready to go into the final merge commit, even though they're not the ones you wanted.
Because Mercurial has more information than Git—in particular, which branch something happened on—it would be possible for Mercurial to behave differently from Git here. But in fact, both do the same thing with this kind of operation. They both find a merge base snapshot, compare the snapshot to the two input commit snapshots, and apply the resulting combined changeset to the files from the merge base. Mercurial can do a better job of catching file renames (since it knows them, vs Git, which just has to guess) and could do a different job of merging here, but doesn't.
1Some might object that Mercurial stores changesets, not snapshots. This is true—or rather, sort of true: every once in a while, Mercurial stores a new copy of a file, instead of a change for it. But as long as we have all the commits needed, storing changes vs storing snapshots is pretty much irrelevant. Given two adjacent snapshots, we can find a changeset, and given one snapshot and a changeset to move forward or backward, we can compute a new snapshot. That's how we can extract a snapshot in Mercurial (which stores changesets), or show a changeset in Git (which stores snapshots).
Script: mktest.hg
#! /bin/sh
d=test-hg-graft
test "$1" = replay && rm -rf $d
if test -e $d; then
echo "fatal: $d already exists" 1>&2
exit 1
fi
set -e
mkdir $d
cd $d
hg init
hg branch stable
cat << END > file.txt
This
file
to
be
merged
END
hg add file.txt
hg commit -m initial
hg branch dev
ed file.txt << END
3s/to/might/
w
q
END
hg commit -m 's/to/might/'
hg checkout stable
hg graft -r 1 # pick up s/to/might/; graft makes its own commit
ed file.txt << END
3s/might/to/
w
q
END
hg commit -m 'back to "to" on stable'
hg merge dev
hg commit -m "merge dev into stable"

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!

Delete local bookmarks that haven't been touched in 7 days

How should I clean up all the local bookmarks that hasn't been touched recently (say in the past 7 days)? Using
hg bookmark -d <bookmark name>
seems unscalable.
To my knowledge there is no information as to when a bookmark was updated to last or when it was created; you can only obtain the information of the age of the commits they are attached to easily, e.g.
hg log -r "bookmark() and date('-1000')"
hg log -r "bookmark() and date('<01/30/2015')"
for all bookmarks attached to commits created in the last 1000 days or all bookmarks attached to commits older than January 30th 2015.
EDIT to add: There is the Journal Extension. It allows to actually track when and to which revisions a bookmark was attached to. Thus you might want to enable this extension if you want to solve your problem for the future.
hg bookmark -d can take multiple arguments, so combining with the answer above you can do:
hg bookmark -d `hg log -r "bookmark() and date('-1000')" -T '{bookmarks} '`
I use this to remove all public bookmarks, since I only use them locally:
hg bookmark -d `hg log -r "bookmark() and public()" -T '{bookmarks} '`

hg log: how to get latest commit by a particular user?

I have a repo with multiple users. I need to make a python script to retrieve a particular user's latest commits. How do I do that with mercurial?
I was thinking of calling an hg log command thru Python's subprocess call. The problem is how I should call the hg log command such that it tells me a user's latest logs.
Easy (but not efficient or elegant way)
hg log -u USERNAME
or (with revsets)
hg log -r "author(USERNAME)"
with added value
If string starts with "re:", the remainder of the string is treated as a regular expression. To match a user that actually contains "re:", use the prefix "literal:".
I think you should be able to get a single user's latest commit by calling something like this with a system call. (Command-line version follows.)
$ hg log -u your-user-name | head -5
The head -5 gives you the whole abbreviated hg log output for the latest changeset for your-user-name, which includes five lines: changeset, tag, user, date, and summary. If you want only the changeset, you could use something along these lines. (Command-line version, again.)
$ hg log -u mike#fontling.com | head -1 | awk '{print $2}'
Comments suggest this makes unwarranted assumptions about the output format. I agree.
Based on comments, this seems to be the best expression for getting the last commit from a user.
hg log -r "last(author('email#domain.com'))"
hg log -r "last(author('Fred Flintstone'))"
To get the last three . . .
hg log -r "last(author('email#domain.com'), 3)"
hg log -r "last(author('Fred Flintstone'), 3)"

How can I list a series of revisions using 'hg log'?

I'm attempting to use the hg log command to show a series of revisions, x through y.
When I do this:
hg log -r 1+5
I get this:
changeset: 1:7320d2a9baa5
user: Tim Post <tpost#whereiwork.com>
date: Fri Sep 30 20:38:29 2011 +0800
summary: Foo foo everywhere is foo
changeset: 5:8d6bea76ce60
user: Tim Post <tpost#whereiwork.com>
date: Fri Sep 30 20:51:42 2011 +0800
summary: Blah blah blah
Which is Mercurial understanding that I want to see revisions one and five instead of one through five.
Oddly enough, this works:
hg log -r 1+2+3+4+5
But, that gets extremely cumbersome, especially when trying to get a summary between revisions that are +500 away from each other.
Is there a way to get logs for revisions x through y instead of x and y without concatenating every revision in the series?
I'm using the output in order to determine how many commitments each developer made in a given series. If I simply can't do that using the hg command, I'm more than open to using the Mercurial API. I resorted to the hg command because I did not see an obvious way of doing it via the API.
By API, I mean just using Python via a hook or extension.
hg log -r1:5.
Mercurial has an entire mini-language devoted to selecting revisions for commands (not just for logs). For more information, see hg help revsets (needs Mercurial 1.6+).