Joshua Goldberg
Joshua Goldberg

Reputation: 5333

Why does mercurial's log --follow option miss changesets?

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.)

Upvotes: 2

Views: 300

Answers (3)

jwd
jwd

Reputation: 11134

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:

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?

Upvotes: 1

Joshua Goldberg
Joshua Goldberg

Reputation: 5333

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.

Upvotes: 1

Edward
Edward

Reputation: 3276

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.

Upvotes: 1

Related Questions