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

GitHttpClient.GetCommitDiffsAsync获取指定Commit文件内容异常求助

问题:Azure DevOps API 获取指定提交的文件内容时始终返回最新版本

背景代码

已连接Azure DevOps API并创建Git客户端:

var conn = new VssConnection(new Uri(uri), new VssBasicCredential("", pat));
var gitClient = conn.GetClient<GitHttpClient>();

获取提交列表:

var commits = gitClient.GetCommitsAsync(project, repo.Id.ToString(), searchCriteria).WaitForResult();

使用的WaitForResult扩展方法:

public static class TaskExtension
{
    public static T WaitForResult<T>(this Task<T> task) where T : class
    {
        task.Wait();
        return task.Result;
    }
}

获取提交修改文件内容的代码

尝试获取每个提交中修改的VB文件内容,但始终返回最新版本:

var c2 = gitClient.GetCommitAsync(project: project, commitId: commit.CommitId, repositoryId: repositoryId)
    .WaitForResult();
if (c2.Parents?.Any() ?? false)
{
  var parentCommitId = c2.Parents.First();

  var desc = new GitTargetVersionDescriptor
  {
    Version = commit.CommitId,
    VersionType = GitVersionType.Commit,
    VersionOptions = GitVersionOptions.None
  };

  var pdesc = new GitBaseVersionDescriptor
  {
    Version = parentCommitId,
    VersionType = GitVersionType.Commit,
    VersionOptions = GitVersionOptions.None
  };

  var diff = gitClient.GetCommitDiffsAsync(repositoryId: repositoryId,
    project: project, 
    diffCommonCommit: false,
    targetVersionDescriptor: desc, 
    baseVersionDescriptor: pdesc
    ).WaitForResult();

  foreach(var change in diff.Changes)
  {
    if (!change.Item.IsFolder && change.ChangeType == Microsoft.TeamFoundation.SourceControl.WebApi.VersionControlChangeType.Edit && change.Item.Path.EndsWith(".vb"))
    {
      var item = gitClient.GetItemAsync(project: project, repositoryId,
        path: change.Item.Path, versionDescriptor: desc, includeContent: true).WaitForResult();
      
      /* 此处获取的item.Content始终为文件最新版本,即使使用pdesc结果也相同 */
    }
  }
}

核心问题

  1. 调用GetItemAsync时,无论使用当前提交的版本描述符还是父提交的版本描述符,均返回文件的最新版本内容,而非对应提交版本的内容
  2. 即使在Version中填入非SHA1格式的无效哈希值,API不报错,仍返回文件最新版本

原因与解决方案

核心原因

你错误地使用了GitTargetVersionDescriptor和GitBaseVersionDescriptor来指定单个版本的文件。这两个类型是专门用于差异比较场景(如GetCommitDiffsAsync)的参数,并不适用于单独获取某一提交版本的文件内容。当API无法识别这类不匹配的版本描述符时,会默认返回文件的最新版本。

解决方案

将获取文件内容时使用的版本描述符替换为通用的GitVersionDescriptor,该类型才是用于指定单个Git版本(提交、分支、标签等)的正确类型:

修改代码中的版本描述符创建逻辑:

// 替换原有的GitTargetVersionDescriptor
var targetVersion = new GitVersionDescriptor
{
    Version = commit.CommitId,
    VersionType = GitVersionType.Commit,
    VersionOptions = GitVersionOptions.None
};

// 替换原有的GitBaseVersionDescriptor
var parentVersion = new GitVersionDescriptor
{
    Version = parentCommitId,
    VersionType = GitVersionType.Commit,
    VersionOptions = GitVersionOptions.None
};

然后在GetItemAsync中使用修改后的版本描述符:

// 获取当前提交版本的文件内容
var item = gitClient.GetItemAsync(project: project, repositoryId,
    path: change.Item.Path, versionDescriptor: targetVersion, includeContent: true).WaitForResult();

// 若需要父提交版本的文件内容,使用parentVersion即可
// var parentItem = gitClient.GetItemAsync(project: project, repositoryId,
//     path: change.Item.Path, versionDescriptor: parentVersion, includeContent: true).WaitForResult();

额外验证

确保传入的commit.CommitId和parentCommitId是完整的SHA1哈希值(如示例中的e71789c1424ba1ea5c6a9edb5bca4fff1b647185),短哈希可能导致API无法准确定位到目标提交,同样会 fallback 到最新版本。


内容的提问来源于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 13:43:11