¿Cómo manejas el código de integración de múltiples ramas / desarrolladores cada sprint?


42

Acabo de recibir una llamada retro en la que los desarrolladores expresaron su preocupación por la integración de sus historias en la rama maestra en cada sprint. Todos los desarrolladores codifican dentro de su propia rama y hacia el final del sprint se fusionan en una sola rama maestra.

Luego, un desarrollador (generalmente el mismo) tiene la tarea de asegurarse de que todo se haya integrado bien con el código de otro desarrollador (la mayoría de los cambios están en la misma página. Por ejemplo, una historia de visualización de datos, una historia de filtrado de datos y un indicador de SLA).

¿Cómo podemos reducir esta carga y facilitar la fusión de nuestro código? Desde mi punto de vista, hacer que el PO o SM priorice las historias de una manera más eficiente para que no tengamos este tipo de dependencias en el mismo sprint puede resolver algunos de los problemas. ¿Cómo abordan esto los demás? ¿O es solo parte del proceso?


18
¿No tiene una rama de desarrollo donde se realiza la integración continua?
Kayaman

13
Estoy con Kayaman aquí, la mejor práctica para esto es implementar una integración continua.
RandomUs1r

27
¡Feliz día de fusión! Cada vez que su problema es demasiado similar a algo en The Daily WTF, sabe que está en problemas.
user3067860

Combinar temprano, combinar a menudo: {escriba el código de prueba más pequeño que fallará (rojo), escriba el código de producción más pequeño que pasará (verde), refactorizará, volverá a probar, fusionará} mientras no esté terminado.
ctrl-alt-delor

1
Primer check-in gana! ¡Nunca seas el último! :-)
ChuckCottrill

Respuestas:


88

Si está utilizando Git, cada desarrollador se moverá de la developrama a su propia rama de características para asegurarse de que no se alejen demasiado de la línea de base actual. Pueden hacerlo a diario, de modo que las tareas que tardan más de un par de días permanecen sincronizadas y se combinan los problemas mientras se mantienen pequeños.

Cuando el desarrollador termina su trabajo, crea una solicitud de extracción . Cuando se aprueba, se fusiona con la developrama.

La developrama siempre debe tener un código de trabajo y estar lista para su lanzamiento en cualquier momento. Cuando usted haga realmente un comunicado, se fusionan developen mastery la etiqueta de la misma.

Si tiene un buen servidor de integración continua, construirá cada rama cuando se registren los cambios, especialmente para las solicitudes de extracción. Algunos servidores de compilación se integran con su servidor Git para aprobar o desaprobar automáticamente una solicitud de extracción si la compilación falla o las pruebas automáticas fallan. Esta es otra forma de encontrar posibles errores de integración.


73
La parte importante (que solo está implícita en su respuesta) es que las ramas deben fusionarse tan pronto como estén listas, generalmente con solo 1 a 5 confirmaciones, y no solo al final del sprint. Una rama por característica / historia, no una rama por desarrollador. Eso requiere que las historias sean realmente pequeñas, es decir, tarden como máximo dos días.
amon

@amon, de acuerdo. Se agregaron las palabras "rama característica", pero tratando de mantener esta respuesta bastante pequeña. Hay muchos buenos artículos que profundizan en este proceso.
Berin Loritsch

55
No te quedes aislado en tu propia sucursal. Así comienza el infierno de fusión. Utilice el desarrollo de la línea principal, aísle el trabajo en progreso detrás de los conmutadores de funciones u otra configuración de tiempo de ejecución.
Rob Crawford

3
@Zibbobz Mi equipo usa "Ramas de funciones" explícitas para aquellas que se tratan básicamente como la rama de desarrollo, pero solo para solicitudes de extracción y confirmaciones relacionadas con ese cambio. En general, dependiendo de cuánto tiempo tiene que permanecer separado, cada pocos días alguien combinará los cambios para desarrollarlos en la función y resolverá cualquier problema. De esa manera, las ramas son lo más similares posible cuando llega el momento de fusionarse. Como nota, esto es solo para cambios realmente importantes
refutar el

99
"aislar el trabajo en progreso detrás de los conmutadores de funciones u otra configuración de tiempo de ejecución" En su lugar, evitó fusionar el infierno al entrar en el infierno de configuración. "Combinar el infierno" es solo un problema para un desarrollador a la vez y se evita fácilmente simplemente sincronizándose regularmente, tener toneladas de configuración efímera es un infierno para todos los futuros desarrolladores para siempre.
Cubic

23

Trabajé en un equipo donde luchamos con el mismo problema. Descubrimos que cuanto menos tiempo teníamos antes de integrarnos, menos difícil se volvía. Sé que la mayoría de las personas que enseñan integración continua hablan de comprometerse cada pocos minutos; probablemente lo hicimos cada hora más o menos.

También encontramos que solo construir no era suficiente. Necesitábamos un buen nivel de cobertura de prueba para asegurarnos de no romper accidentalmente el código de los demás.


2
Esta es mi experiencia también. Realmente no importa con qué frecuencia se compromete, pero una vez que se compromete rápidamente, la integración / fusión del compromiso ahorra mucho esfuerzo en el futuro. Una vez estuve en un proyecto donde teníamos tres ramas de desarrollo divergentes, cada una con meses de trabajo. Fusionarlos no fue divertido. Aprendí mucho de ese error :)
amon

44
Sí, esto es lo que significa "integración continua". ¡Estás integrando continuamente tus cambios con los cambios de otros desarrolladores!
Rob Crawford

@Rob, de acuerdo. Mi declaración no pretendía sugerir que la integración continua no es, bueno, continua. Solo que no hicimos el ideal y aún vimos muchos beneficios al acercarnos a él.
Daniel

12
  • Mantenga sus ramas de corta duración (parece que ya lo está haciendo).
  • Deje que los resultados de su prueba hablen por sí mismos.
  • No esperes al final del sprint.

Ni siquiera necesita suscribirse a TDD para este. Todo lo que necesita son algunas pruebas que prueben que las características de sus desarrolladores funcionan correctamente. Estos podrían incluir pruebas unitarias y pruebas de integración, pero idealmente serán un par de pruebas automatizadas de extremo a extremo de las características críticas. Paquete de regresión estándar.

Luego, una vez que se haya completado la fusión, puede verificar el informe de prueba de automatización y verificar que todo se haya integrado con éxito.

Estoy de acuerdo con una de las otras respuestas donde el autor declaró que Git PR resolvería este problema haciendo que cada desarrollador fusionara su propio trabajo.

Otro punto que creo es lo suficientemente importante como para dejarlo hasta el último párrafo. Le sugiero que ejecute pruebas manuales sobre sus compilaciones nocturnas, en lugar de esperar hasta el final del sprint. Los desarrolladores deben fusionarse tan pronto como la característica esté completa para que pueda integrarse, implementarse y probarse lo antes posible.


6

No

Dependiendo de su idioma y qué archivos está editando, puede que no tenga sentido que cada desarrollador los edite en su propia sucursal. Por ejemplo, en C # descubrí que lo mejor es que solo una persona edite los archivos de diseño de la interfaz de usuario a la vez. Estos son archivos autogenerados, por lo que el código a veces se mueve sin razón aparente, y esto causa estragos en la mayoría de las herramientas de fusión.

Esto significa que algunas historias pueden bloquear otras historias hasta que se complete el trabajo de la interfaz de usuario. Y / o, se crea una nueva historia para simplemente diseñar la interfaz de usuario, y las otras historias implementan la funcionalidad. O tal vez un desarrollador hace todo el trabajo de la interfaz de usuario mientras que otros implementan la funcionalidad de esa interfaz de usuario.

En una nota relacionada, si sabe que varias historias tocarán el mismo archivo (s), es posible que desee evitar trabajar en todas ellas al mismo tiempo. No los tire a todos en el mismo sprint, o no comience a trabajar en todos ellos hasta que uno o más hayan terminado.


Honestamente, la herramienta de control de versiones en uso es más crítica para una ramificación y fusión exitosa. Incluso con el código C # y presumiblemente el código WinForms o WebForms con el que debe estar trabajando, generalmente no cambian tanto . Si lo son, quizás necesites hacer algunas maquetas antes de jugar con código. Las interfaces de usuario basadas en XAML son tan estables como el código regular y el código intermedio no se registra.
Berin Loritsch

2
El código de diseño de @BerinLoritsch WinForms puede cambiar mucho, incluso con pequeños cambios visuales. Descubrí que las líneas de código son las mismas, pero el orden es muy diferente, especialmente cuando varios desarrolladores están haciendo ediciones al mismo tiempo. Tal vez es un problema de la herramienta VCS (hemos usado varios, tal vez solo estamos usando los incorrectos), pero para nosotros es mucho más simple alterar ligeramente nuestro proceso.
mmathis

2
@BerinLoritsch Tengo que respaldar mmathis aquí al menos para los formularios ganadores (nunca usé formularios web). Al diseñador de la interfaz de usuario de winforms le encanta reordenar aleatoriamente todo el código en el archivo del diseñador en respuesta a un cambio trivial en algún lugar del formulario. A menos que deshaga manualmente los reordenamientos antes de cada confirmación (algo que puede ser fácilmente 10 o 15 minutos en un formulario complejo), el historial del archivo del diseñador es absolutamente inútil, y si 2 personas están trabajando en la interfaz de usuario del formulario a la vez resultará en Un conflicto de fusión del infierno. El bloqueo es generalmente una opción terrible, pero con winforms es realmente el menos malvado.
Dan Neely

@DanNeely, esa es solo una de las razones por las que nuestro equipo emigró del código WinForms. Otra razón es que el diseñador es terriblemente frágil, y algunas de nuestras formas complejas no se pueden editar visualmente de todos modos. Terminamos teniendo que hacer cambios directamente en el código subyacente, probablemente por eso no recuerdo demasiada agitación allí. Eso y nuestros usuarios que trabajan con pantallas de alta densidad realmente nos empujaron a WPF. Un proceso doloroso con una curva de aprendizaje alta, pero una buena recompensa al final. De todos modos, la mayoría de las historias en la cartera eran para diferentes partes de la aplicación.
Berin Loritsch

@BerinLoritsch igual aquí. Los formularios de Win pagaron una gran parte de mis facturas durante la mayor parte de una década en mi trabajo anterior, pero estaré muy feliz de no volver a tocarlos en el futuro.
Dan Neely

2

Otro enfoque posible para evitar fusiones grandes y tardías son los indicadores de características : protege sus cambios con un indicador configurable (idealmente dinámico) que evita que se activen antes de lo previsto.

Esto le permite fusionar sus cambios temprano en cualquiera de mastersus ramas de desarrollo conjunto sin romper nada. Otros desarrolladores pueden fusionar estos cambios nuevamente en sus ramas de características (o volver a crear sus ramas en consecuencia).

Como las otras respuestas ya han señalado, esto debería combinarse con una solución de integración continua.

Las banderas de características tienen beneficios adicionales (por ejemplo, hacen que sea fácil hacer pruebas A / B). Consulte este artículo de Martin Fowler para obtener más información.


0

Estamos siguiendo un enfoque de rama de desarrollo separada para cada característica, y luego estamos fusionando las ramas con una rama de QA para probar en el entorno de pruebas de integración.

Una vez que se completan las pruebas de regresión e integración, trasladamos fácilmente las funciones que están listas para usar, a la rama de lanzamiento.

Si todo va bien, fusionamos la rama de lanzamiento de nuevo con la rama maestra.


0

En pocas palabras, comprometerse y fusionarse a menudo reduce la ventana de oportunidad para los conflictos de fusión y reducirá en gran medida los conflictos. La otra parte está planeada por el líder, lo que puede garantizar aún más que el trabajo fluya sin problemas.

Las otras respuestas brindan una gran perspectiva sobre las mejores prácticas para los commits y, simplemente siguiendo estas, probablemente reducirá la gran mayoría de sus problemas de fusión. Es casi seguro que más fusiones sean necesarias, pero para un equipo más pequeño, su enfoque de sucursal por persona probablemente funcione lo suficientemente bien. Por supuesto, ¡no hace daño (mucho) entrar en prácticas más extensibles!

Sin embargo, nadie parece haber abordado una de sus preguntas más importantes: qué hacer cuando todos están tocando las mismas áreas de código. Aquí es donde es útil tener un líder que esté familiarizado con la base del código y pueda reconocer dependencias de diferentes tareas. Si no organizan el momento del trabajo y los compromisos, es probable que termine con conflictos de fusión y resolución línea por línea. Organizar las tareas \ sincronización es mucho más difícil con un equipo más grande, pero con un equipo pequeño es posible identificar estas tareas conflictivas. El líder podría incluso trasladar todas las tareas relacionadas al mismo ingeniero, para evitar el conflicto por completo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.