Git
version control
code analysis
software development
programming tips

How to count total lines changed by a specific author in a Git repository?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Git can tell you how many lines a specific author added and removed across the history of a repository, but the answer depends on what you mean by "changed." The usual approach is to sum git log --numstat output for that author, which gives additions and deletions per file per commit.

The basic command

Use git log filtered by author together with --numstat:

bash
1git log \
2  --author="[email protected]" \
3  --no-merges \
4  --pretty=tformat: \
5  --numstat

This prints lines like:

text
12      3       src/app.py
5       0       README.md

The first column is lines added, the second is lines deleted, and the third is the file path.

Summing the totals

Pipe that output into awk to get totals:

bash
1git log \
2  --author="[email protected]" \
3  --no-merges \
4  --pretty=tformat: \
5  --numstat |
6awk 'NF == 3 && $1 ~ /^[0-9]+$/ && $2 ~ /^[0-9]+$/ {
7  added += $1
8  deleted += $2
9}
10END {
11  printf "added: %d\nremoved: %d\nnet: %d\n", added, deleted, added - deleted
12}'

That is the standard answer for "how many lines changed by this author?" It is simple, reproducible, and works in most repositories.

Narrowing the scope

You can filter further by date, branch, or path.

For a date range:

bash
1git log \
2  --author="[email protected]" \
3  --since="2025-01-01" \
4  --until="2025-12-31" \
5  --no-merges \
6  --pretty=tformat: \
7  --numstat

For a specific directory:

bash
1git log \
2  --author="[email protected]" \
3  --no-merges \
4  --pretty=tformat: \
5  --numstat -- src/

These filters matter because whole-repository totals can be misleading in monorepos or long-lived projects.

What the numbers mean and what they do not

This method counts line additions and deletions in commits authored by the specified person. It does not tell you:

  • who currently owns the surviving lines in the codebase
  • how much of the work was meaningful versus formatting noise
  • who committed the changes if author and committer differ

If you want current ownership rather than historical churn, git blame or specialized tools are closer to the right question.

It is also worth separating author identity from committer identity. In normal feature branch workflows they often match, but rebases, patches applied by maintainers, and bots can make them diverge. Pick the field that matches the question you are trying to answer.

Special cases

Binary files show - instead of numeric counts in --numstat. The awk filter above ignores those lines on purpose.

Merge commits can also distort totals, especially in repositories with noisy merge histories. That is why --no-merges is usually a better default for author contribution summaries.

You should also be careful with author matching. A developer who committed from multiple email addresses may need a broader pattern:

bash
git log --author="Alice Smith"

or multiple separate runs if the identities are inconsistent.

Common Pitfalls

  • Forgetting --pretty=tformat: and then feeding commit headers into awk.
  • Counting merge commits, which can inflate totals or make the numbers harder to interpret.
  • Assuming author totals equal current ownership of code.
  • Ignoring binary files and wondering why the parser breaks on - values.
  • Using an email filter when the same person committed with several different identities.

Summary

  • Use git log --author=... --numstat to list per-file line additions and deletions.
  • Sum the numeric columns with awk to get added, removed, and net totals.
  • Add --no-merges unless you explicitly want merge commit statistics.
  • Filter by date or path when repository-wide totals are too broad.
  • Treat the result as historical churn, not as a definitive measure of code ownership or impact.

Course illustration
Course illustration

All Rights Reserved.