Git Blame Commit Statistics

git ls-tree -r HEAD|sed -re 's/^.{53}//'|while read filename; do file "$filename"; done|grep -E ': .*text'|sed -r -e 's/: .*//'|while read filename; do git blame -w "$filename"; done|sed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'|sort|uniq -c

Step by step explanation:

List all the files under version control

git ls-tree -r HEAD|sed -re 's/^.{53}//'

Prune the list down to only text files

|while read filename; do file "$filename"; done|grep -E ': .*text'|sed -r -e 's/: .*//'

Git blame all the text files, ignoring whitespace changes

|while read filename; do git blame -w "$filename"; done

Pull out the author names

|sed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'

Sort the list of authors, and have uniq count the number of consecutively repeating lines

|sort|uniq -c

Example output:

   1334 Maneater
   1924 Another guy
  37195 Brian Ruby
   1482 Anna Lambda

Update

git ls-tree -r -z --name-only HEAD -- */*.c  | sed 's/^/.\//' | xargs -0 -n1 git blame \
--line-porcelain HEAD |grep -ae "^author "|sort|uniq -c|sort -nr

I updated some things on the way.

For convenience, you can also put this into its own command:

#!/bin/bash

# save as i.e.: git-authors and set the executable flag
git ls-tree -r -z --name-only HEAD -- $1 | sed 's/^/.\//' | xargs -0 -n1 git blame \
 --line-porcelain HEAD |grep -ae "^author "|sort|uniq -c|sort -nr

store this somewhere in your path or modify your path and use it like

  • git authors '*/*.c' # look for all files recursively ending in .c
  • git authors '*/*.[ch]' # look for all files recursively ending in .c or .h
  • git authors 'Makefile' # just count lines of authors in the Makefile

Original Answer

While the accepted answer does the job it's very slow.

$ git ls-tree --name-only -z -r HEAD|egrep -z -Z -E '\.(cc|h|cpp|hpp|c|txt)$' \
  |xargs -0 -n1 git blame --line-porcelain|grep "^author "|sort|uniq -c|sort -nr

is almost instantaneous.

To get a list of files currently tracked you can use

git ls-tree --name-only -r HEAD

This solution avoids calling file to determine the filetype and uses grep to match the wanted extension for performance reasons. If all files should be included, just remove this from the line.

grep -E '\.(cc|h|cpp|hpp|c)$' # for C/C++ files
grep -E '\.py$'               # for Python files

if the files can contain spaces, which are bad for shells you can use:

git ls-tree -z --name-only -r HEAD | egrep -Z -z '\.py'|xargs -0 ... # passes newlines as '\0'

Give a list of files (through a pipe) one can use xargs to call a command and distribute the arguments. Commands that allow multiple files to be processed obmit the -n1. In this case we call git blame --line-porcelain and for every call we use exactly 1 argument.

xargs -n1 git blame --line-porcelain

We then filter the output for occurences of "author " sort the list and count duplicate lines by:

grep "^author "|sort|uniq -c|sort -nr

Note

Other answers actually filter out lines that contain only whitespaces.

grep -Pzo "author [^\n]*\n([^\n]*\n){10}[\w]*[^\w]"|grep "author "

The command above will print authors of lines containing at least one non-whitespace character. You can also use match \w*[^\w#] which will also exclude lines where the first non-whitespace character isn't a # (comment in many scripting languages).


I wrote a gem called git-fame that might be useful.

Installation and usage:

  1. $ gem install git_fame
  2. $ cd /path/to/gitdir
  3. $ git fame

Output:

Statistics based on master
Active files: 21
Active lines: 967
Total commits: 109

Note: Files matching MIME type image, binary has been ignored

+----------------+-----+---------+-------+---------------------+
| name           | loc | commits | files | distribution (%)    |
+----------------+-----+---------+-------+---------------------+
| Linus Oleander | 914 | 106     | 21    | 94.5 / 97.2 / 100.0 |
| f1yegor        | 47  | 2       | 7     |  4.9 /  1.8 / 33.3  |
| David Selassie | 6   | 1       | 2     |  0.6 /  0.9 /  9.5  |
+----------------+-----+---------+-------+---------------------+

Tags:

Git