如何用Git统计两个Commit间的代码细分(含历史修改时间维度)
实现三类代码行细分统计的方法
Git没有原生命令直接输出你需要的三类统计,得结合git diff、git blame和脚本逻辑来完成——核心是追踪变更行的历史修改时间,以此区分Refactored和Reworked行。
核心思路拆解
- NewLines:直接统计两个commit间diff里以
+开头的行(排除diff头部的+++行) - RefactoredLines/ReworkedLines:对diff中被删除/修改的原行(以
-开头的行),用git blame查询该行在旧commit中的最后修改时间,判断是否超过30天,分别归类
可运行的Bash脚本示例
以下脚本接收两个commit ID作为参数,自动统计三类行的数量:
#!/bin/bash # 检查参数是否齐全 if [ $# -ne 2 ]; then echo "用法: $0 <旧commit ID> <新commit ID>" exit 1 fi COMMIT_OLD=$1 COMMIT_NEW=$2 # 初始化统计变量 NEW_LINES=0 REFACTORED_LINES=0 REWORKED_LINES=0 # 计算30天前的时间戳(单位:秒) THIRTY_DAYS_AGO=$(date -d "30 days ago" +%s) # 遍历所有有变更的文件 git diff --name-only "$COMMIT_OLD" "$COMMIT_NEW" | while read -r FILE; do # 获取当前文件的diff块信息(无上下文) git diff -U0 "$COMMIT_OLD" "$COMMIT_NEW" -- "$FILE" | grep '^@@' | while read -r HUNK; do # 提取旧版本中该diff块的起始行号和行数 OLD_RANGE=$(echo "$HUNK" | awk '{print $2}' | sed 's/^-//') OLD_START=$(echo "$OLD_RANGE" | cut -d',' -f1) OLD_COUNT=$(echo "$OLD_RANGE" | cut -d',' -f2) [ -z "$OLD_COUNT" ] && OLD_COUNT=1 # 遍历该块内的每一行(旧版本中的行) for ((i=0; i<OLD_COUNT; i++)); do LINE_NUM=$((OLD_START + i)) # 获取该行最后一次修改的时间戳 BLAME_COMMIT=$(git blame -L $LINE_NUM,$LINE_NUM "$COMMIT_OLD" -- "$FILE" | awk '{print $1}') COMMIT_TIME=$(git show -s --format=%at "$BLAME_COMMIT") # 判断时间归属类别 if [ "$COMMIT_TIME" -lt "$THIRTY_DAYS_AGO" ]; then ((REFACTORED_LINES++)) else ((REWORKED_LINES++)) fi done done # 统计当前文件的新增行 ADD_LINES=$(git diff -U0 "$COMMIT_OLD" "$COMMIT_NEW" -- "$FILE" | grep '^+' | grep -v '^+++' | wc -l) NEW_LINES=$((NEW_LINES + ADD_LINES)) done # 输出最终统计结果 echo "=== 代码行统计结果 ===" echo "- NewLines: $NEW_LINES" echo "- RefactoredLines: $REFACTORED_LINES" echo "- ReworkedLines: $REWORKED_LINES"
使用说明
- 将脚本保存为
code_stat.sh,赋予执行权限:chmod +x code_stat.sh - 运行脚本:
./code_stat.sh <旧commit> <新commit>(比如./code_stat.sh abc123 def456)
注意事项
- 脚本依赖Bash环境和Git,确保已安装
- 对于大型仓库或大量变更的commit,脚本运行速度会较慢(因为要对每行执行
git blame),可以通过批量导出git blame信息来优化 - 脚本中会自动跳过diff的头部信息,只统计实际的代码变更行
简化替代方案(非精确)
如果不需要严格精确到每行的修改时间,可以用以下思路快速估算:
- 用
git diff --stat获取总插入/删除数,得到NewLines的近似值 - 用
git log --since="30 days ago" --oneline "$COMMIT_OLD".."$COMMIT_NEW"获取最近30天内的commit,对这些commit执行git diff --stat统计ReworkedLines,剩余的删除/修改行即为RefactoredLines
- 这种方法误差较大,因为是基于commit提交时间而非行的最后修改时间,仅适合粗略统计
内容的提问来源于stack exchange,提问作者darthkurak
相关产品推荐
相关产品推荐

