Skip to content

Git Log Parser

The Git Log Parser turns the history of a git repository into metrics per file: how often it changed, how many people changed it, how old it is and which files change together with it. Merged with code metrics, that shows you the hotspots: complex files that change all the time.

The parser follows a file across renames, also on feature branches before they are merged, so renamed files show up once, under their current name. A deletion that is reverted later is ignored.

Terminal window
ccsh gitlogparser repo-scan --repo-path path/to/repository -o history.cc.json

This writes history.cc.json.gz. ccsh analyse runs the same scan for you and merges it with the code metrics.

The parser has two commands: repo-scan reads the history of a local repository itself, log-scan reads a git log and a file list you created.

ParametersDescription
log-scanuse log-scan mode - generates cc.json from a given git-log file
repo-scanuse repo-scan mode - generates cc.json from an automatically generated git-log file
--add-authoradd an array of authors to every file
--commit=<ref>analyze the repository at a specific git commit, tag, branch, or date expression (creates a temporary worktree, repo-scan only). See Commit-Based Analysis
--git-log=FILEgit-log file to parse (log-scan only, required)
-h, --helpdisplays help and exits
-nc, --not-compressedsave uncompressed output File
-o, --output-file=<outputFilePath>output File (or empty for stdout)
--repo-files=FILElist of all file names in current git project (log-scan only, required)
--repo-path=DIRECTORYroot directory of the repository (repo-scan only; the scan fails without it)
--silentsuppress command line output during process
Usage for log-scan mode:
ccsh gitlogparser log-scan [-h] [--add-author] [-nc] [--silent]
--git-log=FILE [-o=<outputFilePath>]
--repo-files=FILE
Usage for repo-scan mode:
ccsh gitlogparser repo-scan [-h] [--add-author] [--commit=<ref>] [-nc]
[--silent] [-o=<outputFilePath>]
--repo-path=DIRECTORY
MetricDescription
age_in_weeksThe file’s age measured in weeks since creation.
number_of_authorsThe count of distinct authors (including co-authors) who have contributed commits.
number_of_commitsThe total commits made to the file.
number_of_renamesHow many times the file has been renamed.
range_of_weeks_with_commitsThe span of weeks during which commits were made.
successive_weeks_with_commitsConsecutive weeks during which the file received commits.
weeks_with_commitsThe number of weeks in which the file was modified.
highly_coupled_filesFiles often modified together with this file (35% overlap or more).
median_coupled_filesThe median number of files modified in tandem with this file.
feat_commitsNumber of commits starting with ‘feat’ for this file.
fix_commitsNumber of commits starting with ‘fix’ for this file.
docs_commitsNumber of commits starting with ‘docs’ for this file.
style_commitsNumber of commits starting with ‘style’ for this file.
refactor_commitsNumber of commits starting with ‘refactor’ for this file.
test_commitsNumber of commits starting with ‘test’ for this file.
hotfix_commitsNumber of commits containing the word ‘hotfix’ for this file.
hotfix_commit_ratioRatio of hotfix commits (containing the ‘hotfix’ keyword) to total commits for this file.
semantic_commit_ratioRatio of semantic commits (which start with feat, fix, docs, style, refactor or test) to total commits for this file.

The parser also writes one edge metric between files:

MetricDescription
temporal_couplingThe degree of temporal coupling between two files (>=35%)

With --add-author, every file also gets the list of its authors’ names.

repo-scan writes a git log and the list of tracked files of the repository at --repo-path into your temp folder and parses them. Point --repo-path at the root of the repository.

log-scan parses a git log and a file list you created, for example on another machine or with anonymized authors. Create both in the root folder of the repository:

Terminal window
cd path/to/repository
git -c core.quotepath=off log --numstat --raw --topo-order --reverse -m > git.log
git -c core.quotepath=off ls-files > file-name-list.txt
ccsh gitlogparser log-scan --git-log git.log --repo-files file-name-list.txt -o history.cc.json

-c core.quotepath=off keeps file names with non-ASCII characters unquoted. Use it for both commands, so the log and the file list spell such a name the same way.

The log has to be in this format:

SCMLog formatCommand for log creationtracks renamesignores deleted filessupports code churn
gitGIT_LOG_NUMSTAT_RAW_REVERSEDgit -c core.quotepath=off log --numstat --raw --topo-order --reverse -myesyesno

To hide the authors, create the log with the anongit script instead (anongit > git.log). It replaces every author with anon1, anon2 and so on, and keeps the mapping in hashmap.authors in the current folder.

Both commands merge a project piped into them with their result, and the merged project keeps the project name of the Git Log Parser:

Terminal window
ccsh unifiedparser path/to/repository | ccsh gitlogparser repo-scan --repo-path path/to/repository -o project.cc.json