_ _
_ ( )_ ( )_
__ (_)| ,_) _ __ __ _ _ _ _ __ | ,_)
/'_ `\| || | ( '__)/'__`\( '_`\ /'_`\ ( '__)| |
( (_) || || |_ | | ( ___/| (_) )( (_) )| | | |_
`\__ |(_)`\__) (_) `\____)| ,__/'`\___/'(_) `\__)
( )_) | | |
\___/' (_)
One command,
git report, tells you who wrote the code in any Git repository.
git-author-report analyzes a repository and prints a per-author breakdown of how much
code each contributor wrote: surviving lines, lifetime additions and deletions,
commit counts, and files touched, all in a clean ASCII table. It runs on whatever
Ruby is already on your machine (including the stock macOS system Ruby), needs no
Bundler, and has no runtime gem dependencies, so it never touches your global
gems.
+-----------------+-----+---------+-------+------+------+
| Name | LOC | Commits | files | +LOC | -LOC |
+-----------------+-----+---------+-------+------+------+
| John Doe | 258 | 15 | 12 | 390 | 123 |
| Jane Smith | 87 | 8 | 5 | 125 | 38 |
+-----------------+-----+---------+-------+------+------+
- Why git-author-report?
- Quick Start
- Understanding the Output
- Features
- Requirements
- Installation
- How It Works
- Compatibility
- Troubleshooting
- Development
- Uninstallation
- License
git shortlog tells you who committed and how often, but commit counts are a
poor proxy for contribution. git-author-report answers the questions that actually
matter:
- Who owns the code that exists today? The
LOCcolumn counts the lines each author wrote that still survive in the current tree (viagit blame), not just what they once added. - Who has done the most work over time? The
+LOC/-LOCcolumns sum every line added and removed across the project's history. - How is effort spread across the team? Commits and files-touched fill in the rest, all in one table with zero configuration.
gem install git-author-report # also registers a global `git report` alias
cd /path/to/any/repo
git report # print the contributor table
git report --version # print the version and exitgit report takes no other arguments; it always reports on the repository in
the current directory. Nothing else needs installing, since git-author-report has no
runtime gem dependencies and runs straight off the stock system Ruby.
Each row is one contributor (authors with multiple email addresses but the same name are merged into a single row). The columns:
💡 LOC vs. +LOC:
LOCmeasures what remains today;+LOCmeasures everything ever written. A contributor whose code was later refactored away can have a high+LOCbut a lowLOC.
Rows are sorted by surviving LOC (descending), and contributors with no
measurable contribution are omitted. Untracked and uncommitted files are
ignored, so the report reflects committed history only.
- 📊 Per-author commit, line, and file statistics in one table
- 🧬 Distinguishes surviving code (
LOC) from lifetime additions/deletions (+LOC/-LOC) - 🔀 Merges contributors who used multiple email addresses
- 🚀 Parallel processing (plain Ruby threads) for fast analysis of large repositories
- 🌐 Global
git reportcommand that works in any repository - 🧰 Zero runtime dependencies: pure Ruby standard library, nothing to install
- 💎 Runs on Ruby 2.6 through 4.0+, including the stock macOS system Ruby
- Git (any recent version)
- Ruby 2.6 or higher (the macOS system Ruby is fine)
- RubyGems (bundled with Ruby)
gem install git-author-reportInstalling the gem also registers a global Git alias so you can run git report
from any repository on your machine. (Because the executable is named
git-report, Git also resolves git report natively once the gem's bin
directory is on your PATH.)
git clone https://github.com/wteuber/git-author-report.git
cd git-author-report
./bin/git_add_alias_reportThis registers the same global git report alias without installing the gem.
If you'd rather wire up the alias yourself:
git config --global alias.report "!exec \"/path/to/git-author-report/bin/git-report\""None at runtime. git-author-report uses only the Ruby standard library, with
parallelism built on plain Thread (see lib/git/parallel.rb),
so there is no gem to install, no Bundler, and no version conflicts. It runs
directly on whatever Ruby is on your PATH, including the stock macOS system
Ruby.
- Git analysis. Gathers contributor data with
git shortlog(commits),git blame -w(surviving lines and files), andgit log --numstat(lifetime additions/deletions). - Parallel processing. Uses plain Ruby threads to fan blame and log work out across files and authors, keeping large repositories fast. The git subprocesses are I/O-bound and release the GVL, so threads give real concurrency without any gem.
- Author deduplication. Merges authors who committed under the same name with different email addresses into a single row.
- No runtime dependencies. Relies only on the Ruby standard library, so it
runs on whatever Ruby is on your
PATHwith nothing to install.
git-author-report is designed to run anywhere Git and Ruby already exist:
- ✅ Ruby 2.6 (support floor) through 4.0+, all verified in CI
- ✅ Runs on the stock macOS system Ruby, so end users need no Ruby install
- ✅ Works with system Ruby or version managers (rbenv, rvm, chruby)
- ✅ No runtime gems to install, so no permission or version conflicts
The Ruby version floor is enforced by RuboCop (TargetRubyVersion: 2.6) and a CI
matrix that runs against 2.6, a recent 3.x, and the latest Ruby (4.0). The
.ruby-version file (4.0.4) only selects a comfortable Ruby for local
development; it does not narrow the supported range.
Permission errors installing gems. git-author-report has no runtime
dependencies, so the only gem involved is git-author-report itself. If gem install
needs elevated permissions, install into your user gem dir
(gem install --user-install git-author-report) or use a version manager.
Ruby version issues. The .ruby-version file selects Ruby 4.0.4 for local
development, but the tool supports any Ruby from 2.6 up and does not use Bundler
at runtime, so Bundler version conflicts cannot affect it.
"Not a git repository". Run git report from inside a Git working tree;
the tool reports on the repository in the current directory.
git-author-report/
├── bin/
│ ├── git-report # Main executable
│ ├── git_add_alias_report # Registers the `git report` alias
│ └── git_remove_alias_report # Removes the `git report` alias
├── ext/git_report/
│ ├── extconf.rb # Install-time hook that adds the alias
│ └── Makefile # No-op (keeps RubyGems happy)
├── lib/
│ ├── git_report.rb # Entry point (loads the Git:: classes)
│ ├── version.rb # Gem version (reads VERSION)
│ ├── rubygems_plugin.rb # Removes the alias on `gem uninstall`
│ └── git/
│ ├── author.rb # Author statistics class
│ ├── parallel.rb # Thread-based parallel map/each helpers
│ └── report.rb # Report generation class
├── test/ # minitest suite (smoke + unit tests)
├── git-author-report.gemspec # Gem specification
├── VERSION # Single source of truth for the version
├── Rakefile # `rake` runs tests + RuboCop
├── .github/workflows/
│ └── ci.yml # CI: tests (Ruby 2.6 + 3.4 + 4.0) and RuboCop
├── .rubocop.yml # Lint config; enforces the Ruby 2.6 syntax floor
├── Gemfile # Declares the Ruby floor (dev deps only)
├── .ruby-version # Ruby for local development (does not narrow support)
└── README.md # This file
The minitest suite drives the real executable against throwaway Git repositories. It uses only minitest (a Ruby default gem):
ruby test/smoke_test.rb # the end-to-end smoke test
# or run everything plus RuboCop:
bundle install
bundle exec rakeCI runs the suite on Ruby 2.6, 3.4, and 4.0, plus RuboCop for 2.6 compatibility.
Contributions are welcome!
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Make your change and keep the tests green (
bundle exec rake) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
If you installed the gem:
gem uninstall git-author-report # also removes the global `git report` aliasIf you installed from a clone:
cd /path/to/git-author-report
./bin/git_remove_alias_reportReleased under the MIT License.
