From: Thomas Rast <hidden> Date: 2016-06-15 22:56:57
Ramkumar Ramachandra [off-list ref] writes:
Thomas Rast wrote:
quoted
[...]
I think you've misunderstood the whole thing. The histories of M^1
and M^2 are completely unrelated: they're from different projects
altogether. Considering the /ichi in M^2 a "rename" of the /ichi in
M^1 is completely wrong. They have nothing to do with each other. I
intentionally named it "ichi" in my orphan branch just to drive my
point. I suspect you've got confused because I used an orphan branch
to emulate a different project's history. If you want an end-user
understanding of the problem, use git subtree:
$ cd /tmp
$ git clone gh:artagnon/varlog
$ cd varlog
$ git subtree add --prefix=clayoven \
gh:artagnon/clayoven master
$ cd clayoven
$ git log README.md
What do you expect? The same output you would get if you cloned
gh:artagnon/clayoven separately and executed 'git log README.md' on
it.
No, I don't. But that's probably because I know a few things about how
git-log works that your hypothetical $USER doesn't.
At the risk of restating what everyone agrees on: It's a design
principle of git that it only stores tree states, and anything about
diffs, files, renames, etc. is purely in the imagination of the user.
We support that imagination by having analysis tools with which some
things can be found out, but others can't.
So (I think?) in the above you claim that $USER interprets
git log -- README.md
as
Show me the history of README.md.
But there's no such thing as the history of a file! The command instead
says
If I filter all history for only changes affecting a path 'README.md'
in the root of the repository[1], then what does it look like?
So please don't write tests that go contrary to that definition, because
they're *wrong*. The current implementation precisely matches the
current definition of pathspec filtering.
You can try arguing for changing the definition, but unless you find one
that can be implemented fast enough to be generally usable, I will
oppose that change.
The only thing that's broken in any of this is that I think, as
explained on IRC, that a hypothetical fixed --follow -C should be able
to figure out this case. By spending extra cycles on analysis,
naturally.
[1] and also skipping lines of history that seem uninteresting at this
point already, compare --simplify-merges
--
Thomas Rast
trast@{inf,student}.ethz.ch
So (I think?) in the above you claim that $USER interprets
git log -- README.md
as
Show me the history of README.md.
But there's no such thing as the history of a file!
I made no such claims. I might not know as much as you or the others
on the list about git, but I can certainly grok how git stores
history.
There needs to be some amount of mutual respect for a healthy
conversation: if you start assuming midway that I don't understand
what history is, we have a problem.
So please don't write tests that go contrary to that definition, because
they're *wrong*. The current implementation precisely matches the
current definition of pathspec filtering.
Who said anything about changing any definitions? Where are you
getting all this from?
How does "git log HEAD~3 -- README" work? It sets up a revision walk
to start from HEAD~3 going all the way down to the root commit. In
each of these commits, it looks for the entry "README" in the
corresponding tree. It then runs diff-tree with the previous commit's
tree to see if the object (blob) corresponding to the "README" entry
is different: if so, it selects the commit and displays it.
Now, what am I saying? I'm saying that this approach assumes that all
trees are read into /. A pathspec "subproject/README" is _only_
present in the subtree-merge commit^{tree} and nowhere else. The
current log algorithm might try to look for the entry
"subproject/README" (your pathspec) in all the commit^{tree}s of the
commits leading up to M^2. That is _not_ the problem, as I have
already illustrated that --follow follows over merges. The problem is
looking for the pathspec "subproject/README" in the first place: those
commit^{trees}s have the entry stored as "README".
Am I making any sense, or are you going to accuse me of not
understanding trees now?
The only thing that's broken in any of this is that I think, as
explained on IRC, that a hypothetical fixed --follow -C should be able
to figure out this case. By spending extra cycles on analysis,
naturally.
For the 100th time, nothing has been "copied". There is no need to
spend time on any analysis. It's a very straightforward problem that
requires no computation or heuristics: it just requires you to strip
the leading "subproject/" when looking for pathspecs in the M^2
commit^{tree}s. Done.
For the 100th time, nothing has been "copied". There is no need to
spend time on any analysis. It's a very straightforward problem that
requires no computation or heuristics: it just requires you to strip
the leading "subproject/" when looking for pathspecs in the M^2
commit^{tree}s. Done.
And if you're still not convinced, run 'git log HEAD^2 -- README.md'
from the toplevel directory. You'll get the log of README.md from the
subproject.
And if you're still not convinced, run 'git log HEAD^2 -- README.md'
from the toplevel directory. You'll get the log of README.md from the
subproject.
On IRC, Thomas explained to me that mixing in changes from various
branches into the pathspec will break this so-called determinism. To
try it out for yourself, do:
$ cd /tmp
$ git clone gh:trast/subtree-mainline-example
$ cd subtree-mainline-example
$ git log HEAD^2 -- sub # only lists the side changes
$ git log -- dir/sub # only lists the mainline changes
What we should really expect is a mix of the two.