如何通过Python SDK获取Azure Git仓库提交中的具体变更行?
如何在Azure DevOps中获取Pull Request的变更行内容
我正在测试AI驱动的PR审查工具,需要获取Azure Git仓库PR中的变更行内容交给GPT-4审查。目前使用Azure DevOps SDK只能读取变更文件的完整内容,无法获取仅变更的行,请问有什么解决办法?
方法1:调用Azure DevOps REST API的Diff端点
Azure DevOps提供了直接返回PR差异的REST API,结果包含每个文件的变更块(hunk),其中明确标记了变更行的位置和内容,这是最直接的官方解决方案。
代码示例
import os import requests from dotenv import load_dotenv load_dotenv() PAT = os.getenv('PAT') ORG_URL = os.getenv('ORG_URL') PROJECT_NAME = os.getenv('PROJECT_NAME') REPO_ID = os.getenv('REPO_NAME') PR_ID = 2 # 构建Diff API请求地址 diff_url = f"{ORG_URL}/{PROJECT_NAME}/_apis/git/repositories/{REPO_ID}/pullRequests/{PR_ID}/diffs?api-version=7.1-preview.1" # 设置认证请求头 headers = { 'Authorization': f'Basic {PAT}' } # 发送请求并解析结果 response = requests.get(diff_url, headers=headers) response.raise_for_status() diff_data = response.json() # 遍历并输出变更行 for file_diff in diff_data['changes']: print(f"\n文件路径: {file_diff['item']['path']}") if 'hunks' in file_diff: for hunk in file_diff['hunks']: print(f"变更范围: 原文件行 {hunk['oldStart']}-{hunk['oldStart'] + hunk['oldLength'] -1} → 新文件行 {hunk['newStart']}-{hunk['newStart'] + hunk['newLength'] -1}") print("变更内容:") for line in hunk['lines']: # 根据行类型添加前缀标识 prefix = '+' if line['lineType'] == 'add' else '-' if line['lineType'] == 'remove' else ' ' print(f"{prefix}{line['content']}")
方法2:使用Git命令行工具
如果运行环境允许执行Git命令,可以通过克隆仓库、对比PR的源分支与目标分支来获取变更行,适合需要本地处理差异的场景。
代码示例
import os import subprocess from dotenv import load_dotenv load_dotenv() REPO_URL = f"{os.getenv('ORG_URL')}/{os.getenv('PROJECT_NAME')}/_git/{os.getenv('REPO_NAME')}" TARGET_BRANCH = "main" # PR的目标分支 SOURCE_BRANCH = "feature-branch" # PR的源分支 # 克隆临时仓库(若不存在) temp_repo_path = './temp_pr_repo' if not os.path.exists(temp_repo_path): subprocess.run(['git', 'clone', REPO_URL, temp_repo_path], check=True) os.chdir(temp_repo_path) # 拉取最新代码 subprocess.run(['git', 'pull'], check=True) # 获取分支间的差异内容 diff_result = subprocess.run( ['git', 'diff', f"{TARGET_BRANCH}...{SOURCE_BRANCH}"], capture_output=True, text=True, check=True ) # 输出变更行 print(diff_result.stdout)
方法3:结合GitPython本地计算差异
通过Azure DevOps SDK获取PR的源/目标Commit ID,再用GitPython库拉取对应版本的文件内容,最后本地计算行差异,适合需要自定义差异解析逻辑的场景。
代码示例
import os import difflib from git import Repo from dotenv import load_dotenv from azure.devops.connection import Connection from msrest.authentication import BasicAuthentication load_dotenv() PAT = os.getenv('PAT') ORG_URL = os.getenv('ORG_URL') PROJECT_NAME = os.getenv('PROJECT_NAME') REPO_ID = os.getenv('REPO_NAME') PR_ID = 2 # 初始化Azure DevOps连接 credentials = BasicAuthentication('', PAT) connection = Connection(base_url=ORG_URL, creds=credentials) git_client = connection.clients.get_git_client() # 获取PR的源/目标分支Commit信息 pull_request = git_client.get_pull_request(REPO_ID, PR_ID, project=PROJECT_NAME) target_commit_id = pull_request.target_ref_name.split('/')[-1] source_commit_id = pull_request.source_ref_name.split('/')[-1] # 克隆或打开本地仓库 repo_path = './temp_pr_repo' if not os.path.exists(repo_path): repo = Repo.clone_from(f"{ORG_URL}/{PROJECT_NAME}/_git/{REPO_ID}", repo_path) else: repo = Repo(repo_path) # 获取两个Commit的文件树 target_tree = repo.commit(target_commit_id).tree source_tree = repo.commit(source_commit_id).tree # 计算并输出文件差异 diff_index = target_tree.diff(source_tree) for diff in diff_index: print(f"\n文件: {diff.a_path}") if diff.change_type in ['M', 'A']: # 读取文件的新旧版本内容 old_content = diff.a_blob.data_stream.read().decode('utf-8').splitlines() if diff.a_blob else [] new_content = diff.b_blob.data_stream.read().decode('utf-8').splitlines() # 生成行级差异 diff_lines = difflib.unified_diff(old_content, new_content, fromfile=diff.a_path, tofile=diff.b_path) print('\n'.join(diff_lines))
内容的提问来源于stack exchange,提问作者Federico
相关产品推荐
相关产品推荐

