又到了季度汇报或者项目复盘的时候,办公室里总会冒出类似的问题:"这个月咱们团队每个人提交了多少行代码?"我自己在 IDEA 里写了十多年 Java,遇到过很多次类似需求——给管理者做人力投入分析、给项目整理贡献度数据、或者单纯想看看自己最近半年到底写了多少代码。如果你也想在 IDEA 里统计 Git 提交的代码行数并排出名次,这篇文章就是给你准备的。我会从最实用的方案讲起,把命令、参数、踩坑点一次说清楚,保证你复制过去就能用。
1. 为什么需要统计提交代码行数:场景与方案选型
1.1 三个最常见的实际场景
第一个场景是管理汇报。不少团队在月底、季度末会需要一份"谁写了多少代码"的数据,虽然行数不能完全代表产出质量,但在跨部门汇报、人力预算沟通时,这个数字往往是管理层最容易理解的信号。第二个场景是项目复盘。项目结束后统计各个模块的代码量,能够直观看到人力投入的分布,后续接手代码的人也能快速判断"这块代码该去问谁"。第三个场景是我自己用得最多的——个人提交习惯分析。我有一段时间发现每周五提交特别多,周中却很安静,用行数统计拉出来一看,果然是习惯性攒代码然后一次性提交。这种数据对调整开发节奏很有帮助。
1.2 两条技术路线:IDEA 自带功能还是命令行
先说结论:统计单次提交的变更行数,IDEA 自带的 Git 集成完全够用;但要统计"某个人在一段时间内累计提交了多少行"甚至排出全员名次,IDE 界面操作非常吃力,效率远不如命令行加脚本。
我整理了一个对比表格,方便你快速决策:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| IDEA 自带 Git 集成 | 界面友好,查看单次提交非常直观 | 没有累计汇总和排名能力,需要人工加总 | 临时查看某一次提交改了多少 |
| Git 命令行 + awk/sort 脚本 | 一次命令出结果,可复用,支持过滤和排序 | 命令有学习成本,Windows 环境需要额外配置 | 团队全员排名、周期统计、自动化报告 |
| 第三方插件 | 安装简单 | 插件五花八门,真正专注"提交行数排名"的很少 | 日常辅助,比如看当前行为谁所写 |
1.3 我的最终推荐
我自己的做法是:日常开发用 IDEA 看提交历史没问题,但只要是"统计、排名、汇总"这类需求,一律打开终端跑命令。把常用统计脚本放到项目根目录的scripts文件夹里,月底跑一下,改个时间区间就能出报告,比手动切换 IDEA 界面快一个数量级。
提示:无论用哪种方式,统计命令都是只读操作,不会改动代码仓库,可以放心反复执行。
2. 核心原理拆解:Git 提交记录里藏着哪些数据
2.1 git log 的几种输出形态
要统计行数,首先要理解git log能输出什么。常见的输出形态有四种:
git log --oneline:只显示提交哈希和标题,适合快速浏览历史。git log --shortstat:每个提交后面跟一行汇总,比如1 file changed, 10 insertions(+), 5 deletions(-),人眼可读但不好做脚本累加。git log --numstat:纯数字输出,每行格式是新增行数、删除行数、文件路径,用 tab 分隔,这是做统计的黄金格式。git log --stat:在--shortstat基础上增加文件列表和改动比例条,信息丰富但解析麻烦。
我的经验是:统计任务一律用--numstat,因为它结构干净、字段固定,脚本处理起来最省事。
2.2 四个关键过滤参数
git log自带一套强大的过滤参数,统计排名就是靠它们把范围圈定准确的:
| 参数 | 作用 | 示例 |
|---|---|---|
--author="名字" | 按作者过滤,支持模糊匹配 | --author="Zhang" |
--since | 起始时间 | --since="2024-01-01" |
--until | 截止时间 | --until="2025-01-01" |
--no-merges | 排除合并提交 | 防止 merge 提交干扰统计 |
--author实际匹配的是提交者名字和邮箱,所以哪怕代码里登记的姓名不完整,用邮箱关键字也能过滤到人。时间参数配合使用的效果是左闭右开:--since="2024-01-01" --until="2025-01-01"表示统计 2024 年全年,简单直观。
2.3 统计行数的三种口径
行数统计必须明确口径,否则数字会骗人。我常用的三种口径是:
- 新增行数:所有新增的代码行,包含空行和注释。这个数字偏大,容易给人"写了很多"的错觉。
- 删除行数:被删掉的行。重构、清理死代码时这个数字会暴涨。
- 净增行数:新增减去删除。这个数字更能反映有效产出,推荐作为排名依据。
举个例子:一次提交里删了 200 行老代码、加了 50 行新代码,新增行数是 50,净增行数是 -150。如果只看新增行数,会觉得这个人工作量不大;但结合提交信息看,可能是他做了一次成功的架构精简。所以行数数据一定要结合上下文解读,不能只看表面数字。
2.4 为什么推荐 --numstat 而不是 --stat
--stat输出的条形比例图(带+和-符号)是给人看的,不是给脚本算的。--numstat则非常干净:每行三个字段,tab 分隔,直接喂给 awk 做累加即可。
需要注意一个小坑:当遇到二进制文件时,--numstat会在新增和删除列输出两个-而不是数字。awk 做算术运算时会把-自动转成 0,所以一般情况下不会报错,但心里要明白这个行为,避免统计数据里出现奇怪的偏差。
3. 实操:用 IDEA 自带功能快速查看提交量
3.1 打开 Version Control 面板
IDEA 底部的工具窗口里有 Version Control(老版本叫 Git,新版本统一叫 Version Control),快捷键是 Windows 和 Linux 下的Alt+9,macOS 下的Cmd+9。打开后默认停留在 Log 标签页,这里能看到当前分支的所有提交历史,每一行包含提交哈希、作者、时间、提交说明。
3.2 按作者与日期过滤
Log 标签页顶部有搜索框,输入user:张三可以只显示张三的提交;输入日期范围如since:2024-01-01 until:2025-01-01可以按时间过滤。这两个条件可以组合使用,能够快速把目标提交范围缩小。
3.3 单次提交的变更行数
点击任意一条提交记录,右侧会显示这次提交涉及的文件列表。选中某个文件,可以看到详细的 diff 内容,IDEA 会在编辑区顶部标注类似+12, -5的行数变化。如果要看单次提交的总变化量,选中提交后查看右侧上方的汇总信息,或者直接看编辑器里 diff 统计。
3.4 IDEA 自带功能的局限
IDEA 有个很尴尬的地方:它能清楚地告诉你"这次提交改了 30 行",但没法一键告诉你"张三这个月累计改了 8500 行,团队排名第二"。每条提交的+xx -xx数字需要你自己记录、自己加总,提交一多根本算不过来。所以我的结论是:IDEA 自带的 Git 功能适合"查一次具体提交",不适合"做一段时间的排名汇总"。真要做排名,还是得上命令行。
4. 实操:用 Git 命令行一键生成排名报告
4.1 准备工作:让 IDEA 终端能用上 Linux 命令
统计命令依赖awk、sort,这在 Windows 自带的cmd里是不存在的。推荐两个解决途径:
第一种是使用 Git 自带的 Git Bash。安装 Git for Windows 后在 IDEA 里打开Settings -> Tools -> Terminal,把 Shell path 设置为 Git Bash 的可执行文件路径,比如C:\Program Files\Git\bin\bash.exe。设置完成后,IDEA 底部 Terminal 窗口就变成了 Bash 环境,awk、sort这些命令全都能用。
第二种是使用 WSL,适合习惯在 Linux 环境工作的人,但对大部分 Java 开发来说有点重。我更推荐第一种,几秒钟就能配置好,之后一劳永逸。
4.2 统计某个人的累计提交行数
打开 Terminal,进入项目目录,执行下面的命令:
git log --author="张三" --since="2024-01-01" --until="2025-01-01" --pretty=tformat: --numstat --no-merges | awk '{ add += $1; del += $2 } END { printf "新增:%d 删除:%d 净增:%d\n", add, del, add - del }'拆解一下这个命令:--author指定作者,--since和--until限定时间范围,--pretty=tformat:把提交信息隐藏掉,--numstat输出纯数字行,--no-merges排除合并提交。管道后面的awk逐行累加第一列(新增)和第二列(删除),最后输出结果。
如果你想统计所有人的排名,把这句命令中的--author="张三"去掉,然后把--author改成按邮箱过滤,再换一个累加逻辑即可。
4.3 统计全员提交行数排名
下面这条命令是核心,推荐直接复制到脚本里使用:
git log --since="2024-01-01" --until="2025-01-01" --pretty=format:"%ae" --numstat --no-merges | awk -F'\t' ' NF == 1 { author = $0; next } NF == 3 { add[author] += $1; del[author] += $2 } END { for (name in add) printf "%s\t%d\t%d\t%d\n", name, add[name], del[name], add[name] - del[name] } ' | sort -k2 -nr这里有个关键设计:--pretty=format:"%ae"会先输出作者的邮箱,然后再输出该提交涉及的文件变更行。awk -F'\t'把制表符作为字段分隔符,NF == 1说明这一行是作者信息,记录下来;NF == 3说明这是一条文件变更记录,将行数累加到对应作者上。最后用sort -k2 -nr按第二列(新增行数)从大到小排序。
用邮箱%ae而不是姓名%an的原因是邮箱几乎不可能包含空格,脚本解析更可靠,而且同名不同人的情况也能区分开。如果你希望输出姓名,可以把%ae换成%an,脚本逻辑不变。实测下来,一个几百次提交的中型项目,这条命令几秒钟就能跑完。
4.4 按时间区间统计:月度、季度、年度
调整时间范围只需要改--since和--until。月度统计用--since="2025-03-01" --until="2025-04-01",季度统计用--since="2025-01-01" --until="2025-04-01",年度统计就是用--since="2025-01-01" --until="2026-01-01"。写好脚本后,这些参数可以抽成变量,每次执行时手动传入。
4.5 处理合并提交与多分支
--no-merges这个参数建议每次都带着。合并提交(merge commit)会把你分支上所有的文件变更重复算一遍,行数虚高非常严重。如果团队常用 rebase 方式整合分支,merge 提交很少,加了这个参数也无妨,属于有备无患。
默认情况下git log只看当前分支的历史。如果需要统计所有分支的提交,加上--all参数。但要注意,--all会把远程分支的提交也纳入统计,可能跟团队实际发布版本有出入,统计前要想清楚口径。
4.6 导出成文本报告或 CSV
把输出重定向到文件就能生成报告:
git log --since="2024-01-01" --until="2025-01-01" --pretty=format:"%ae" --numstat --no-merges | awk -F'\t' ' NF == 1 { author = $0; next } NF == 3 { add[author] += $1; del[author] += $2 } END { for (name in add) printf "%s\t%d\t%d\t%d\n", name, add[name], del[name], add[name] - del[name] } ' | sort -k2 -nr > stats.txt执行后打开项目根目录下的stats.txt,就能看到按行数排序的完整排名。需要导入 Excel 的话,把printf里的\t分隔符改成逗号,保存为.csv即可。
注意:如果输出内容较多,建议先在 Terminal 里跑一次带
head -30的预览命令确认结果,再重定向到文件,避免一次性生成几百行的报告后才发现参数写错了。
5. 常见问题与排查技巧实录
5.1 统计结果为空或者漏人
最常见的原因是作者名不完全匹配。Git 识别作者靠的是提交时配置的user.name和user.email,如果你用--author="张三",但代码里提交者写的是英文名或者带了公司邮箱前缀,那就会漏。排查方法是先执行git log --format='%an <%ae>' | sort -u,看一眼仓库里到底有哪些作者信息,再调整过滤条件。
如果团队有人用了多个邮箱提交,比如原来用个人邮箱、后来改成公司邮箱,按邮箱统计会分成两个人。这种情况建议用姓名过滤,或者在统计前统一规范提交邮箱。
5.2 合并提交导致行数虚高
这个我踩过不止一次。某个同事喜欢把develop分支频繁合并进自己的功能分支,统计下来他一个月"写了"几万行,实际上大部分是别人的代码。加上--no-merges之后数字瞬间就合理了。另外也要留意cherry-pick和revert提交,它们会成块复制或回滚代码,行数变化大但实际工作量不一定大,容易造成排名失真。
5.3 Reformat Code 污染统计结果
这可能是最坑的一个问题。IDEA 的 Reformat Code 功能会对整个文件做格式化,改动量巨大,一次提交可能产生上千行的增减,但这些行本质上只是排版变化,不是真正的业务开发量。我见过有人的月度行数统计里,格式化占了一半比例。解决办法有两个:一是团队约定格式化代码单独提交,并在提交信息里标注chore: format之类的关键词,统计时将这些提交排除;二是命令里加上-w参数让 diff 忽略空白变化,git log -w --numstat在统计时能过滤掉一部分纯格式化的影响,但并不能完全解决缩进方式改变的情况。
5.4 中文作者名称显示乱码
在 Windows 的cmd里跑统计,输出中文很可能变成乱码,这是编码问题而不是数据问题。执行git config --global i18n.logOutputEncoding utf-8,然后在终端里执行chcp 65001切换到 UTF-8 代码页。如果是 PowerShell 环境,执行[Console]::OutputEncoding = [System.Text.Encoding]::UTF8效果也一样。当然,换成 Git Bash 之后基本不需要处理这个问题。
5.5 大仓库统计速度慢
统计范围太大、历史太深时,命令可能要跑几十秒甚至几分钟。比如一个存在了七八年的仓库,git log要遍历几万次提交,慢是正常的。解决办法是尽量缩小时间范围,或者用--since限制起点;也可以先git gc压缩仓库对象,之后统计会快不少。
5.6 Windows 下 awk 命令不可用
如果你在 cmd 里粘贴命令发现提示awk 不是内部或外部命令,说明没用上 Git Bash。这是环境配置问题,按前文第 4.1 节的方法,先在 IDEA 里把 Terminal 的 Shell path 改成bash.exe,再重新打开终端窗口就行。
6. 插件辅助与自动化扩展
6.1 GitToolBox:日常开发的好帮手
IDEA 插件市场里有一款叫 GitToolBox 的工具,安装量非常大。它能在编辑器里显示每一行代码最近是谁提交的、什么时候提交的,还会在状态栏显示当前分支领先和落后远程多少提交。虽然它不直接提供"提交行数排名"功能,但团队里想看代码归属时非常方便。要注意的是,另一个老牌插件 Statistic 统计的是项目当前文件的行数(LOC),跟 Git 提交历史完全是两码事,不要混淆。
如果你发现市面上的插件都不满足需求,也可以考虑自己写一个 IDEA 插件。核心思路是用 JGit 的 API 遍历git.log().all()返回的提交对象,对每次提交调用 diff 计算器拿到文件变更列表,再用FileHeader.getInsertedLines()和getDeletedLines()累加行数。大致结构如下:
Git git = Git.open(new File(projectPath)); Iterable<RevCommit> commits = git.log().all().call(); DiffFormatter formatter = new DiffFormatter(DisabledOutputStream.INSTANCE); formatter.setRepository(git.getRepository()); for (RevCommit commit : commits) { if (commit.getParentCount() > 0) { RevCommit parent = commit.getParent(0); List<DiffEntry> entries = formatter.scan(parent, commit); for (DiffEntry entry : entries) { // 累加 entry 对应的新增和删除行数 } } }不过说实话,对绝大多数团队而言,自己开发插件的成本远高于运行一条脚本。除非你要把统计功能集成到公司内部的工程效能系统里,否则老老实实用命令行脚本是性价比最高的方案。
6.2 把统计命令固化成项目脚本
我建议在项目根目录创建scripts文件夹,把统计命令保存为code-stats.sh,内容可以这样组织:
#!/bin/bash SINCE="$1" UNTIL="$2" git log --since="$SINCE" --until="$UNTIL" --pretty=format:"%ae" --numstat --no-merges | awk -F'\t' ' NF == 1 { author = $0; next } NF == 3 { add[author] += $1; del[author] += $2 } END { for (name in add) printf "%s\t%d\t%d\t%d\n", name, add[name], del[name], add[name] - del[name] } ' | sort -k2 -nr使用的时候执行bash scripts/code-stats.sh 2024-01-01 2025-01-01,把时间参数传进去即可。这样团队成员拿到脚本就能自己跑统计,不需要每个人都理解 awk 的细节。
6.3 统计融入常态化的建议
行数是结果,不是目的。我见过有团队为了卷行数,故意把代码写得冗长或者频繁做无意义的小重构,这跟统计的本意完全背道而驰。我的习惯是:月度、季度各跑一次统计,观察趋势但不作为考核依据,重点看提交频率、提交信息质量和净增行数的分布。把这几天统计出来的数据和 code review 记录放在一起看,能得到比孤立数字客观得多的结论。
我个人在实际操作中最大的体会是:不要只看新增行数,也不要追求单次提交行数大,真正的产出质量藏在"长期净增趋势 + 提交粒度合理 + 代码可维护"这几个维度里。最后再分享一个小技巧:统计命令里加一个--grep参数,比如--grep="merge" --all-match可以快速定位哪些提交是合并分支或者自动化工具产生的,把它们从统计范围里剔除,排名会更接近真实情况。