如何用Python获取Git仓库的代码增删行数(类似git log --numstat)
嘿,这个需求我刚好折腾过!要在现有Python代码基础上,实现类似git log --numstat的新增/删除行数统计效果,其实有两种靠谱的路子——直接调用Git命令行解析输出,或者用专门的Git Python库来实现更优雅的代码。我给你分别拆解一下:
方法一:直接调用Git命令行(快速上手)
这种方法最直接,因为Git本身就自带了--numstat参数可以输出统计数据,咱们用Python的subprocess模块调用命令,再解析结果就行。
比如如果你的现有代码是对比当前树和上一棵树(比如HEAD和HEAD~1),那对应的Git命令是git diff --numstat HEAD~1 HEAD,它的输出格式是:
新增行数 删除行数 文件名
(如果是二进制文件,新增和删除行数会显示-)
下面是完整的Python代码示例:
import subprocess import os def get_git_numstat(commit1="HEAD~1", commit2="HEAD"): # 确保在Git仓库目录下 if not os.path.exists(".git"): print("当前目录不是Git仓库!") return None try: # 执行Git diff命令,捕获输出 result = subprocess.run( ["git", "diff", "--numstat", commit1, commit2], capture_output=True, text=True, check=True ) output = result.stdout.strip() if not output: print("两个版本之间没有文件变更") return [] # 解析每行输出 numstat_list = [] for line in output.split("\n"): parts = line.split("\t") if len(parts) != 3: continue # 跳过异常行 added, removed, filename = parts # 处理二进制文件的情况 added = int(added) if added != "-" else 0 removed = int(removed) if removed != "-" else 0 numstat_list.append({ "filename": filename, "added": added, "removed": removed }) return numstat_list except subprocess.CalledProcessError as e: print(f"执行Git命令出错: {e.stderr}") return None # 调用示例 stats = get_git_numstat() if stats: print("文件变更统计:") for stat in stats: print(f"{stat['filename']}: +{stat['added']} - {stat['removed']}")
方法二:用GitPython库(更Pythonic的方式)
如果你不想直接解析命令行输出,想要更优雅的面向对象写法,可以用GitPython库,它封装了Git的各种操作。
首先需要安装库:
pip install gitpython
然后是代码示例:
from git import Repo import os def get_git_numstat_with_gitpython(commit1="HEAD~1", commit2="HEAD"): # 初始化Repo对象 try: repo = Repo(os.getcwd()) except Exception as e: print(f"无法初始化Git仓库: {str(e)}") return None try: # 获取两个commit对象 commit_a = repo.commit(commit1) commit_b = repo.commit(commit2) # 获取两个commit的diff diffs = commit_a.diff(commit_b, create_patch=True) numstat_list = [] for diff in diffs: # 跳过已删除的文件(如果需要的话) if diff.deleted_file: continue filename = diff.b_path if diff.b_path else diff.a_path # 统计新增和删除行数 added = 0 removed = 0 if diff.patch: for line in diff.patch.split("\n"): if line.startswith("+") and not line.startswith("+++"): added += 1 elif line.startswith("-") and not line.startswith("---"): removed += 1 # 处理二进制文件(patch为None) else: added = 0 removed = 0 numstat_list.append({ "filename": filename, "added": added, "removed": removed }) return numstat_list except Exception as e: print(f"获取diff统计出错: {str(e)}") return None # 调用示例 stats = get_git_numstat_with_gitpython() if stats: print("文件变更统计:") for stat in stats: print(f"{stat['filename']}: +{stat['added']} - {stat['removed']}")
一些额外注意事项
- 如果你的现有代码是对比其他版本(比如某个分支和当前分支),只需要修改
commit1和commit2的参数即可,比如commit1="main", commit2="feature-branch" - 二进制文件的统计:Git不会统计二进制文件的行数,所以两种方法里都处理了这种情况,显示为0行新增/删除
- 如果要实现类似
git log --numstat遍历所有提交的统计,可以循环遍历Git的commit历史,逐个对比当前commit和它的父commit
内容的提问来源于stack exchange,提问作者Akhil Singhal
相关产品推荐
相关产品推荐

