In git log, how do you filter commits by author, message text, and date range?
answer
- Three filter families, different combination rules
- Patterns are regular expressions by default
- Same filter repeated means OR
- --all-match turns the message patterns into AND
- Date limiting prunes rather than post-filters
basics
~10 sgit log --author=<pattern> matches the author header, --grep=<pattern> matches the commit message, and --since/--until bound the date range. Patterns are regular expressions; multiple --grep options are OR-ed unless you add --all-match.
solid answer
~40 s`--author=<pattern>` and `--committer=<pattern>` match a regular expression against the corresponding header line, so either a name or an email address works. `--grep=<pattern>` matches the commit message. `--since` (alias `--after`) and `--until` (alias `--before`) bound the range and accept human dates like `--since='2 weeks ago'`. The combination rules trip people up: several `--grep` patterns are OR-ed by default, `--all-match` demands every one of them matches, and `--invert-grep` excludes matches; but `--author` and `--grep` together are AND-ed because they are different filter kinds. `-i` makes the matching case-insensitive, `-F` treats the pattern as a fixed string rather than a regex. One caveat worth knowing: date limiting prunes the traversal, so skewed commit dates can cut history off early.
code
bash · 4 linesgit log --oneline --author=jane --since='3 months ago'
git log --grep='PROJ-1234' --all
git log --grep=fix --grep=revert --all-match --oneline
git log --author=jane --grep=timeout -i --no-mergesgo deeper
Know the three flags by name and that they combine: --author, --grep, and --since with --until. Being able to produce a one-week summary for one person is enough at this level.
Explain the semantics — regular-expression matching against header and message, OR between repeated --grep patterns unless --all-match is given, and AND across different filter kinds.
Demonstrate the failure modes: date limiting prunes traversal and can truncate on non-monotonic dates, and author versus committer dates diverge after rebases, which skews any date-based report.
Frame it as querying an audit trail. Decide what history must be answerable — release contents, ownership, ticket traceability — and drive the message and trailer conventions that make those queries reliable.
## The three filter families `git log` filters fall into groups that behave differently when combined, which is the part most candidates get wrong. **By person.** `--author=<pattern>` limits output to commits whose author header line matches the pattern; `--committer=<pattern>` does the same for the committer. Because the match is against the whole header line, which contains both the name and the email in angle brackets, `--author=jane` and `[email protected]` both work. These are regular expressions, not literal strings, so a dot matches any character unless you escape it or pass `-F`. **By message.** `--grep=<pattern>` matches a regular expression against the commit message — subject and body. `--invert-grep` flips it to exclude matching commits. This is how you find, say, every commit mentioning a ticket identifier. **By date.** `--since=<date>` (alias `--after`) and `--until=<date>` (alias `--before`) bound the range. Git's date parser is generous: `--since='2 weeks ago'`, `--since=2024-01-01`, `--since='last monday'` all parse. These compare against the commit date. ## The combination rules Within the message filters, multiple patterns are OR-ed: `--grep=fix --grep=bug` shows commits matching either. `--all-match` changes that to AND, requiring every `--grep` pattern to match. Across different filter kinds, the semantics are AND: `--author=jane --grep=timeout --since='1 month ago'` means all three conditions. Knowing that `--all-match` exists — and that it applies to the grep patterns rather than to the filters generally — is the detail that separates a rehearsed answer from a used-in-anger one. ## Pattern flavour and case By default the patterns are basic regular expressions. `-i` (`--regexp-ignore-case`) makes matching case-insensitive; `-E` (`--extended-regexp`) switches to extended regex; `--perl-regexp` uses PCRE where the build supports it; `-F` (`--fixed-strings`) turns off regex interpretation entirely, which is what you want when searching for something containing punctuation. ## The date-limiting caveat `--since` does not simply filter a full traversal — it prunes it, stopping the walk when it reaches commits older than the cutoff. That is a performance win and normally correct, because history is broadly ordered by date. But commit dates are not guaranteed monotonic: a rebase, an imported patch, or a machine with a wrong clock can produce a commit whose date is older than its parent's. When traversal hits such a commit, it can stop early and hide newer commits behind it. Recent Git provides `--since-as-filter=<date>`, which checks every commit instead of stopping the walk — slower, but complete. If a date-limited log looks suspiciously short, this is the first thing to suspect. ## Author date versus commit date Every commit carries two timestamps. The author date is when the change was originally written; the committer date is when the commit object was created. Rebasing, amending, and cherry-picking preserve the author date but reset the committer date, which is why a rebased branch shows old author dates and fresh committer dates. Date range filtering works on the commit date, while `--pretty` formats can print either — `%ad` for author date, `%cd` for committer date, with `--date=short`, `--date=relative`, or `--date=iso` controlling the rendering. If a date-filtered report surprises you on a rebase-heavy repository, this distinction is usually why. ## Practical shapes Filters combine with the presentation flags freely, so the working commands look like `git log --oneline --author=jane --since='3 months ago'`, or `git log --grep='PROJ-1234' --all` to find a ticket's commits across every branch, or `git log --no-merges --since='1 week ago' --pretty=format:'%h %an %s'` for a standup summary. `-n <count>` caps the output when you only want a sample. ## What is being assessed The flags themselves are cheap. What an interviewer listens for is whether you understand that these are regular expressions, that OR-versus-AND depends on which filters you combined, and that date limiting is a traversal cut rather than a post-filter. Those three points are what turn `git log` from a scroll into a query tool.
- You pass two --grep patterns and get more results than expected. Why?Multiple --grep patterns are OR-ed by default, so a commit matching either one is shown. Add --all-match to require that every pattern matches. Note that --all-match constrains the message patterns only; mixing --author with --grep is already an AND across filter kinds.
- Which timestamp does --since compare against, and why does that matter after a rebase?It compares the commit date. Rebasing, amending and cherry-picking preserve the original author date but rewrite the committer date, so rebased work can look brand new to a date-limited query even though it was written weeks earlier. Print both with %ad and %cd when the distinction matters.
- Your --since query seems to truncate history early. What is happening?Date limiting prunes the traversal rather than filtering a complete walk, so it can stop when it meets a commit whose date is older than the cutoff — which happens with rebased, imported, or bad-clock commits. Recent Git offers --since-as-filter, which examines every commit instead of halting the walk.
- How do you search for a message containing regex metacharacters?Pass -F (--fixed-strings) so the pattern is treated literally instead of as a regular expression, or escape the metacharacters. Combine with -i for case-insensitive matching. Without it, characters like dots, brackets and plus signs silently change what you are matching.
saying these in an interview costs you the question
- Assumes --grep and --author are literal substring matches
- Thinks repeating --grep narrows results rather than widening them
- Believes --since filters on the author date
- Expects --author to require an exact full name
- Never suspects traversal pruning when date-limited output looks short