This morning, I was struggling (not for the first time) to produce a Git
command that would identify a merge commit that dropped a change. I
could see where it was added, but couldn't automate finding out why it
wasn't any longer in HEAD.
All the permutations of "--full-history", "-m", "-S", "-G" on "git log"
I could think of did not get me anywhere. As long as I had
"--full-history", they could find the original commit that had added the
change, but not the merge commit that had dropped it by taking the other
parent.
So, how to automatically find a merge that ignored a known change?
And then for visualisation purposes, how do you persuade gitk's diff
display to actually show that that merge commit removed the change from
one of its parents? Again, "-m" didn't seem to work.
Help appreciated!
Kevin
On 09/04/2013 21:00, Kevin Bracey wrote:
So, how to automatically find a merge that ignored a known change?
I think I've found the problem. It only doesn't work _if you specify the
file_.
Specifically, if I was missing an addition, my first attempt to find it
would be
git log -p -m -S<addition> <file>
If the addition was lost in a merge, that doesn't even show the
addition, which is surprising, but intentional. The addition isn't part
of the HEAD version of <file>, so no point going down that path of the
merge. Fine. However, I expected this to work:
git log --full-history -p -m -S<addition> <file>
But it doesn't. It finds the addition, but _not_ the loss in the merge
commit.
But this does work:
git log -p -m -S<addition>
That really feels like a bug to me. By specifying a file, I've made it
miss the change, and I can see no way to get the change without making
it a full-tree operation.
Looking at try_to_simplify_commit() it appears the merge that removed
the addition is excluded because it's TREESAME to its _other_ parent.
But with --full-history, we should only be eliminating a merge if its
TREESAME to all parents, surely? Otherwise we have this case that we
show a commit but not its reversion.
And the code doing this looks broken, or at least illogical - the parent
loop sets "tree_same" for a same parent in --full-history, rather than
immediately setting the TREESAME flag, so maybe previous authors were
thinking about this. But setting tree_same guarantees that TREESAME is
always set on exit anyway, so it's pointless (unless I'm missing something).
It does appear this is documented behaviour in the manual: "full-history
without parent rewriting" .. "P and M were excluded because they are
TREESAME to _a_ parent." I would say that they should have been excluded
due to being TREESAME to _all_ parents. I really don't want a merge
where one version of my file was chosen over another excluded from its
so-called "full history".
Now, obviously in a sane environment, most merges won't be that
interesting, as they'll just be propagating wanted patches from the real
commits already in the log. But I'd like some way to find merges that
drop code in a specified file, and surely "--full-history" is it?
Kevin