git log --author="Name". It is a regular expression matched against the whole Name <email> string, so partial names work and --author="^Name$" matches nothing.
Finding one person’s commits is a common enough job: reviewing a colleague’s work, working out who touched something, or counting contributions. git log --author does it, with one behaviour that catches people out.
Filtering By Author
git log --author="Sam" git log --author="Sam" --oneline
That returns every commit whose author matches. The match is partial by default, so --author="Sam" also matches “Samantha” and “Sam Taylor”.
It Is A Regex, And It Matches More Than The Name
This is the part worth knowing, because it makes an obvious-looking command silently return nothing.
--author is matched against the author as Git stores it, which is the name and the email together in one string:
Sam Taylor <sam.taylor@example.com>
$ returns zero commits. git log --author="^Sam Taylor$" looks like it should match exactly, and it matches nothing at all, because the string does not end after the name. Tested on a repository with 777 commits by one author: --author="^Name$" returned 0, while --author="^Name <" returned all 777.So anchor at the start and stop before the email, or match on the email instead:
git log --author="^Sam Taylor <" # exact name, anchored properly git log --author="@example.com" # everyone from one organisation git log -i --author="sam" # case-insensitive
-i makes the match case-insensitive. Order does not matter: -i --author="sam" and --author="sam" -i both work.
Counting Commits Per Person
For a quick tally, do not loop over git log. There is a built-in:
git shortlog -sn git shortlog -sn --all # include every branch
412 Sam Taylor
238 R. Maintainer
77 A. Developer
-s summarises to counts only and -n sorts by number of commits. Without them you get the full list of commit subjects grouped by author, which is also useful for writing release notes.
Combining With Other Filters
git log --author="Sam" --since="1 month ago" --oneline git log --author="Sam" --oneline -- src/reports/ # one directory git log --author="Sam" --grep="fix" -i --oneline # their fixes only
For the one-line format itself and the alias worth saving, see git log one line.
Author Versus Committer
Git records two people per commit. The author wrote the change, the committer applied it. They differ after a rebase, a cherry-pick, or when someone applies a patch on your behalf. --author filters the first, --committer the second, and if a search comes back empty when you are certain the person worked on something, try the other one.
If SQL Server is part of your day job, my current work lives over at sqldba.blog: production DBA scripts, an error library and the SSMS guide.
It Returned Nothing and the Person Definitely Exists
Two causes, and neither of them produces an error. You get an empty result and no reason for it.
Alternation does not work in the default regex flavour. --author uses basic regular expressions unless you say otherwise, and in that mode | is a literal pipe character rather than an “or”. So the obvious way to search for two people silently matches nobody. Tested on git 2.54.0:
# returns 0 commits, with no error git log --author='Sam Taylor|Ann Other' # returns them, because -E turns on extended regex git log -E --author='Sam Taylor|Ann Other'
This is the same shape of trap as the anchoring one further up the page. The command looks correct, exits cleanly, and is quietly answering a different question.
Or you are looking at the wrong part of history. git log walks back from HEAD, so commits sitting on a branch that has never been merged are simply not in scope. Somebody who has worked only on an unmerged feature branch shows zero commits, which reads exactly like “this person has not contributed”:
# 0 commits, because their branch is not merged git log --author='Branch Person' --oneline # 1 commit, because --all covers every ref git log --all --author='Branch Person' --oneline
If you are auditing rather than browsing, use --all. Both of those results are from the same repository, seconds apart.
Asking About Several People at Once
You do not need the regex for this. Repeating --author ORs the filters, which is usually what you meant and is far easier to read:
git log --author='Sam Taylor' --author='Ann Other' --oneline
Worth knowing it is an OR and not an AND, in case you were hoping to narrow rather than widen. There is no combination of --author flags that means “commits by both of these people”, because a commit only has one author.
One Person, Several Identities
This is the one that quietly ruins counts. A single person routinely commits under a work email, a personal email, and GitHub’s 12345+user@users.noreply.github.com address, which gets applied to squash merges when they have email privacy switched on. Filtering by name misses some of those. Filtering by email misses others.
The fix is a .mailmap file at the root of the repository, mapping the stray identities onto one canonical one:
# .mailmap Sam Taylor <sam@example.com> <sam.taylor@oldjob.com> Sam Taylor <sam@example.com> <12345+sam@users.noreply.github.com>
The catch is that git log and git shortlog do not treat that file the same way. Tested on 2.54.0 with the mapping above in place: git shortlog -sn collapsed both identities into one person automatically, while git log --format='%an' still listed both names. So the tally and the raw log disagree about the same human being, and neither is wrong.
Two ways to make the log agree with the tally:
# %aN, capital N, is the mailmap-aware placeholder git log --format='%aN' # --use-mailmap also makes --author match the mapped identities git log --use-mailmap --author='Sam Taylor' --oneline
That second one matters more than it looks: with the mapping in place it returned the old-identity commits too, which is exactly what you want when somebody changed employer halfway through a project.
Two Things That Bite Inside Scripts
git shortlog with no revision range reads standard input. Interactively you will see it sit there doing nothing. In a scheduled job with stdin closed it is worse than that: it returns successfully with no output at all, so your report is empty and the exit code says everything went fine. Tested on 2.54.0, and I managed to hang a terminal on it while writing this section. Always give it something to walk:
# hangs, or returns nothing at all git shortlog -sn # does what you meant git shortlog -sn HEAD git shortlog -sn --all
Counting with -sn includes merge commits. On a repository that takes pull requests this inflates whoever does the merging, because every PR they merged counts as one of their commits. If you are counting contribution rather than activity, exclude them:
git shortlog -sn --no-merges --all
And the small one that catches everybody once: git pipes output through a pager, so a git log in a script can stall waiting for a reader that does not exist. git --no-pager log ... removes the problem.
Leave a Reply