【问题标题】:TFS2010: Retrieve all changesets associated with a branch (full recursion)TFS2010:检索与分支关联的所有变更集(完全递归)
【发布时间】:2012-03-05 18:06:24
【问题描述】:

这是 my previous question 关于 TFS 2010 和创建变更日志的可能性。

我之前使用标签来识别程序的版本,但由于标签不是固定时间点,现在我使用分支。

分支层次结构如下所示:

如您所见,有两个不同的应用程序是主干的分支:APP_A(应用程序 A)和APP_B(应用程序 B)。两者几乎相同,但存在一些功能差异。

以下是创建应用程序新版本(比如 1.3 版)的过程:

  1. 修改了Main trunk(添加了新功能,修复了错误...)
  2. 从修改后的Main trunk 创建一个新分支:Main trunk 1.3
  3. APP_A 分支可能会被修改,因此 APP_A 的独特功能将适用于 v1.3 的修改
  4. APP_B 分支可能会被修改,因此 APP_B 的独特功能将适用于 v1.3 的修改
  5. Main trunk 1.3 合并到 APP_AAPP_B,因此 APP_AAPP_B 应用程序都会收到 Main trunk 的修改
  6. 从修改后的APP_A 分支创建一个新分支:APP_A_1.3
  7. 从修改后的APP_B 分支创建一个新分支:APP_B_1.3

我的目标是能够在APP_A_1.3APP_A_1.2 之间生成更新日志。

变更日志是指工作项列表。每个签入的变更集都与一个或多个工作项相关联(例如,一个错误项)。 我希望能够获取链接到已影响 APP_A_1.3 的变更集的所有工作项的列表:这些变更集可能来自 Main trunk(上面的第 1 步)、@ 987654347@(上面的第 3 步)甚至是 APP_A_1.3 分支本身(如果在创建分支后签入了修补程序)。

为了获取此工作项列表,我尝试获取“链接”到APP_A_1.2 的所有变更集列表(“链接”= 签入的代码变更集中现在位于分支 APP_A_1.2) 以及“链接”到 APP_A_1.3 的所有变更集的列表。

然后,我将能够知道哪些变更集“链接”到APP_A_1.3,而不是“链接”到APP_A_1.2。从这个变更集子集中,我将获得所有相关的 WorkItems 以及我的变更日志。

这是我的问题:如何获得与指定分支“链接”的 ALL 变更集列表?我将 TFS 2010 API 用于 C# 代码。

我的程序的输入(将检索指定分支的所有变更集)将是分支的名称(例如 APP_A_1.2),输出将是以下变更集的列表:

  • 应用于APP_A_1.2 分支本身的变更集
  • 在创建 APP_A_1.2 之前应用于 APP_A 分支的变更集
  • Main trunk 1.2 分支合并到APP_A 之前应用的变更集
  • 在创建 Main trunk 1.2 之前应用于 Main trunk 分支的变更集

我编写了以下代码来获取所有这些变更集:

// Gets the list of all changesets ID from APP_A_1.2 branch
var branch1ChangeSets = myVersionControlServer.QueryHistory(
    "$/PATH/APP_A_1.2/",
    VersionSpec.Latest,
    0,
    RecursionType.Full,
    null,
    null,
    null,
    int.MaxValue,
    false,
    false).OfType<Changeset>().Select(z => z.ChangesetId).ToList();

即使指定了RecursionType.Full,上面的代码返回在APP_A_1.2分支本身签入的变更集。这与 Visual Studio 中源代码资源管理器视图中的“历史记录”命令相同。

然后我尝试了以下代码:

// Gets the list of all changesets ID from APP_A_1.2 branch
var branch1MergedChangeSets = myVersionControlServer.QueryMerges(
    null,
    null,
    "$/PATH/APP_A_1.2/",
    VersionSpec.Latest,
    null,
    null,
    RecursionType.Full).Select(z => z.SourceVersion).ToList();

这将返回在 APP_A_1.2 分支上签入的变更集 + 在创建 APP_A_1.2 之前在 APP_A 分支上签入的变更集。好多了,但还不够。我找不到使递归与“高于”APP_A(在我的情况下为Main trunk)的分支一起工作的方法......

有人有想法吗?

此外,欢迎任何更好的想法来获取两个分支之间的变更日志...... 谢谢。

【问题讨论】:

  • 好问题! ATM,您不知道如何准确地检索变更集。获得它们后,请考虑 B.Hodges 的这篇精彩文章,它将帮助您将变更集列表与工作项列表相关联:blogs.msdn.com/b/buckh/archive/2012/02/01/…

标签: c# branch tfs-workitem changelog


【解决方案1】:

首先让我先问一个问题。在你写的帖子的顶部: “我的目​​标是能够在 APP_A_1.3 和 APP_A_1.2 之间生成变更日志。”

但是,当您编写具体的更改时,您正在寻找您的列表: 应用于 APP_A_1.2 分支本身的变更集 创建 APP_A_1.2 之前应用于 APP_A 分支的变更集 在主干线 1.2 分支合并到 APP_A 之前应用的变更集 在创建主干线 1.2 之前应用于主干线分支的变更集

这不是一个有效的列表,因为它会将所有对 APP_A_1.3、APP_A_1.2、1.1 等做出贡献的更改都提供给存储库的开头。

我现在无法测试我的方法,但我会这样做: - QueryHistory 将所有更改直接签入分支 1.3 - 使用 QueryMergesExtended 跟随合并到这个分支。 QueryMergesExtended (http://msdn.microsoft.com/en-us/library/ff736485.aspx) 是在 TFS 2010 中添加的,目的是为了比 QueryMerges 和 QueryMergesWithDetails 更高效、更健壮,以支持分支可视化工具 - afaik 你不需要在 QueryMergesExtended 中指定选项 FollowRenames 因为你在分支的根上查询合并 - 当您获得源更改列表(来自 APP_A)时,您需要检查每个变更集以查看它是否包含合并更改。如果是这样,您需要在 app_a 上查询这些变更集的合并。递归执行此操作,直到遍历整个分支层次结构。

关于附带主题,您可以稍后查看 QueryMergeRelationships (http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.versioncontrol.client.versioncontrolserver.querymergerelationships.aspx),它为您提供了 tfs 2010 中引入的分支对象列表(这是在源代码管理资源管理器中选择文件夹并单击转换为分支时发生的情况)。但是,如果您能以不同的方式(硬编码)发现您的分支,那么就不需要了。

希望这会有所帮助!

【讨论】:

  • 嗨,我不明白为什么我提到的列表会给我在APP_A_1.3 上应用的变更集。我对APP_A_1.2APP_A_1.1 没意见(这是我所期望的),但我看不到仅应用于APP_A_1.3 的变更集将如何出现在其中一个列表中。另外,我测试了QueryMergesExtended,但它不会递归返回所有变更集(例如,应用于APP_A_1.3,它从APP_A 返回变更集,但不是从Main Trunk)。
  • 我确实可以使用QueryMergeRelationships 来发现我的分支然后多次调用QueryMergesExtended,这应该可以。我还找到了TrackMerges 的方法,我会尽快将其作为另一个答案发布。我赞成您的回答,因为它很有用,谢谢。
【解决方案2】:

我终于想出了一个简单的解决方案。我对它并不完全满意,因为它实际上看起来像一个蛮力算法,但至少它有效。

我做的是:

1) 获取应用于我的 TFS 分支的最根目录每个变更集的列表(即Main Trunk 的“父路径”):

var allChangesets = vcs.QueryHistory(
    "MySourcePath",
    VersionSpec.Latest,
    0,
    RecursionType.Full,
    null,
    firstPossibleChangeset,
    VersionSpec.Latest,
    int.MaxValue,
    true,
    false).OfType<Changeset>().ToList();

2) 对于每个检索到的变更集,我调用TrackMerges 以查看变更集是否以某种方式影响我的分支。 TrackMerges 能够告诉我是否在我指定为函数参数的分支上应用了指定的变更集(它将在这些分支上返回目标变更集 ID)。如果变更集应用于目标分支(在我的情况下为 APP_A_1.3)而不是源分支(APP_A_1.2),那么这意味着它绝对是我的 APP_A_1.3 分支上的新内容。

List<int> newChangesets = new List<int>();
foreach (var z in allChangesets.Where(y => y.ChangesetId > firstPossibleChangesetId))
{
    var zz = vcs.TrackMerges(
        new int[] { z.ChangesetId },
        new ItemIdentifier("THE TRUNK PATH"),   // The root of all branches
        new ItemIdentifier[] { new ItemIdentifier(fromBranchPath), new ItemIdentifier(toBranchPath) },
        null);

    var targetInFromBranch = zz.Where(t => t.TargetItem.Item == fromBranchPath).FirstOrDefault();
    var targetInToBranch = zz.Where(t => t.TargetItem.Item == toBranchPath).FirstOrDefault();

    if (targetInToBranch != null && targetInFromBranch == null)
    {
        // Then the changeset is only applied on the ToBranch
        newChangesets.Add(z.ChangesetId);
    }
}

3) 现在从“新变更集”列表中获取我的变更日志(工作项列表)非常简单:

// Now, gets associated work items!
Dictionary<int, WorkItem> dico = new Dictionary<int, WorkItem>();
foreach (int changesetId in newChangesets)
{
    foreach (WorkItem zz in vcs.GetChangeset(changesetId).WorkItems)
    {
        this.AddWorkItemToDicRecursive(wis, dico, zz);
    }
}

private void AddWorkItemToDicRecursive(WorkItemStore wis, Dictionary<int, WorkItem> dico, WorkItem workItem)
{
    if (!dico.ContainsKey(workItem.Id))
    {
        dico.Add(workItem.Id, workItem);

        foreach (WorkItemLink associatedItem in workItem.WorkItemLinks)
        {
            this.AddWorkItemToDicRecursive(wis, dico, wis.GetWorkItem(associatedItem.TargetId));
        }
    }
}

我认为这不是最好的方法,但它可以正常工作并且仍然很简单。此外,我不必对任何内容(分支名称/层次结构)进行硬编码,因此 IMO 还不错。希望它会帮助某人。

【讨论】:

    【解决方案3】:

    是的,我自己也在解决这个问题。无论如何,当您区分标签时,我找到了一个解决它的 codeplex 项目。

    看看这是否有帮助:http://tfslabeldiff.codeplex.com/SourceControl/changeset/view/7075#158224

    我很惊讶这是多么难以找到,但 TFS 的文档充其量是缺乏的。看起来应该很明显!

    【讨论】:

    • 嗨 Sharon,我认为你的提议不是遍历分支历史,换句话说,它不会递归检索不同分支之间的变更集。
    猜你喜欢
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多