Search code examples
tfs-sdk

TFS2010 - Track Merges


Given a changeset c and given that c contains merge operations, I would like to get a list of all changesets that have been merged and resulted in c.

For example:

  • Changeset 1 contains some edits for some files.
  • Changeset 2 contains some edits for some other files.
  • Changeset 3 is a merge of changesets 1+2 to a parent branch.

Now I would like to get changesets 1+2 from asking changeset 3 which changeset merges it contained.

I want to do this using the TFS API. I came across the versionControlServer.TrackMerges method, however I do not understand what the ItemIdentifiers that the method expects should be. Unfortunately, I cannot find an example of how to use this method. Also I'm not sure if that is really the correct one.


Solution

  • Okay, it took me really long, but I think I found out how to do this. This is the Code that will find all the "parent" changesets:

    /// <summary>
    /// Gets the changesets which have resulted in the given changeset due
    /// to a merge operation.
    /// </summary>
    /// <param name="changeset">The changeset.</param>
    /// <param name="versionControlServer">The version control server.</param>
    /// <returns>
    /// A list of all changesets that have resulted into the given changeset.
    /// </returns>
    public static List<Changeset> GetMergedChangesets(Changeset changeset, VersionControlServer versionControlServer)
    {
        // remember the already covered changeset id's
        Dictionary<int, bool> alreadyCoveredChangesets = new Dictionary<int, bool>();
    
        // initialize list of parent changesets
        List<Changeset> parentChangesets = new List<Changeset>();
    
        // go through each change inside the changeset
        foreach(Change change in changeset.Changes)
        {
            // query for the items' history
            var queryResults = versionControlServer.QueryMergesExtended(
                                    new ItemSpec(change.Item.ServerItem, RecursionType.Full),
                                    new ChangesetVersionSpec(changeset.ChangesetId),
                                    null,
                                    null);
    
            // go through each changeset in the history
            foreach (var result in queryResults)
            {
                // only if the target-change is the given changeset, we have a hit
                if (result.TargetChangeset.ChangesetId == changeset.ChangesetId)
                {
                    // if that hit has already been processed elsewhere, then just skip it
                    if (!alreadyCoveredChangesets.ContainsKey(result.SourceChangeset.ChangesetId))
                    {
                        // otherwise add it
                        alreadyCoveredChangesets.Add(result.SourceChangeset.ChangesetId, true);
                        parentChangesets.Add(versionControlServer.GetChangeset(result.SourceChangeset.ChangesetId));
                    }
                }
            }
        }
    
        return parentChangesets;
    }
    

    Edit:

    I just realized that there is a small "bug" in the above code, I used to write "VersionSpec.Latest" in the query, however: "new ChangesetVersionSpec(changeset.ChangesetId)" would be better, because then the changesets would also be tracked once the source branch has been deleted.