如何从Git commit对象获取代码行数?Jupyter Notebook实现方法问询
从Git Commit对象提取指定Python文件的代码行数(Jupyter Notebook实现)
当然有办法啦!我之前做过类似的统计需求,刚好可以给你捋清楚在Jupyter Notebook里怎么实现。
步骤1:安装依赖
我们可以借助gitpython这个库来直接操作Git仓库和commit对象,它能让我们用Python代码优雅地和Git交互。先在Notebook里安装它:
!pip install gitpython
步骤2:核心实现代码
下面是完整的可运行代码,我会逐行给你解释逻辑:
from git import Repo # 替换成你的Git仓库本地路径 repo_path = "/path/to/your/git/repository" # 替换成你要统计的.py文件相对路径(相对于仓库根目录) target_file = "src/your_script.py" # 打开目标Git仓库 repo = Repo(repo_path) # 只获取涉及目标文件的所有提交历史(过滤掉不相关的commit,提升效率) file_commits = list(repo.iter_commits(paths=target_file)) # 遍历每个commit,统计对应版本的代码行数 for commit in reversed(file_commits): # reversed让输出顺序从最早提交到最新提交 try: # 从commit对象的树结构中提取目标文件的内容 file_content = commit.tree[target_file].data_stream.read().decode("utf-8") # 统计总行数(如果要排除空行/注释行,可以加额外判断) line_count = len(file_content.splitlines()) # 输出关键信息:短哈希、提交时间、行数 print(f"Commit {commit.hexsha[:7]} | {commit.committed_datetime.strftime('%Y-%m-%d %H:%M')} | 代码行数: {line_count}") except KeyError: # 处理文件还未被创建的旧commit(比如文件是后来新增的) print(f"Commit {commit.hexsha[:7]} | {commit.committed_datetime.strftime('%Y-%m-%d %H:%M')} | 文件未存在")
关键细节说明
repo.iter_commits(paths=target_file):这个方法会自动过滤出所有修改过目标文件的commit,不用遍历仓库里的所有提交,效率更高。commit.tree[target_file].data_stream.read():这就是直接从commit对象提取文件内容的核心逻辑——每个commit都对应一个文件树结构,我们可以通过文件路径直接定位到该版本的文件内容,进而统计行数。- 如果需要排除空行或单行注释,可以修改统计逻辑,比如:
line_count = sum(1 for line in file_content.splitlines() if line.strip() and not line.strip().startswith("#"))
备选方案:直接调用Git命令
如果你不想安装额外库,也可以用subprocess直接调用Git命令实现,适合环境受限的场景:
import subprocess repo_path = "/path/to/your/git/repository" target_file = "src/your_script.py" # 获取所有涉及目标文件的commit短哈希和提交信息 commits = subprocess.check_output( ["git", "-C", repo_path, "log", "--oneline", "--follow", "--", target_file], text=True ).splitlines() for commit_line in reversed(commits): commit_hash = commit_line.split()[0] try: # 获取该commit版本下目标文件的内容并统计行数 file_content = subprocess.check_output( ["git", "-C", repo_path, "show", f"{commit_hash}:{target_file}"], text=True ) line_count = len(file_content.splitlines()) print(f"Commit {commit_hash} | 代码行数: {line_count}") except subprocess.CalledProcessError: print(f"Commit {commit_hash} | 文件未存在")
两种方法各有优劣:gitpython更贴合Python生态,代码可读性强;直接调用Git命令则无需额外依赖,适合快速验证。
内容的提问来源于stack exchange,提问作者asoomdeys
相关产品推荐
相关产品推荐

