Home > Software engineering >  Git log grep: How to match commit-message substrings regardless of word-order?
Git log grep: How to match commit-message substrings regardless of word-order?

Time:02-22

I tried this

git log -i --all --grep='/(?=.*fix)(?=.*a)(?=.*bug)/'

but did not work.

CodePudding user response:

There are several issues:

  • When using grep, the regex pattern is not passed inside regex delimiters, but as a regular string
  • The PCRE-compliant pattern you used might not work as the default git grep regex engine is POSIX BRE flavor
  • The pattern you used matches fix, a or bug in any order on the same line but requires them all to be present. To match specified strings in any order you need alternation patterns, e.g. a|b|c. However, in POSIX BRE, alternation operator is not supported, although the POSIX extension available in GNU tools allows the use of \| alternation operator version.

So, if you plan to match entries with these 3 words in any order, you need to remove regex delimiters and enable PCRE regex engine:

git log -i -P --all --grep='^(?=.*fix)(?=.*a)(?=.*bug)'

Note the -P option that enables the PCRE regex engine. Also, mind what documentation says:

-P
--perl-regexp
Consider the limiting patterns to be Perl-compatible regular expressions.

Support for these types of regular expressions is an optional compile-time dependency. If Git wasn’t compiled with support for them providing this option will cause it to die.

If you want to match entries with any of the words, you can use

git log -i -E --all --grep='fix|a|bug'

With -E option, POSIX ERE syntax is enforced, and | is an alternation pattern in this regex flavor.

To match them as whole words, use \b or \</\> word boundaries:

git log -i -E --all --grep='\<(fix|a|bug)\>'
git log -i -E --all --grep='\b(fix|a|bug)\b'

NOTE for Windows users:

In Windows Git CMD or Windows console, ' must be replaced with ":

git log -i -P --all --grep="^(?=.*fix)(?=.*a)(?=.*bug)"
git log -i -E --all --grep="\b(fix|a|bug)\b"
  • Related