无需git命令从GitHub仓库Git diff文件统计代码变更行数
解决方案
以下两种实现均满足无本地Git环境、无仓库访问权限的限制,只需要传入diff文本内容即可完成统计。
方案1:使用成熟diff解析库(推荐)
采用纯Python编写的unidiff库解析标准unified diff格式,无任何系统级依赖,不需要安装Git,已经覆盖二进制文件标记、文件重命名、多hunk分段、无末尾换行提示等各类边缘场景,统计准确率远高于手写临时解析逻辑。
安装命令:
pip install unidiff
实现代码:
from unidiff import PatchSet def calc_diff_stats(diff_content_list: list[str]) -> tuple[int, int, list[dict]]: """ 统计diff文件的变更数据 :param diff_content_list: 所有diff文件的原始文本内容组成的列表 :return: 总新增行数、总删除行数、单文件统计结果列表 """ total_add = 0 total_remove = 0 per_file_stats = [] for diff_text in diff_content_list: patch = PatchSet(diff_text) file_add = 0 file_remove = 0 for file in patch: for hunk in file: for line in hunk: if line.is_added: file_add += 1 if line.is_removed: file_remove += 1 per_file_stats.append({ "added_lines": file_add, "removed_lines": file_remove, "total_changed_lines": file_add + file_remove }) total_add += file_add total_remove += file_remove return total_add, total_remove, per_file_stats if __name__ == "__main__": # 替换为实际读取到的所有diff文件内容 diff_files = [open("pull_request.diff", "r", encoding="utf-8").read()] add, remove, _ = calc_diff_stats(diff_files) print(f"total lines added = {add}, total lines removed = {remove}")
用你提供的示例diff测试,输出结果为total lines added = 2, total lines removed = 0,和实际变更完全一致。
方案2:纯标准库轻量实现
如果不想引入第三方依赖,可以直接按照unified diff的语法规则逐行遍历统计,核心判断逻辑如下:
- 跳过所有元信息行:包括文件头(以
diff --git、index、---、+++开头)、hunk位置标记(以@@开头)、diff注释(以\开头,比如No newline at end of file提示) - 剩余行中,以
+开头的计入新增行数,以-开头的计入删除行数,其余为未变更的上下文行,不计入增删统计
实现代码:
def calc_diff_stats_no_dep(diff_content_list: list[str]) -> tuple[int, int]: total_add = 0 total_remove = 0 for diff_text in diff_content_list: for line in diff_text.splitlines(): # 跳过所有非内容的标记行 if ( line.startswith("diff --git") or line.startswith("index ") or line.startswith("--- ") or line.startswith("+++ ") or line.startswith("@@") or line.startswith("\\") ): continue if line.startswith("+"): total_add += 1 elif line.startswith("-"): total_remove += 1 return total_add, total_remove if __name__ == "__main__": diff_files = [open("pull_request.diff", "r", encoding="utf-8").read()] add, remove = calc_diff_stats_no_dep(diff_files) print(f"total lines added = {add}, total lines removed = {remove}")
可选GitHub原生方案
由于目标仓库托管在GitHub,你也可以直接调用GitHub的PR相关接口,接口返回的结构化数据中直接自带additions、deletions统计字段,不需要自行解析diff文本,适合批量统计大量PR的场景。
内容的提问来源于stack exchange,提问作者milosmns
相关产品推荐
相关产品推荐

