Æ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.