Re: Am able to delete a file with no trace in the log

9 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: Am able to delete a file with no trace in the log

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:54

Linus Torvalds [off-list ref] writes:
For example, right now there is _no_ way to get even a "show diff relative 
to first parent". You can do "-m", which will show it relative to _both_ 
parents, but nobody ever wants that. And you can do "-c" or "--cc", but 
that simplifies away all the paths that match in one. 
Actually for that "Where did my file 'x' go across the merge chain", I was
going to suggest something like

	git log --simplify-merges -m --raw -- x
So here's a challenge: in the git repository, get a nice view of what your 
merges looked like. The closest I can get is

	git log -c --stat --grep="Merge branch '"

which is actually very non-intuitive ("-c" on its own gives no useful 
output, but "-c --stat" gives nice diffstat against the first parent, 
which in this case is what we want).
I think the logical place to hook that into is the --first-parent option.

I actually have very hard resisted so far the temptation to do so because
your mantra has always been "in a merge, all parents are equal."  If you
treat the first parent specially too heavily, it would go against the "I
got a pull request from you, but the resulting conflicts are too much for
me; you know the area much better than I do, so could you do the merge for
me and I'll fast forward to you later" workflow.  The "first parent is the
mainline" and "I am important, so I'll merge with --no-ff to pee in the
snow" mentality problems will become worse.

Re: Am able to delete a file with no trace in the log

From: Jeff King <hidden>
Date: 2016-06-15 22:46:54

On Wed, Jun 03, 2009 at 03:38:00PM -0700, Junio C Hamano wrote:
Actually for that "Where did my file 'x' go across the merge chain", I was
going to suggest something like

	git log --simplify-merges -m --raw -- x
But in the original example, the merge commit where 'x' is deleted isn't
shown _at all_ when path limiting is used. You end up either with
"git log -m" showing the two sides of the merge separately, "git log
--simplify-merges -- x" showing stuff that happened on the side branch
but _not_ the actual merge that made a change, or of course "git log --
x" showing nothing (because we don't traverse the changing side of the
merge).

Is there a way to say "show me everything that touched x, _including_
merges"?

-Peff

Re: Am able to delete a file with no trace in the log

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:46:54


On Wed, 3 Jun 2009, Junio C Hamano wrote:
Linus Torvalds [off-list ref] writes:
quoted
For example, right now there is _no_ way to get even a "show diff relative 
to first parent". You can do "-m", which will show it relative to _both_ 
parents, but nobody ever wants that. And you can do "-c" or "--cc", but 
that simplifies away all the paths that match in one. 
Actually for that "Where did my file 'x' go across the merge chain", I was
going to suggest something like

	git log --simplify-merges -m --raw -- x
Ok. Not very readable, but it's certainly getting closer.
quoted
So here's a challenge: in the git repository, get a nice view of what your 
merges looked like. The closest I can get is

	git log -c --stat --grep="Merge branch '"

which is actually very non-intuitive ("-c" on its own gives no useful 
output, but "-c --stat" gives nice diffstat against the first parent, 
which in this case is what we want).
I think the logical place to hook that into is the --first-parent option.

I actually have very hard resisted so far the temptation to do so because
your mantra has always been "in a merge, all parents are equal." 
Oh, I agree. The challenge was just the first step - how to make it do 
merges in general sanely would be the issue.

Because if you do just --first-parent, then that won't even show the 
test-case that Graham actually had - because the missing file didn't come 
in from the first parent of a merge. 

The challenge was mainly as a way to point out that even some fairly 
simple cases aren't all that simple.

		Linus

Re: Am able to delete a file with no trace in the log

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:46:54


On Wed, 3 Jun 2009, Jeff King wrote:
Is there a way to say "show me everything that touched x, _including_
merges"?
Well, that's the "--simplify-merges" part. 

It's just that our diff generation isn't very smart. We do show the 
commit, we just don't show a meaningful diff in that case.

And doing good diffs for a merge is _hard_. The "--cc" thing is supremely 
useful - it's just that it's useful for data conflicts, not for metadata 
issues.

It's in fact somewhat dubious if you actually want to see the file removal 
as a _diff_ in a merge, exactly because it's so verbose and yet often so 
uninteresting (ie the removal may well be intentional). 

It might be that the right thing to do is to expand on "-c" and '--cc" to 
just give a summary of metadata changes.

Right now, "-c" and "--cc" ignore files that didn't change from one of the 
parents.

But maybe the right thing to do is to entirely ignore files only if they 
exist in all parents, but didn't change in one - and for things that have 
actual metadata changes, just say

 - exists in merge result, but not in parent 2:

   File 'x' was created in parent 1

 - does not exist in merge result, but exists in parent 1:

   File 'y' was deleted by parent 2

or similar (with perhaps even rename detection some day if -M is 
specified, although n-way rename detection is likely pretty painful).

IOW, do the whole "extended diff", but not actually show any diffs, just 
summary information, for new/deleted files in merges.

That would be enough of a hint to then use other tools to see the exact 
details of what happened..

			Linus

Re: Am able to delete a file with no trace in the log

From: Jeff King <hidden>
Date: 2016-06-15 22:46:54

On Wed, Jun 03, 2009 at 03:56:01PM -0700, Linus Torvalds wrote:
quoted
Is there a way to say "show me everything that touched x, _including_
merges"?
Well, that's the "--simplify-merges" part. 

It's just that our diff generation isn't very smart. We do show the 
commit, we just don't show a meaningful diff in that case.
No, --simplify-merges doesn't show the merge, unless I am doing
something very wrong. Try (and this is a simplified version of the
original example):

  mkdir repo && cd repo && git init &&
  echo content >base && git add base && git commit -m base &&
  echo context >a.txt && git add a.txt && git commit -m 'master 1' &&
  git checkout -b other HEAD^ &&
  echo content >b.txt && git add b.txt && git commit -m 'other 1' &&
  echo conflict >a.txt && git add a.txt && git commit -m 'other 2' &&
  git checkout master &&
  git merge other ;# conflicts

  rm b.txt && git add b.txt &&
  echo resolve >a.txt && git add a.txt &&
  git commit -m merged

Now try running git log on that. I can see the merge diff if I use "-m",
which is obviously too verbose, but at least works. But if I give
"b.txt" as a path limiter, I can't get the merge commit to display at
all. Doing "git log -m --simplify-merges --stat -- b.txt" yields only
the commit "other 1" in which b.txt was added.

-Peff

Re: Am able to delete a file with no trace in the log

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:46:54


On Wed, 3 Jun 2009, Jeff King wrote:
Try (and this is a simplified version of the original example):

  mkdir repo && cd repo && git init &&
  echo content >base && git add base && git commit -m base &&
  echo context >a.txt && git add a.txt && git commit -m 'master 1' &&
  git checkout -b other HEAD^ &&
  echo content >b.txt && git add b.txt && git commit -m 'other 1' &&
  echo conflict >a.txt && git add a.txt && git commit -m 'other 2' &&
  git checkout master &&
  git merge other ;# conflicts

  rm b.txt && git add b.txt &&
  echo resolve >a.txt && git add a.txt &&
  git commit -m merged
This doesn't work at all for me.

Do

	git show HEAD:b.txt

and it still shows b.txt in the commit. You should have used

	git rm b.txt

rather than "git add b.txt" (or you use use "-u" or "-a" to git add).

That looks like a bug, btw, but whatever. It seems intentional (we do the 
whole "ADD_CACHE_IGNORE_REMOVAL" flag thing).

But you're right. Even when fixed, it does seem to need "--full-history" 
to stay around, and --simplify-merges is insufficient. Bug in merge 
simplification?

			Linus

Re: Am able to delete a file with no trace in the log

From: Jeff King <hidden>
Date: 2016-06-15 22:46:54

On Wed, Jun 03, 2009 at 04:27:39PM -0700, Linus Torvalds wrote:
quoted
  rm b.txt && git add b.txt &&
  echo resolve >a.txt && git add a.txt &&
  git commit -m merged
This doesn't work at all for me.

Do

	git show HEAD:b.txt

and it still shows b.txt in the commit. You should have used

	git rm b.txt

rather than "git add b.txt" (or you use use "-u" or "-a" to git add).
Er, sorry, yeah, I botched the recipe (I initially used "git rm" by
itself, but it complains about "changes staged in the index", so I fixed
it up manually and then botched writing out the automated version).

But I see you figured out what I meant, so...
But you're right. Even when fixed, it does seem to need "--full-history" 
to stay around, and --simplify-merges is insufficient. Bug in merge 
simplification?
I don't even see it with --full-history. I get:

  $ git log -m --stat --oneline | head
  b1a38ec (from 2671fa7) merged
   a.txt |    2 +-
   1 files changed, 1 insertions(+), 1 deletions(-)
  b1a38ec (from d0bac65) merged
   a.txt |    2 +-
   b.txt |    1 -
   2 files changed, 1 insertions(+), 2 deletions(-)

  $ git log -m --stat --oneline -- b.txt
  (no output)

  $ git log --simplify-merges -m --stat --oneline -- b.txt
  912ac84 other 1
   b.txt |    1 +
   1 files changed, 1 insertions(+), 0 deletions(-)

  $ git log --full-history -m --stat --oneline -- b.txt
  912ac84 other 1
   b.txt |    1 +
   1 files changed, 1 insertions(+), 0 deletions(-)

Is there some trick to enabling both path limiting _and_ still showing
the merge commit? Or is this a bug?

-Peff

Re: Am able to delete a file with no trace in the log

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:46:54


On Wed, 3 Jun 2009, Jeff King wrote:
I don't even see it with --full-history. 
Oh, that's because I used "gitk" rather than "git log", and that adds 
--parents, which in turn means that it actually keeps the merges. 

So with

	git log --full-history --parents --stat -- b.txt

you actually finally get a visible removal.

		Linus

Re: Am able to delete a file with no trace in the log

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:54

Linus Torvalds [off-list ref] writes:
And doing good diffs for a merge is _hard_. The "--cc" thing is supremely 
useful - it's just that it's useful for data conflicts, not for metadata 
issues.

It's in fact somewhat dubious if you actually want to see the file removal 
as a _diff_ in a merge, exactly because it's so verbose and yet often so 
uninteresting (ie the removal may well be intentional). 
Thinking about this a bit more, a "good" diff for merge that catches this
kind of "broken merge" would likely require redoing a merge when you ask
for a diff.

Earlier, in my "Here is a crude attempt" patch, I mentioned that the
merges in the beginning part of the output are uninteresting while the one
that merges "Build-in git-clone" is interesting (and "crude attempt" was
not useful because it shows both).

The reason?  The uninteresting ones match mechanical merge result, while
the interesting one does not.  For example, 17d778e (the first one in the
output --- an uninteresting one) is a merge between 5e97f46 and 450f437;
the former branch removes the path in question (git-clone.sh) compared to
their merge base, while the latter does not change it, hence the
mechanical resolution to remove the path matches what the final merge
records.  On the other hand, b84c343 (Merge branch 'db/clone-in-c') merges 
0dbaa5b (modifies "git-clone.sh" since the merge base) and b50c846
(removes) and the mechanical merge results in a conflict.

I think the original example can be handled in the same way.  A side
branch created a new file since the merge base, but a merge lost the file
by mistake.  The recorded result does not resemble the mechanical merge
result and we can flag it by detecting this condition (that is, if we
wanted to --- I do not think we want to spend cycles to recreate a merge
while traversing the history with "log --stat" by default).
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help