Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git alias for searching for commit messages

I do have aliases found on the web:

find = "log --decorate -i --all --date=short --grep"

search = "!f() { git log --decorate --grep=$1 -i --all --date=short; }; f"

They both do the same: search within commit messages. Is there one somehow one "superior" to the other? Why?

QUESTION -- How could we write an alias for searching for commits that contain particular words in the message?

For example, where:

git search-msg foo bar baz

would match commits containing the words foo, bar and baz, in whichever order?

ANSWER -- Better formatting here (from LeGEC):

search-msg = "!f() { str=\"git log --all-match\"; \
                     for var in \"$@\"; do \
                         str=\"$str --grep '$var'\"; \
                     done; \
                     eval $str; }; f"
like image 749
user3341592 Avatar asked Mar 15 '26 03:03

user3341592


2 Answers

First a word about git log's --grep option :

  • you can specify it multiple times
  • default multiple grep is "match any of the patterns"
  • there is an additional --all-match flag, which indicates "match all of the patterns"

Example :

# two commits contain 'foo' in their message (one of them also contains 'bar'):
$ git log --oneline --grep foo
b76121c bar baz foo
b7a342f foo

# two commits contain 'bar' in their message (one of them also contains 'foo'):
$ git log --oneline --grep bar
bbb27f3 (HEAD -> master) bar
b76121c bar baz foo

# if I look for both patterns : I get the union of both searches (3 commits)
$ git log --oneline --grep foo --grep bar
bbb27f3 (HEAD -> master) bar
b76121c bar baz foo
b7a342f foo

# if I add '--all-match' : only the commit which contains both is kept
$ git log --oneline --grep foo --grep bar --all-match
b76121c bar baz foo

To answer your question : here is a sample script that takes a list of arguments, and turns them into a git log --all-match --grep aaa --grep bbb command :

# in file git-search-msg :

#!/bin/bash

cmd=("log" "--all-match")

for var in "$@"
do
        cmd+=('--grep')
        cmd+=("$var")
done

git "${cmd[@]}"

If you paste this in a file named git-search-msg, and put it somewhere on your PATH, then git search-msg foo bar baz will do what you want.


The following works in plain sh, but uses eval :

#!/bin/sh
str="git log --all-match"

for var in "$@"
do
    # This loops takes arguments one by one and adds
    # them as '--grep' args to the 'git log' command.
    str="$str --grep '$var'"
done

# tech note : this sample script does not escape single quotes
eval $str

If you manage to oneline it (and escape it correctly), you can use it in an alias.

Beware the escaping problems mixed with eval though ...

like image 107
LeGEC Avatar answered Mar 17 '26 22:03

LeGEC


You may want to add history to search through the whole repository, by adding rev-list to your git log

git log --grep 'Something relevant in my commits' $(git rev-list --all)

Something like should work in the .gitconfig file

[alias]
    search = "!f() { git log --grep \"$1\" $(git rev-list --all); }; f"
[log]
    date = iso

The date = iso thing is here to get a better date (current format is 2019-11-26 17:35:30 +0100)

like image 31
Tarto Avatar answered Mar 17 '26 21:03

Tarto