这是关于TFS2010和创建changelog的可能性的my previous question。
我以前使用标签来标识程序的一个版本,但是由于标签不是固定的时间点,所以现在我使用分支。
下面是分支层次结构的外观:
如您所见,有两个不同的应用程序是主干的分支:APP_A
(应用程序A)和APP_B
(应用程序B)。两者几乎相同,但存在一些功能上的差异。
下面是创建应用程序的新版本(比如1.3版)的过程:
Main trunk 1.3
APP_A
Main trunk
被修改(添加了新功能,错误修复...)
APP_B
分支可能会被修改,因此APP_A
的独特功能将与Main trunk 1.3
APP_A
分支的修改一起使用,因此APP_B
的独特功能将与v1.3
APP_B
的修改合并到APP_A
和<代码>D23Main trunk >,因此,APP_A
和APP_B
应用程序都会收到修改后的APP_B_1.3
分支的Main trunk
APP_A_1.3
APP_A
分支。我的目标是能够在APP_A_1.3
和APP_A_1.2
之间生成changelog。
我指的是WorkItems的列表。每个签入的变更集都与一个或多个WorkItem相关联(例如,Bug项)。我希望能够获得链接到影响的变更集的所有工作项的列表,这些变更集可能来自Main trunk
(上面的步骤1)、APP_A branch
(上面的步骤3)甚至APP_A_1.3
分支本身(如果在创建分支之后签入了热修复)。
为了获得这个工作项列表,我尝试获取与APP_A_1.2
APP_A_1.2
“链接”的所有变更集的列表("linked“=变更集中签入的代码现在位于分支 APP_A_1.2
)上),以及”链接“到APP_A_1.3
的所有变更集的列表。
然后,我将能够知道哪些变更集“链接”到了APP_A_1.3
,而不是“链接”到了APP_A_1.2
。从这个变更集的子集中,我将获得所有相关的WorkItems,从而获得我的变更日志。
这就是我的问题:如何获得与指定分支“链接”的所有变更集的列表?我对C#代码使用了TFS2010API。
我的程序(将检索指定分支的所有变更集)的输入将是该分支的名称(例如APP_A_1.2
),输出将是以下变更集的列表:
在将itself
Main trunk 1.2
分支上应用的APP_A
APP_A
分支上应用APP_A_1.2
之前,在Main trunk 1.2
分支上应用了APP_A_1.2
分支上应用的我已经编写了以下代码来获取所有这些变更集:
// 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中源代码资源管理器视图中的"History“命令相同。
然后我尝试了下面这段代码:
// 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
)的分支一起工作……
有谁有主意吗?
此外,欢迎任何在两个分支之间获取changelog的更好的想法...谢谢。
发布于 2012-03-03 00:50:17
我终于想出了一个简单的解决方案。我对它并不完全满意,因为它实际上看起来像是一个蛮力算法,但至少它是有效的。
我所做的是:
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)现在,从"new changesets“列表中获取我的changelog (工作项列表)非常简单:
// 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。希望这能帮助到某个人。
发布于 2012-02-27 18:26:39
首先,我先问一个问题。在文章的顶部,你写道:“我的目标是能够在APP_A_1.3和APP_A_1.2之间生成一个changelog。”
但是,当您编写具体要查找的更改时,请列出:应用于APP_A_1.2分支本身的变更集在创建APP_A_1.2之前应用于APP_A分支的变更集在合并到创建主干1.2分支之前应用于主干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)是在TFS2010中专门添加的,目的是比QueryMerges和QueryMergesWithDetails更高的性能和健壮的性能,为了支持分支可视化工具- afaik你不需要在QueryMergesExtended中指定选项FollowRenames,因为你在分支的根上查询合并-当你获得源更改(从APP_A)的列表时,你需要检查每个变更集,看看它是否包含合并更改。如果是这样,则需要在app_a上查询这些变更集的合并。递归地执行此操作,直到遍历整个分支层次结构。
在副标题上,您可以稍后查看QueryMergeRelationships (http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.versioncontrol.client.versioncontrolserver.querymergerelationships.aspx),它为您提供了TFS2010中引入的分支对象列表(这是在源代码管理资源管理器中选择文件夹并单击转换为分支时发生的情况)。然而,如果你可以用不同的方式发现你的分支(硬编码),那么就不需要了。
希望这能有所帮助!
发布于 2012-02-29 15:20:56
是的,我自己也在解决这个问题。我发现了一个codeplex项目可以解决这个问题,不管怎样,当你在比较标签的时候。
看看这是否有帮助:http://tfslabeldiff.codeplex.com/SourceControl/changeset/view/7075#158224
我很惊讶这是多么难以找到,但TFS的文档充其量也是缺乏的。这看起来应该是显而易见的!
https://stackoverflow.com/questions/9275760
复制相似问题