Combinar correcciones de errores desde el tronco en ramas viejas

7

Ahora estamos en el proceso de cambiar de svn a git (después de un año dedicado a convencer a la gente, ¡yay!) en mi empresa.

Hasta ahora, esto es todo para mejor, pero hay una pequeña cosa que actualmente tenemos en nuestro flujo de trabajo que tampoco puedo encontrar un buen equivalente.

Actualmente, todos nuestros desarrolladores trabajan en master. Una vez cada trimestre, dividimos el maestro en la rama X.x, que más tarde se convertirá en nuestro último lanzamiento. Esto significa que nuestro repositorio svn se ve así:

  • tronco
  • ramas
    • 3.8
    • 4.1
    • 4.2
    • ...

Realmente no usamos etiquetas.

De vez en cuando, se descubre una solución urgente de errores.

La forma actual de hacerlo es:

  • Repáralo en el maestro
  • SVN fusiona el rango relevante de confirmaciones en las sucursales relevantes (Quizás nuestra última versión, quizás más).

Estamos en la industria espacial, por lo que nuestras sucursales son de larga duración y el proceso de actualización del cliente es bastante largo, por lo que hemos trabajado así hasta ahora.

Ahora, ¿cómo sería un buen equivalente en git?

Hasta ahora, he tratado de corregir el error en una rama creada desde el maestro, y luego fusionar esta rama nuevamente en el maestro y en 4.3 (por ejemplo). Lo que pasa es que la rama de hotfix contiene el historial maestro, y todas las confirmaciones entre el maestro y 4.3 también se combinan, lo que no queremos.

Cosas en las que podría pensar hasta ahora:

  • He examinado el muy exitoso Método de flujo de trabajo Git , y su solución es corregir el error en la rama de lanzamiento y fusionarlo de nuevo en lugar de hacerlo al revés. Esto podría funcionar en nuestro caso, pero sería bastante engorroso porque nos requeriría saber ya la rama más antigua en la que queremos corregir el error antes de corregirlo realmente.
  • Otra solución es arreglar en maestro, y luego seleccionar los compromisos (como lo hacemos para la combinación svn hoy). Lo molesto aquí es que, en este caso, perdemos la historia de lo que se ha fusionado en el pasado, ya que las selecciones de cerezas parecen nuevos compromisos y perdemos la relación.

Entonces, ¿cuál es la "buena" manera de hacerlo? ¿Deberíamos arreglar las confirmaciones en la historia, o elegir y hacer un seguimiento manual de lo que se ha fusionado, o incluso de otra cosa?

Si tengo poca experiencia en producción con git, estoy seguro de que me he perdido algo.

    
pregunta jlengrand 15.12.2015 - 12:46

1 respuesta

7

El flujo de Git supone que solo tiene una única versión compatible, con la rama master siempre apuntando a la última versión. Dado que admite varias versiones simultáneamente, no puede copiar ese flujo de trabajo 1: 1. Git Flow de Nvie es un muy buen ejemplo de una estrategia de bifurcación, pero debes adaptarla a tus necesidades. Lo más importante es que tendrá múltiples sucursales de versiones activas.

Cuando identifique un error, tendrá que hacer algunas pruebas para determinar todas las versiones afectadas. No es suficiente escribir primero el arreglo, luego fusionarlo nuevamente en las sucursales de lanzamiento como una revisión. Por lo general, terminará con un rango continuo de versiones afectadas. Las versiones muy antiguas pueden no contener el error, las versiones más recientes pueden haber solucionado el error accidentalmente. Deberá verificar el error en cada versión para que pueda verificar que realmente se haya ido después de la corrección. Si puede expresar el error como un testcase automatizado, es bastante sencillo encontrar la confirmación problemática a través de git bisect , o ejecutar la prueba para cada versión:

for release in 3.8 4.1 4.2
do
  git checkout $release
  if ./testcase >release-$release.log
  then echo "$release ok"
  else echo "$release AFFECTED"
  fi
done

Ahora, solías escribir la corrección en trunk / master . Esto es problemático porque la parte con errores puede haber cambiado entre versiones, por lo que un parche generalmente no se aplicará a una versión anterior. En particular, el código en master puede depender de cualquier característica disponible en el maestro, que puede no haber estado presente en versiones anteriores. Por lo tanto, tiene mucho sentido que un compromiso Git haga referencia a toda su historia, no solo al conjunto de cambios. Cuando vuelva a unirse, obtendrá toda la historia de la que depende.

El uso de cherry-pick o rebase ignora este historial y registra una nueva confirmación con el mismo conjunto de cambios, pero un historial diferente. Como se señaló, esto no funcionará si su base de código se ha desviado.

La solución "correcta" es escribir la corrección como una revisión en la versión más antigua afectada. Luego, fusiona la versión más antigua en la segunda versión más antigua. Por lo general, una versión más nueva contendría todas las confirmaciones de una versión anterior, por lo que está bien. Si las cosas han cambiado, ahora tiene la oportunidad de resolver manualmente el conflicto de combinación. Luego continúas fusionando cada lanzamiento en el siguiente lanzamiento más joven hasta que hayas terminado. Esto mantiene el historial adecuado y evita una gran cantidad de trabajo innecesario, mientras que solo requiere un esfuerzo que debe ser gastado de todos modos. En particular, esta fusión incremental lo acerca al estado de desarrollo actual en pequeños pasos.

Como un diagrama:

| o normal commit |
| x hotfix        |
| ⇘ merging       |

3.8 --o-----------------x
       \                 ⇘
4.1     o--o--o-----------x'
               \           ⇘
4.2             o--o--o-----x''
                       \     ⇘
develop                 o--o--x'''--o--o
    
respondido por el amon 15.12.2015 - 13:35

Lea otras preguntas en las etiquetas