代码统计一般是对某一个或者多个代码仓库的开发人员在某段时间内或所有历史时间段内进行代码提交次数、代码提交行数等进行统计,以反映人员对代码仓库的贡献量的一种手段。
通过 git 进行代码管理的项目,通常使用 git log 命令的输出进行统计。

git log

可以使用 git --help log 查看 git log 的完整用法。

git log 常见参数说明:

不带参数

列出所有的历史记录,最近的排在最上方,显示提交对象的哈希字符串、作者、修订日期和提交说明。
如果记录过多,可以按照 Page Up/Page Down 键来控制滑动翻阅,按 q 键可以退出。

shortcut_inner

显示参数

-p 展开每次提交的内容差异
--stat 显示每次更新的文件修改统计信息,列出具体的文件列表
--shortstat 统计每个 commit 的文件修改行数,包括增加、删除,但不列出文件列表
--numstat 统计每个 commit 的文件修改行数,包括增加、删除,并列出文件列表
--name-only 仅在提交信息后显示已修改的文件清单
--name-status 显示新增、删除、修改的文件清单
--abbrev-commit commit 显示为短 id 形式,仅展示前7个字符
--relative-date 使用相对较短的时间显示(例如,显示为“2 weeks ago”)
--graph 显示 ASCII 图形表示的分支合并历史
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline short medium full fuller email rawformat:<string>,例如:git --pretty=format: 可以定制要显示的记录格式,这样输出便于后期提取分析
例如 git log --pretty-format: "%h - %an, %ar : %s 显示为:

shortcut_inner

下面列出了常用的格式占位符的写法及其代表的意义:

选项 说明
%H 提交对象(commit)的完整哈希字符串
%h 提交对象的简短哈希字符串
%T 树对象(tree)的完整哈希字符串
%t 树对象的简短哈希字符串
%P 父对象(parent)的完整哈希字符串
%p 父对象的简短哈希字符串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期,可以用 -date= 选项定制日期格式
%ar 作者修订日期,按照多久之前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按照多久之前的方式显示
%s 提交说明

format 参数支持通过以 %C 开头来控制显示的颜色和字体,例如: git log --pretty=format:"%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>" 显示为:

shortcut_inner

筛选参数

按数量:
-{n} 仅展示最近 n 次 commit 的更新, 例如 git log -2 显示最近2次的 commit 。
按作者:
--author 指定作者,不需要精确匹配,只需要包含即可。可以使用正则表达式。包含电子邮箱的匹配。
按日期:
--after= 标志指定日期之后,同 --until
--before= 标志指定日期之前,同 --since
按 commit 描述:
--grep=<string> 可以传入 -i 忽略大小写。同时使用 --author--grep 时,必须附加 --all-match 来表示全匹配
按文件:
-- <filepath> 例如 git log -- ./src/utils/ 只展示 ./src/utils/ 路径下的变更
按分支:
<branchname> 例如 git log origin/master
按范围:
<since>...<until> 例如 git log master...feature 展示 feature 分支到 master 分支的变化,包含了所有在 feautre 分支但不在 master 分支的 commit
过滤掉 merge commit
--no-merges 过滤掉 merge commit
按标签tag:
<tagname> 例如 git log v1.0 查询标签 v1.0 之前的 commit,git log v1.0.. 查询标签 v1.0 之后的 commit
按 commit:
<commit> 查看 commit 之前的记录,包括 commit
<commit1> <commit2> 查看 commit1 与 commit2 之间的记录,不包括 commit1
<commit1>...<commit2> 查看 commit1 与 commit2 之间的记录,包括 commit1
commit 表示一次提交的哈希字符串或简短哈希字符串,HEAD 表示最后一次提交,HEAD^ 表示最后一次提交的父提交,相当于 HEAD~1,也就是倒数第二次的提交,HEAD~2 表示倒数第三次提交

常用命令

统计代码行数

根据用户名统计每个作者的增删代码行数

1
2
3
4
git log --format='%an' | sort -u | while read name; 
do echo -en "$name\t";
git log --author="$name" --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -;
done

根据电子邮箱统计每个作者的增删代码行数

1
2
3
4
git log --format='%an' | sort -u | while read name;
do echo -en "$name\t";
git log --author="$name" --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -;
done

根据用户名统计每个作者在 startTimeendTime 时间之内的增删代码行数(可以统计最近半年、最近一年的数据)

1
2
3
4
git log  --format='%an' | sort -u | while read name;
do echo -en "$name\t";
git log --author="$name" --since=${startTime} --until=${endTime} --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -;
done

查看总共的代码增删行数

1
git log --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

查看作者用户名为 username 总共的代码增删行数

1
git log --author="${username}" --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

统计提交次数

查看所有作者用户名数量

1
git log --pretty='%an' | sort -u | wc -l

查看总提交次数统计

1
git log --oneline | wc -l

查看作者所有提交次数排名

1
git log --pretty='%an' | sort | uniq -c | sort -k1 -n -r

根据电子邮箱查看作者所有提交次数排名

1
git log --pretty='%ae' | sort | uniq -c | sort -k1 -n -r

查看仓库提交次数排名前5

1
git log --pretty='%an' | sort | uniq -c | sort -k1 -n -r | head -n 5

查看用户 usernamestartTime 时间开始的提交(不包含 merge commit)

1
git log --author=${username} --since="${startTime}" --no-merges | grep -e 'commit [a-zA-Z0-9]*'