Re: bug: `git log --grep ... --invert-grep --author=...` negates / ignores --author

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx> writes:

> Anyway, much of the above may be incorrect, I haven't dug deeply
> beyond just finding that something's funny going on and we definitely
> have *some* bugs here.

One thing that is very correct in what you said is that the
documentation of "--invert-grep" is wrong to mention only "--grep".
It probably is because the author of "--invert-grep" did not realize
that the "--author" thing internally is considered a part of "grep"
processing done in revision.c::commit_match() that chooses which
commit to show.

As you may have noticed, the integration to the grep infrastructure
with "git log" and friends does not expose the power of combination
(e.g. "--and", "--not", etc.), unlike "git grep", to the command
line.  This is purely a technical limitation (e.g. "--not" is taken
to mean a completely different thing in "git log" family) and there
is no fundamental reason why we shouldn't, but the fact that the end
user cannot combine the "--grep" like terms in a flexible way
remains from the beginning to this day.

Within that constraint, --grep and things like --author are defined
to interact in a certain hardcoded way (the former searches
substring in the body part of commit objects while the latter
searches substrings in the "header" part of them), simply because
defining them to be all ORed together does not give us a very useful
semantics.

In general, two or more of these searches always "OR" together,
e.g. "git log --grep=foo --grep=bar" finds commits that mention foo
or commits that mention bar.  However, searches in body and searches
in header "AND" together, e.g. "git log --author=Ævar --grep=foo"
finds commits that mention foo and written by you.  "git log
--author=Ævar --author=gitster@ --grep=foo --grep=bar" finds commits
that mention either foo or bar and written by either you or me.
IIRC, its parse tree would look like

    (AND (OR (author Ævar) (author gitster@))
         (OR (grep foo) (grep bar))

The "--invert-grep" merely adds (NOT ...) around it.

I vaguely recall there was impliations to "all match" when the
header search and the body search is used together.  Without header
search, the usual "git log --grep=foo --grep=bar" becomes

         (OR (grep foo) (grep bar))

and "--all-match" is applied to this "OR" (i.e. by the time the
matcher finishes a single commit's body, all of the terms ORed
together, i.e. (grep foo) and (grep bar), must have matched at least
once for the commit to be considered a match.  Obviously, a commit
can be authored and commited by only a single person, and applying
all-match naively to "git log --author=Ævar --author=gitster@" would
not make any sense (by definition the result would be an empty set),
and IIRC there is a code that copes with this to avoid requiring a
commit that is written by two people (or committed by two people)
when "--all-match" is in effect.

So taken all together, your example and its output makes all sense
to me.  As you mentioned, the examples by the OP was written a bit
too dense for me to grok quickly and I didn't look too carefully at
them to comment.



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]