2008-09-16 9 views
25

Estoy trabajando en un proyecto con un equipo donde nos registramos temprano y con frecuencia. Los registros individuales se completan a satisfacción del desarrollador que realiza el cambio (incluidas las pruebas cuando sea posible), pero a veces la dirección del trabajo cambia ligeramente y los compromisos previos deben revertirse y realizarse de otra manera. O bien, el código auxiliar se completa en confirmaciones posteriores.Extraiga los cambios relevantes para la revisión del código

Cuando llega el momento de revisar el código, hay una secuencia de confirmaciones todas etiquetadas con el mismo número de identificación de seguimiento de errores. Es fácil obtener una lista de dichos cambios. Cuando un revisor revisa los cambios uno por uno, a veces habrá una confirmación A que se deshace o modifica mediante una confirmación posterior B como parte de la misma revisión. Esto puede hacer que la revisión sea más difícil.

Si solo un desarrollador estuvo trabajando en el archivo durante la duración del cambio, entonces es fácil hacer una diferencia entre el estado original del archivo y el estado final del archivo. El problema surge cuando otro desarrollador hace cambios no relacionados en el mismo archivo, o incluso en las mismas funciones.

¿Cómo manejas esta situación? ¿Existen herramientas que, dadas una secuencia de parches a un archivo, puedan dar el equivalente moral de una diferencia entre la primera y la última versión, pero solo incluye un subconjunto de esos parches?

Ahora que lo pienso, podría crear una sucursal temporal en git comenzando desde antes del primer cambio relacionado, y seleccionar cuidadosamente los cambios relevantes para la revisión. Con suerte, no habrá demasiados conflictos que deban resolverse (y si los hay, todo el lote debería revisarse de una vez). ¿Alguna otra idea?

Más información: Esto pasa a ser un gran sistema heredado donde un solo cambio puede tocar varios archivos. Los archivos son grandes y crudos, demasiado grandes para simplemente revisar el producto final sin una indicación de lo que podría haber cambiado.

Respuesta

16

Uno de los enfoques (usando la terminología de la subversión, pero enfoques similares deben trabajar con otros sistemas, también):

Comprobar una copia de trabajo a una revisión justo antes de los primeros cambios. A continuación, combine todas las confirmaciones relacionadas en su copia de trabajo.

Ahora tiene una copia de trabajo que difiere de su base solo por los cambios relevantes. Puede revisar esto directamente o crear un parche para su revisión.

Si algún cambio no relacionado después de la revisión base se superpone con los cambios revisados, puede obtener un conflicto de combinación, pero esto debería ser raro.

+0

Gracias, este parece ser el enfoque más sólido para nuestra situación. –

+0

De [Jefromi] (http://stackoverflow.com/a/3512492/165495) - El siguiente comando extraerá los cambios de un solo autor en una rama: 'git cherry-pick $ (git log --pretty =% H --author = Alice first_commit..second_commit) '- – Casebash

8

Creo que debe hacer una bifurcación para hacer los cambios. Ver my post here.

+1

Hemos elegido comprometer el desarrollo incremental en el troncal para evitar el problema del "big bang" en el que un desarrollador tarda semanas o más en desarrollar una solución, y luego lanza todo al mismo tiempo. Por supuesto, esto sería después de la revisión, pero hacer confirmaciones frecuentes ayuda con las pruebas de integración. –

+0

¿a qué te refieres con eliminar todo al mismo tiempo? –

+0

Cuando un desarrollador está trabajando en un elemento de trabajo en una sucursal, están aislados del resto del equipo. Puede ser un trabajo perfecto en la sucursal, pero cuando se fusiona en el tronco existe la posibilidad de problemas de integración. Los compromisos frecuentes con el tronco ayudan a identificar tales problemas antes. –

0

Uh, solo mira el último estado del archivo.

(. La ramificación para cada cambio es un PITA No lo haga.)

+0

Desafortunadamente, estamos trabajando en un sistema heredado con enormes archivos fuente crudos que son miles de líneas largas No es posible simplemente mirar el estado actual del archivo y discernir qué sucedió; es probable que el revisor no haya visto el resto del archivo de todos modos. Diffing es requerido. –

3

Resulta puede hacerlo bastante bien en IntelliJ IDEA si tienes esa herramienta:

Seleccione Versión Control | Mostrar vista de cambios

En el lado izquierdo, selecciona el repositorio y haz clic en todas las revisiones que quieras revisar.

En el panel de la derecha, obtendrá una lista de todos los archivos que se ven afectados por las revisiones que ha seleccionado. Cuando eliges "diff", verás los cambios internos en los conjuntos de cambios seleccionados. re-trabajos internos que se producen dentro de las confirmaciones no se muestran (como es de esperar)

+0

Instalé la última IntelliJ IDEA (Community Edition 9.0.1) y esta parece una muy buena característica. Es * casi * hace todo lo que queremos para las revisiones.Al seleccionar múltiples commits no adyacentes en el panel izquierdo, de hecho solo se muestran los archivos afectados por esos cambios en el panel derecho (eso es bueno). Sin embargo, al visualizar la diferencia asociada para un archivo individual, parece que la diferencia mostrada es la diferencia total entre la primera confirmación seleccionada y la última seleccionada. Por lo tanto, esto incluye los cambios de las confirmaciones intermedias que pasaron a tocar el (los) mismo (s) archivo (s). –

+0

Ya no uso la subversión, pero creo que al menos se puede obtener la diferencia sin el otro historial entrelazado. Pero, de nuevo (incluso con git) todavía no estoy del todo seguro del valor semántico de esa vista. Es casi como si uno fingiera que el código vive en el vacío. Pero esa es una discusión diferente – krosenvold

0

Ver nuestra http://www.semdesigns.com/Products/SmartDifferencer/index.html de una herramienta que está parametrizada por la gramática del lenguaje, y produce los deltas en términos de los elementos del lenguaje (identificadores, expresiones, declaraciones , bloques, métodos, ...) insertados, eliminados, movidos, reemplazados o con identificadores sustituidos en forma consistente. Esta herramienta ignora el reformateo de espacios en blanco (por ejemplo, diferentes saltos de línea o diseños) y valores semánticamente indistinguibles (por ejemplo, sabe que 0x0F y 15 tienen el mismo valor).

Esto no desenredará dos conjuntos de cambios realizados por razones fundamentalmente diferentes. Pero minimizará el tamaño de los deltas que tiene que inspeccionar, y eso seguramente ayudará a .

Usted dice que los archivos tienen miles de líneas de longitud. Esto suena como COBOL. Existe una herramienta de diferenciación inteligente para C#, PHP, Java, C++ ... y COBOL, con ejemplos para la mayoría de estos en el sitio web.

+2

"Dices que los archivos tienen miles de líneas de longitud. Esto suena como COBOL". ¿Qué? ¿Nunca ha visto archivos .cpp largos de 3.000 líneas? –

+0

Claro que sí, incluso he escrito algunos. Y, de hecho, todo el mundo ha visto enormes archivos escritos en todos los idiomas inventados (tal vez no para APL pero luego ...) Sin embargo, el OP dijo "gran sistema heredado" e implícito * todos * sus archivos eran bastante grandes, así que supuse . No se han hecho muchos daños si he adivinado mal, pero solo quería asegurarme de que el OP entendiera que también había soluciones para COBOL. –

+0

El sistema en cuestión está realmente escrito en Ada. Lamentablemente, Smart Differencer que citó no parece respaldar eso. Ya tratamos de minimizar los cambios textuales para reducir los conflictos porque hay una rama para cada cliente, con cambios que regularmente se transfieren entre las sucursales (por otros, no por nuestro equipo). Por lo tanto, los especialistas en CM aguas arriba aprecian mucho los cambios textuales mínimos. –

1

Desde el punto de vista de Subversion

Teniendo en cuenta sus necesidades correría por las revisiones de código se diferencian contra una etiqueta de la última revisión; es decir, diferencia entre dos etiquetas.

1

Si tiene la capacidad de cambiar los sistemas de control de fuente, puede considerar seriamente git (o mercurial u otra herramienta similar).

Cada desarrollador crea su propio repositorio local.

Para cada error en el que trabajan, crean una rama.

Cuando terminan los cambios, pueden jugar con su historial utilizando los comandos de rebase para agrupar los cambios en puntos de control coherentes.

El desarrollador luego envía el conjunto de cambios modificado para su revisión.

El integrador o revisor puede entonces aceptar los cambios tal como están, seleccionarlos para captar lo que desean conservar y/o hacer más reajustes para separar las confirmaciones que no deberían haber sido agrupadas.

+0

¿Esta metodología se describe con más detalle en alguna parte? Me gustaría aprender más. –

0

El paquete patchutils contiene una herramienta combinediff que puede "crear un parche unificado acumulativo a partir de dos parches incrementales".

1

Haría prácticamente lo que sugeriste. Crea una rama de revisión. Obtenga los desarrolladores cuyos cambios se están revisando para hacer el trabajo de selección en esa rama. Difiere la raíz de la rama con la cabeza.

Probablemente también crearé una pequeña herramienta para tomar todos los registros que coincidan con una etiqueta de identificación de seguimiento de errores determinada y mezclarlos en una secuencia de comandos aproximada para hacer la selección de cereza. Definitivamente le daría al usuario la oportunidad de editar este script antes de ejecutarlo, ya que apostaría a que algunas cosas se etiquetan mal.

Haga la reseña en la sucursal. Haga cualquier edición en la rama. Cherry recoge los cambios de nuevo en el maletero. Deseche la rama de revisión si ya no la quiere.

0

Si usted es un desarrollador .NET, puede encontrar NDepend code diff capabilities útil para tal escenario.Descargo de responsabilidad: soy uno de los desarrolladores de la herramienta

Básicamente NDepend puede analizar una base de código y crear y luego conservar una instantánea del código. Se pueden comparar dos instantáneas, tomadas en dos momentos diferentes. Entonces, NDepend permite escribir code query over LINQ (CQLinq) para pedir nuevos métodos/clases, métodos eliminadas/clases, métodos/clases donde se cambió el código ... tan fácilmente como la escritura:

from m in Application.Methods where m.CodeWasChanged() select m 

Luego, puede refinar su búsqueda de código y pedir para ciertas propiedades, como si el nombre del método contiene la palabra Extracto y tienen más de 30 líneas de código:

from m in Application.Methods 
where m.CodeWasChanged() && m.NameLike("Extract") && m.NbLinesOfCode > 30 
select m 

Además, NDepend puede plug to any text diff tool. El usuario puede comparar las 2 versiones del método o clase modificado.

Otra buena capacidad, es conectar NDepend a RedGate Reflector, descompilar las 2 versiones del método/clase y comparar estas 2 versiones con una herramienta de diferencia de texto. Esta capacidad puede ser especialmente útil en su escenario, porque de esta manera está haciendo diff de código solo en un único método o clase, incluso si está realmente anidado en un gran archivo fuente.

Además, para evitar escribir la consulta a sí mismo, el panel de búsqueda por cambios generan tales consulta código en diff para usted:

NDepend Search by Changes Panel

Esperanza este enfoque original puede ayudar.

Cuestiones relacionadas