You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Azure DevOps API获取Git提交的实际变更内容(Diff)

Azure DevOps Git API 获取提交变更内容及代码优化

一、解决变更内容为null的问题

你当前使用GetCommitDiffsAsync获取的差异结果中,GitItem.Content和GitChange.NewContent默认不会返回实际文件内容,需要针对每个变更的文件单独调用API获取内容:

  • 对于每个变更项,通过GitChange.Item.Path获取文件路径
  • 调用GitHttpClient.GetItemContentAsync方法,传入仓库ID、项目名、文件路径,以及目标版本(当前提交ID)来获取文件内容

示例修改后的代码片段:

foreach(var change in diff.Changes)
{
    // 获取变更文件的内容
    var contentStream = gitClient.GetItemContentAsync(
        repositoryId: repositoryId,
        project: project,
        path: change.Item.Path,
        versionDescriptor: new GitVersionDescriptor
        {
            VersionType = GitVersionType.Commit,
            Version = commit.CommitId
        }).WaitForResult();

    // 将Stream转换为字符串输出
    using (var reader = new StreamReader(contentStream))
    {
        Debug.WriteLine(reader.ReadToEnd());
    }
}

该方式能覆盖修改、新增等各类文件变更场景,无需依赖NewContent.Uri这类特定字段。

二、简化代码减少API调用

你的代码存在冗余API调用,可从以下两点优化:

  1. 移除多余的GetCommitAsync调用
    GetCommitsAsync返回的GitCommitRef对象已包含Parents属性,无需再次调用GetCommitAsync获取完整提交信息,直接使用commit.Parents即可,减少一次API请求。

  2. 过滤不必要的文件减少请求
    循环内的文件内容请求是主要的API消耗点,可优先过滤需要检查的文件类型(如仅检查.cs、.json等),避免获取无关文件的内容。

优化后的完整代码:

private void GetGitChanges()
{
    var organization = "org";
    var project = "proj";
    var repositoryId = "repo";

    var uri = $"https://tfs.foobar.se/tfs/{organization}/";
    var pat = ConfigurationManager.AppSettings["PAT"];
    using (var conn = new VssConnection(new Uri(uri), new VssBasicCredential("", pat)))
    {
        var gitClient = conn.GetClient<GitHttpClient>();
        
        var searchCriteria = new GitQueryCommitsCriteria
        {
            IncludeWorkItems = true,
            ItemVersion = new GitVersionDescriptor
            {
                VersionType = GitVersionType.Branch,
                VersionOptions = GitVersionOptions.FirstParent,
                Version = "master"
            }
        };

        var commits = gitClient.GetCommitsAsync(project, repositoryId, searchCriteria).WaitForResult();

        foreach(var commit in commits)
        {
            if (commit.Parents?.Any() ?? false)
            {
                var parentCommitId = commit.Parents.First();

                var diff = gitClient.GetCommitDiffsAsync(
                    repositoryId: repositoryId,
                    project: project,
                    diffCommonCommit: false,
                    targetVersionDescriptor: new GitTargetVersionDescriptor 
                    { 
                        Version = commit.CommitId, 
                        VersionType = GitVersionType.Commit, 
                        VersionOptions = GitVersionOptions.None 
                    }, 
                    baseVersionDescriptor: new GitBaseVersionDescriptor 
                    { 
                        Version = parentCommitId, 
                        VersionType = GitVersionType.Commit, 
                        VersionOptions = GitVersionOptions.None 
                    }).WaitForResult();

                foreach(var change in diff.Changes)
                {
                    // 过滤仅检查.cs文件,可根据需求调整
                    if (!change.Item.Path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    var contentStream = gitClient.GetItemContentAsync(
                        repositoryId: repositoryId,
                        project: project,
                        path: change.Item.Path,
                        versionDescriptor: new GitVersionDescriptor
                        {
                            VersionType = GitVersionType.Commit,
                            Version = commit.CommitId
                        }).WaitForResult();

                    using (var reader = new StreamReader(contentStream))
                    {
                        Debug.WriteLine($"文件路径:{change.Item.Path}");
                        Debug.WriteLine($"内容:{reader.ReadToEnd()}");
                    }
                }
            }
        }
    }
}

额外提示

  • 确保你的PAT拥有Code Read权限,否则无法获取文件内容
  • 若遇到API限流问题,可添加重试逻辑或降低并发请求数

内容的提问来源于stack exchange,提问作者Anders Lindén

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 12:50:18