Cumulative Git User Statistics
Git provides a log
function with numerous options for viewing and filtering repository data. But it gives no simple way to print a report of cumulative changes per-file.
The following code is a short C++ script to parse the output of git log --numstat --pretty="%n"
, sum the insertions and deletions for each file, and print a summary. It was written in heed of this advice .
If this seems useful to you, check out my code below, or grab the gist .
/*
This is a command-line program to sum up and print all
line insertions and deletions listed by the statistical
git log command. Where "accum" is the compiled program,
it can be used with a "|" as follows:
git log --numstat --pretty="%n" | accum
Git log results may be filtered by a number of parameters.
Notably, the --author="..." and --since="../../...." can be
used to count all insertions and deletions by a specific
author within a range of time. More here:
https://git-scm.com/docs/git-log.
02-29-2015: Thus far it has only been tested on Cygwin,
built with g++, with the -std=c++0x flag.
*/
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <utility>
#include <iomanip>
int main ( int argc , char ** argv ) {
int max_empty_lines = 15 ;
int num_empty_lines = 0 ;
std :: map < std :: string , std :: pair < int , int > > changes ;
do {
// Grab the next line
std :: string line ;
std :: getline ( std :: cin , line );
// If it's empty, increment the empty counter and skip to the next iteration
if ( line . empty ()) {
num_empty_lines ++ ;
continue ;
} else {
num_empty_lines = 0 ;
}
// Turn the line into a stream
std :: stringstream stream ( line );
// Get this chunk of the report
int insertions ;
int removals ;
std :: string file ;
while (
( stream >> insertions ) &&
( stream >> removals ) &&
( stream >> file )) {
// Make an empty entry for this file if there isn't one already
if ( changes . find ( file ) == changes . end ())
changes [ file ] = std :: pair < int , int > ( 0 , 0 );
// Save this insertion/removal count pair in the map
changes [ file ]. first += insertions ;
changes [ file ]. second += removals ;
};
} while ( num_empty_lines < max_empty_lines );
// Print the final report
int total_insertions = 0 ;
int total_deletions = 0 ;
for ( auto change : changes ) {
std :: cout << std :: left << std :: setw ( 60 ) << change . first << "+" << std :: setw ( 5 ) << change . second . first << "-" << std :: setw ( 5 ) << change . second . second << " \n " ;
total_insertions += change . second . first ;
total_deletions += change . second . second ;
}
std :: cout << " \n " ;
std :: cout << "Total Insertions: " << total_insertions << " \n " ;
std :: cout << "Total Deletions: " << total_deletions << " \n " ;
}