2012-02-14 24 views
17

Esto sigue a my previous question sobre TFS 2010 y la posibilidad de crear un registro de cambios.TFS2010: Recuperar todos los conjuntos de cambios asociados con una rama (recursión completa)

Antes usaba etiquetas para identificar una versión del programa, pero como las etiquetas no son puntos fijos en el tiempo, ahora estoy usando branches.

Así es como la jerarquía de la rama se ve así:

branch hierarchy

Como se puede ver, hay dos aplicaciones diferentes que son ramas del tronco: APP_A (aplicación A) y APP_B (aplicación B). Ambos son casi idénticos, pero hay algunas diferencias funcionales.

Aquí es el proceso para crear una nueva versión de la aplicación (por ejemplo la versión 1.3):

  1. El Main trunk se modifica (se añaden nuevas funcionalidades, correcciones de errores ...)
  2. Desde el modificado Main trunk, se crea una nueva rama: Main trunk 1.3
  3. APP_A rama podría ser modificado, por lo funcionalidades únicas de APP_A trabajarán con la modificación de v1.3
  4. APP_B rama podría modificarse, por lo funcionalidades únicas de APP_B trabajarán con la modificación de v1.3
  5. Main trunk 1.3 se fusionaron para APP_A y APP_B, por lo tanto APP_A y APP_B aplicaciones recibir las modificaciones de la Main trunk
  6. Desde el APP_A rama modificada , se crea una nueva rama: APP_A_1.3
  7. Desde el APP_B rama modificada, se crea una nueva rama: APP_B_1.3

Mi objetivo es poder generar un registro de cambios entre APP_A_1.3 y APP_A_1.2.

Por changelog me refiero a una lista de WorkItems. Cada conjunto de cambios registrado se asocia con uno o más elementos de trabajo (por ejemplo, un elemento de error). Me gustaría poder obtener la lista de todos los elementos de trabajo que se vinculó a un conjunto de cambios que ha afectado APP_A_1.3: esos conjuntos de cambios pueden provenir del Main trunk (paso 1 anterior), APP_A branch (paso 3 anterior) o incluso el APP_A_1.3 rama en sí (si las revisiones están registradas después de que se haya creado la rama).

Para obtener esta lista de elementos de trabajo, traté de conseguir la lista de todos los conjuntos de cambios que están "vinculados" a APP_A_1.2 ("ligado" = el código que se comprueba en el conjunto de cambios está ahora en la rama APP_A_1.2) y la lista de todos los conjuntos de cambios que están "vinculados" al APP_A_1.3.

Entonces, podré saber qué conjuntos de cambios están "vinculados" al APP_A_1.3 y no "vinculados" al APP_A_1.2.A partir de este subconjunto de conjuntos de cambios, obtendré todos los artículos de trabajo asociados y, por lo tanto, mi registro de cambios.

Aquí está mi problema: ¿cómo podría obtener la lista de TODOS conjuntos de cambios que están "vinculados" con una rama específica? Estoy usando la API TFS 2010 para el código C#.

La entrada de mi programa (que sería recuperar todos los conjuntos de cambios para una rama determinada) sería el nombre de la rama (por ejemplo APP_A_1.2), y la salida sería la lista de los siguientes conjuntos de cambios:

  • conjuntos de cambios aplicado sobre APP_A_1.2 propia oficina
  • conjuntos de cambios aplicados en APP_A rama antes APP_A_1.2 fue creado
  • conjuntos de cambios aplicados en Main trunk 1.2 rama antes de que se ha fusionado a APP_A
  • conjuntos de cambios aplicados en Main trunk rama antes Main trunk 1.2 fue creado

He escrito los siguientes fragmentos de código para obtener todos esos conjuntos de cambios:

// 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(); 

Incluso si RecursionType.Full se especifica, el código anterior solo devuelve conjuntos de cambios que se registraron en la rama APP_A_1.2. Esto es idéntico al comando "Historial" en la vista del Explorador de código fuente en Visual Studio.

Luego probé el siguiente fragmento de código:

// 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(); 

Esto devuelve conjuntos de cambios que han sido analizados en el APP_A_1.2 rama + aquellos que fueron cheked-in en APP_A rama antes APP_A_1.2 fue creado. Mucho mejor, pero no suficiente. No puedo encontrar una manera de hacer que la recursión funcione con las ramas que están "arriba" APP_A (Main trunk en mi caso) ...

¿Alguien tiene una idea?

Además, cualquier mejor idea para obtener el registro de cambios entre dos ramas es bienvenido ... Thx.

+1

¡Gran pregunta! El cajero automático está atascado con la forma de recuperar con precisión los conjuntos de cambios. Una vez que los obtenga, considere este fantástico artículo de B.Hodges, que lo ayudará a correlacionar una lista de conjuntos de cambios con una lista de elementos de trabajo: http://blogs.msdn.com/b/buckh/archive/2012 /02/01/listing-the-work-items-associated-with-changesets-for-a-path.aspx – pantelif

Respuesta

2

Finalmente se me ocurrió una solución simple. No estoy totalmente satisfecho con esto, ya que en realidad parece un algoritmo de fuerza bruta, pero al menos funciona.

Lo que hago es:

1) Obtener la lista de cada conjunto de cambios que se aplica sobre la raíz misma de mis ramas TFS (es decir, la "ruta padre" de Main Trunk):

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

2) Para cada conjunto de cambios recuperado, llamo al TrackMerges para ver si el conjunto de cambios impacta de alguna manera en mis ramas. TrackMerges es capaz de decirme si se aplica un conjunto de cambios específico en las ramas que especifico como parámetro de la función (devolverá el ID del conjunto de cambios de destino en estas ramas). Si se aplica un conjunto de cambios en la rama de destino (en mi caso APP_A_1.3) y no en la rama fuente (APP_A_1.2), significa que definitivamente es algo nuevo en mi rama 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) Ahora es muy fácil de conseguir mi lista de cambios (la lista de elementos de trabajo) de la lista de "nuevos conjuntos de cambios":

// 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)); 
     } 
    } 
} 

no creo que es el mejor enfoque posible, pero funciona bien y sigue siendo simple. Además, no tuve que codificar nada (nombres de sucursales/jerarquía) así que no está mal IMO. Espero que ayude a alguien.

3

primero déjame primero hacer una pregunta. En la parte superior de la publicación, escriba: "Mi objetivo es poder generar un registro de cambios entre APP_A_1.3 y APP_A_1.2."

pero luego cuando se escribe que cambia específicamente que busca que lista: conjuntos de cambios aplicados en la misma rama APP_A_1.2 conjuntos de cambios aplicados en la rama APP_A antes APP_A_1.2 fue creado conjuntos de cambios aplicados en el tronco principal de la rama 1.2 antes de que se se ha fusionado con APP_A conjuntos de cambios aplicados en la rama Troncal principal antes de crear Tronco principal 1.2

Esta no es una lista válida porque le dará todos los cambios que contribuyeron a APP_A_1.3, APP_A_1.2, 1.1 y así sucesivamente al comienzo del repositorio.

No puedo probar mi enfoque en este momento, pero esto es lo que haría: - QueryHistory para obtener todos los cambios registrados directamente en la rama 1.3 - use QueryMergesExtended para seguir las fusiones en esta rama. QueryMergesExtended (http://msdn.microsoft.com/en-us/library/ff736485.aspx) se agregó en TFS 2010 específicamente para ser mucho más eficaz y sólido que QueryMerges y QueryMergesWithDetails, con el fin de admitir las herramientas de visualización de sucursales - afaik no necesita especificar la opción Seguir nombres en QueryMergesExtended porque consulta fusiones en la raíz de la rama - cuando obtiene una lista de cambios de origen (de APP_A) necesita verificar cada conjunto de cambios para ver que contiene cambios de fusión. Si es así, debe consultar fusiones en app_a para esos conjuntos de cambios. Hazlo recursivamente hasta que camines por toda la jerarquía de rama.

En el tema lateral, puede consultar más adelante las QueryMergeRelationships (http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.versioncontrol.client.versioncontrolserver.querymergerelationships.aspx) que le proporciona la lista de objetos de sucursal introducida en tfs 2010 (esto es lo que sucede cuando en Source Control Explorer selecciona la carpeta y hace clic en Convertir en bifurcación). Sin embargo, si puede descubrir su sucursal de manera diferente (codificarlos) no es necesario.

Espero que esto ayude!

+0

Hola, no entiendo por qué la lista que mencioné me daría los conjuntos de cambios aplicados en 'APP_A_1.3 '. Estoy de acuerdo con 'APP_A_1.2' y' APP_A_1.1' (esto es lo que espero), pero no veo cómo un conjunto de cambios que solo se aplica en 'APP_A_1.3' aparecerá en una de las listas. Además, he probado 'QueryMergesExtended' pero no devuelve todos los conjuntos de cambios (por ejemplo, aplicado en' APP_A_1.3', devuelve conjuntos de cambios de 'APP_A' pero no de' Main Trunk'). – ken2k

+0

Puedo usar 'QueryMergeRelationships' para descubrir mis ramas y luego llamar varias veces' QueryMergesExtended', esto debería funcionar. También encontré la forma de 'TrackMerges', lo publicaré pronto como otra respuesta. Voté tu respuesta porque es útil, gracias. – ken2k

1

Sí, trabajando en este problema yo también. Encontré un proyecto codeplex que lo resuelve, cuando difundes etiquetas, de todos modos.

ver si esto ayuda: http://tfslabeldiff.codeplex.com/SourceControl/changeset/view/7075#158224

Me sorprendió bastante lo difícil que era encontrar, pero la documentación para el TFS es deficiente en el mejor. ¡Parecía que debería ser obvio!

+0

Hola, Sharon, creo que lo que propones no es atravesar el historial de la sucursal, en otras palabras, no recuperará recursivamente los conjuntos de cambios entre diferentes ramas. – pantelif

Cuestiones relacionadas