File History vs. Path History
Matt Mackall
mpm at selenic.com
Sat Jan 19 20:41:59 UTC 2013
On Sat, 2013-01-19 at 08:17 +0000, Paul Mensonides wrote:
> Hi all.
>
> Is it possible to extract a history for a particular file as opposed to a
> particular path? For example,
>
> hg init repo
> cd repo
>
> # 0
> touch A
> hg add A
> hg ci -m "added A"
>
> # 1
> hg mv A B
> hg ci -m "moved A to B"
>
> # 2
> touch A
> hg add A
> hg ci -m "added (new) A"
>
> If I now say
>
> hg log A
>
> the output refers to revision 0 which seems bizarre to me. The lifetime
> of A in the working copy began at revision 2, not revision 0.
Consider:
echo eisenhower > president
echo kennedy > massachusetts/senator
hg ci -m 'eisenhower reelected'
hg tag y1956
hg rm president
hg mv massachusetts/senator president
hg ci -m 'kennedy elected'
hg tag y1960
..if you say:
hg log president
..then the result is exactly what you want, if you were looking for a
history of presidents rather than a biography of 'obama'. In the grand
scheme of things, the former is more important.
Now replace "president" with "Makefile". From the perspective of your
build system, it does not matter at all how a particular file got to be
the Makefile, it's _still in charge_. Because files on your filesystem
are addressed by name, not by content or history, in a very real way,
filenames matter more than file history.
Opinions differ as to whether this is the right point of view for an SCM
to take; it's a deeply moot and uninteresting question for Mercurial at
this point.
> Is it possible to extract a history of a particular file instead--i.e. the
> first A independently from the second (unrelated) A?
hg log --follow A
..will follow the history of the file named 'A' _in your working
directory_ back to its origin, across copies and renames.
> Explicitly, what I actually need (wian) is all changesets which are
> descendants of a particular changeset which affect a particular file (with
> a --follow variation). E.g.
> hg wian -r 0 A
> => changesets 0 and 1
Unfortunately, we don't have a convenient way to do this for two
reasons:
a) all history pointers point strictly backwards, so tracing renames
forward is extremely expensive
b) there's currently no general syntax to say "tell me about the file
that was X in rev Y in rev Z" except for the special case of "tell me
about the ancestors of X in the working directory"
But you can do it manually. You can list the copies and renames in a
revision thusly:
$ hg stat -C --change 1089
A mercurial/changelog.py <- this file
mercurial/hg.py <- is a copy of this file
A mercurial/dirstate.py <- so is this one
mercurial/hg.py
A mercurial/filelog.py
mercurial/hg.py
A mercurial/httprepo.py
mercurial/hg.py
A mercurial/localrepo.py
mercurial/hg.py
A mercurial/manifest.py
mercurial/hg.py
A mercurial/node.py
A mercurial/remoterepo.py
mercurial/hg.py
A mercurial/repo.py
A mercurial/sshrepo.py
mercurial/hg.py
(this changeset was a massive refactoring in our repo)
We can automate queries using this sort of info with something like:
$ for r in `hg log mercurial/hg.py --template '{rev}\n'`; do (hg status
-C --change $r | grep -q "^ mercurial/hg.py") && hg log -vr $r; done
Let's break that down:
for each revision that touches hg.py
take its revision
use that to get the copies status
search the status for spots where hg.py is a copy source
if we find one:
show the log entry
> Is this possible with the current command set? If not, does the
> repository actually contain the information necessary to do this?
> Specifically, in the latter, are copies and moves actually tracked or are
> they just implied?
Yes, we actually track renames.
--
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial
mailing list