¿Continúas el desarrollo en una rama o en el tronco? [cerrado]


170

Supongamos que está desarrollando un producto de software que tiene lanzamientos periódicos. ¿Cuáles son las mejores prácticas con respecto a la ramificación y fusión? Cortar las ramas de lanzamiento periódico al público (o quien sea su cliente) y luego continuar el desarrollo en el tronco, o considerar el tronco como la versión estable, etiquetarlo como un lanzamiento periódicamente y realizar su trabajo experimental en las ramas. ¿Qué piensan las personas si el baúl se considera "oro" o se considera una "caja de arena"?


3
¿Se pregunta si esto se puede volver a etiquetar sin svn, ya que es bastante genérico para la gestión del control de código fuente?
Scott Saad

44
Esta parece ser una de esas preguntas "religiosas".
James McMahon el

@James McMahon: es más que realmente hay dos mejores prácticas mutuamente excluyentes, pero algunas personas piensan que solo hay una. No ayuda que SO quiera que tengas una respuesta correcta.
Ken Liu

Respuestas:


151

He probado ambos métodos con una gran aplicación comercial.

La respuesta a qué método es mejor depende en gran medida de su situación exacta, pero escribiré lo que mi experiencia general ha demostrado hasta ahora.

El mejor método en general (en mi experiencia): el tronco siempre debe ser estable.

Aquí hay algunas pautas y beneficios de este método:

  • Codifique cada tarea (o conjunto de tareas relacionadas) en su propia rama, luego tendrá la flexibilidad de cuándo desea fusionar estas tareas y realizar un lanzamiento.
  • El control de calidad debe realizarse en cada rama antes de fusionarse con el tronco.
  • Al realizar el control de calidad en cada rama individual, sabrá exactamente qué causó el error más fácilmente.
  • Esta solución se adapta a cualquier número de desarrolladores.
  • Este método funciona ya que la ramificación es una operación casi instantánea en SVN.
  • Etiquete cada lanzamiento que realice.
  • Puede desarrollar funciones que no planea lanzar por un tiempo y decidir exactamente cuándo fusionarlas.
  • Para todo el trabajo que realice, puede tener el beneficio de comprometer su código. Si trabaja solo desde la troncal, probablemente mantendrá su código sin comprometer mucho y, por lo tanto, sin protección y sin historial automático.

Si intenta hacer lo contrario y hacer todo su desarrollo en el tronco, tendrá los siguientes problemas:

  • Problemas constantes de compilación para compilaciones diarias
  • Pérdida de productividad cuando un desarrollador comete un problema para todas las demás personas en el proyecto
  • Ciclos de lanzamiento más largos, porque finalmente necesita obtener una versión estable
  • Lanzamientos menos estables

Simplemente no tendrá la flexibilidad que necesita si intenta mantener una rama estable y el tronco como el entorno limitado de desarrollo. La razón es que no puede elegir y elegir del tronco lo que desea poner en esa versión estable. Ya estaría todo mezclado en el maletero.

El único caso en particular que yo diría que haga todo el desarrollo en el tronco, es cuando está comenzando un nuevo proyecto. Puede haber otros casos también dependiendo de su situación.


Por cierto, los sistemas de control de versiones distribuidas proporcionan mucha más flexibilidad y recomiendo cambiar a hg o git.


35
Lo siento, pero esta respuesta es incorrecta. Todo desarrollo debe ocurrir en el tronco. Si tiene algo que 'aumentar' o alguna característica 'riesgosa', cree una rama de características. Las ramas se deben mantener para cada versión del producto en producción, o si hay una única versión, use una rama de integración.
Mitch Wheat

52
No estaba afirmando que esta fuera la única forma, solo que es la mejor manera. Por supuesto, si crees que tienes suficientes razones por las que piensas que estoy equivocado, entonces debes publicarlo. Al menos mi respuesta está justificada.
Brian R. Bondy

55
Esto es problemático, ya que los desarrolladores pueden trabajar mucho tiempo en una rama que está divergiendo del tronco principal. Integrar esas cosas más tarde puede producir grandes dolores de cabeza. Para mí siempre fue más fácil mantener un tronco de última generación con algunos requisitos mínimos (siempre debe compilarse) y ramificar las cosas que deberían estabilizarse para una liberación.
Mnementh

31
En respuesta a la publicación de Mnementh, creo que una buena solución es que un desarrollador debe fusionar periódicamente el tronco en su rama para que no se alejen demasiado del estado del tronco. Depende de cada desarrollador hacer esto con la suficiente frecuencia como para no tener un gran dolor de cabeza de reintegración en ningún momento.
RjOllos

8
@Mnementh eso no es excusa. Las mejores prácticas y el sentido común dicen que todos en el equipo deberían actualizar sus sucursales con el tronco. El enlace principal no está destinado a ser perfecto ni a lo que empujas a la producción, solo necesita compilarse y es por eso que en buenos entornos de desarrollo, la mayoría de los desarrolladores son muy buenos para asegurarse de que esto suceda, y si no es así, el el equipo tiene el derecho de hacerle pasar un mal rato a esa persona ... también herramientas como Cruise Control y otras configuraciones de construcción continua. ¡De eso se trata la integración continua! Tienes QA prueba tus ramas no su tronco principal.
PositiveGuy

66

He trabajado con ambas técnicas y diría que el mejor camino es desarrollar en el tronco y ramificar puntos estables como lanzamientos.

Esas personas de arriba que se oponen diciendo que tendrás:

  • Problemas de compilación constantes para compilaciones diarias
  • Pérdida de productividad cuando un desarrollador comete un problema para todas las demás personas en el proyecto

Probablemente no haya utilizado técnicas de integración continua.

Es cierto que si no realiza varias compilaciones de prueba durante el día, por ejemplo, una vez cada hora más o menos, se dejará abierto a estos problemas que rápidamente estrangularán el ritmo de desarrollo.

Al hacer varias compilaciones de prueba durante el día, las actualizaciones de la base del código principal se pliegan rápidamente para que otros puedan usarlo y también le avisa durante el día si alguien ha roto la compilación para que puedan arreglarlo antes de irse a casa.

Como se señaló, solo descubrir una compilación rota cuando falla la compilación nocturna para ejecutar las pruebas de regresión es una locura y ralentizará las cosas rápidamente.

Lea el artículo de Martin Fowler sobre Integración continua . Desarrollamos nuestro propio sistema para un proyecto importante (3,000kSLOC) en aproximadamente 2,000 líneas de Posix sh.


1
¿Qué tiene que ver la 'integración continua' con la probabilidad de que un equipo llegue tarde a su función y retrase un ciclo de lanzamiento completo? ¡Es la mejor manera de ir 'por ti'! ¡Hacer varias compilaciones por día no resuelve ningún problema potencial que no sea que usted sabe que se compila! Sus argumentos no proporcionan pruebas de que esa es una mejor manera (aunque esa es la forma en que generalmente también lo hago).
Jeach

CI es necesario para esta respuesta, pero también para Brian.
jyoungdev

2
@Jeach, hacer varias compilaciones por día te da la confianza de que se construye para que puedas ejecutar pruebas regularmente, ya sea pruebas simples de smkoke durante el día o pruebas de regresión durante la noche. Si deja la compilación hasta la compilación de la tarde para la prueba de regresión, puede retrasar todo el proyecto un día solo porque no puede compilar. Esto significa que todos los desarrolladores no podrán ver los resultados de las pruebas de regresión para el nuevo código que han enviado. Un costo bastante costoso, solo porque, por ejemplo, alguien registró un código que contenía un error de sintaxis.
Rob Wells

¿Y si una función lleva 2 meses para construir, y otro toma 6 meses para construir, hay que utilizar allí las ramas, no todo se puede comprobar en el tronco, en tales casos
Kalpesh Soni

1
@Wolf, estás confundiendo confusión con confusión, la gente crea productos, no todos trabajan para devops
Kalpesh Soni

36

Tiendo a adoptar el enfoque de "rama de lanzamiento". El tronco es volátil. Una vez que se acerca el tiempo de lanzamiento, haría una rama de lanzamiento, que trataría con más cautela. Cuando eso finalmente esté hecho, etiquetaría / etiquetaría el estado del repositorio para conocer la versión lanzada "oficial".

Entiendo que hay otras formas de hacerlo, así es como lo hice en el pasado.


19

Ambos.

El tronco se usa para la mayoría del desarrollo. Pero se espera que se realicen los mejores esfuerzos para garantizar que cualquier registro en el tronco no lo rompa. (parcialmente verificado por un sistema automatizado de compilación y prueba)

Las versiones se mantienen en su propio directorio, y solo se realizan correcciones de errores en ellas (y luego se fusionan en el tronco).

Cualquier característica nueva que va a dejar la troncal en un estado inestable o inoperante se realiza en su propia rama separada y luego se fusiona con la troncal al finalizar.


3
Estoy contigo en esto ... ¡los desarrolladores que se adhieren a un solo método todo el tiempo son el problema!
Jeach

14

Me gusta y uso el enfoque descrito por Henrik Kniberg en Control de versiones para equipos ágiles múltiples . Henrik hizo un gran trabajo al explicar cómo manejar el control de versiones en un entorno ágil con múltiples equipos (también funciona para un solo equipo en entornos tradicionales) y no tiene sentido parafrasearlo, así que simplemente publicaré la "hoja de trucos" (que se explica por sí mismo) a continuación:

texto alternativo texto alternativo

Me gusta porque:

  • Es simple: puedes obtenerlo de la imagen.
  • Funciona (y escala) bien sin demasiados problemas de fusión y conflicto.
  • Puede lanzar "software de trabajo" en cualquier momento (en el espíritu de ágil).

Y en caso de que no fuera lo suficientemente explícito: el desarrollo se realiza en "ramas de trabajo", el enlace troncal se usa para el código HECHO (liberable). Verifique el Control de versiones para múltiples equipos ágiles para todos los detalles.


Mi experiencia personal es que esto SOLO funciona para equipos pequeños, a diferencia de su comentario de 'escala'. A medida que los equipos crecen y las historias se vuelven a crear, todos los demás equipos gastan cantidades considerables de equipo haciendo fusiones. Y en proyectos muy grandes (muchos archivos y KLOC), los problemas de fusión comienzan a aparecer regularmente, especialmente cuando hay mucha volatilidad del código.
Jeach

@Jeach Nos ha funcionado bien en un gran proyecto con 5 equipos organizados en equipos principales, aunque no estoy negando que la fusión tenga un costo.
Pascal Thivent

11

Una buena referencia sobre un proceso de desarrollo que mantiene estable el tronco y hace todo el trabajo en las sucursales es el Sistema de desarrollo de máxima calidad de Divmod . Un resumen rápido:

  • Todo el trabajo realizado debe tener un ticket asociado
  • Se crea una nueva sucursal para cada ticket donde se realiza el trabajo para ese ticket
  • Los cambios de esa rama no se fusionan nuevamente en el enlace troncal principal sin ser revisados ​​por otro miembro del proyecto

Utilizan SVN para esto, pero esto podría hacerse fácilmente con cualquiera de los sistemas de control de versiones distribuidos.


10

Creo que su segundo enfoque (por ejemplo, etiquetar lanzamientos y hacer cosas experimentales en ramas, considerando el tronco estable) es el mejor enfoque.

Debe quedar claro que las ramas heredan todos los errores de un sistema en el momento en que se ramifica: si se aplican arreglos a un tronco, tendrá que ir uno por uno a todas las ramas si mantiene las ramas como una especie de liberar el terminador del ciclo. Si ya ha tenido 20 versiones y descubrió un error que se remonta a la primera, tendrá que volver a aplicar su solución 20 veces.

Se supone que las ramas son las cajas de arena reales, aunque el tronco también tendrá que desempeñar este papel: las etiquetas indicarán si el código es "dorado" en ese momento, adecuado para su lanzamiento.


8

Nos desarrollamos en el tronco a menos que los cambios sean demasiado importantes, desestabilizadores o nos acerquemos a un lanzamiento importante de uno de nuestros productos, en cuyo caso creamos una rama temporal. También creamos una rama permanente para cada lanzamiento de producto individual. El documento de Microsoft sobre la orientación de ramificación me pareció bastante útil. El tutorial de Eric Sink sobre la ramificación también es interesante, y señala que lo que funciona para Microsoft puede ser demasiado pesado para algunos de nosotros. Fue en nuestro caso, en realidad utilizamos el enfoque que Eric dice que su equipo hace.


5

Depende de tus situaciones. Usamos Perforce y generalmente tenemos varias líneas de desarrollo. El tronco se considera "oro" y todo el desarrollo ocurre en las ramas que se fusionan con la línea principal cuando son lo suficientemente estables como para integrarse. Esto permite el rechazo de características que no hacen el corte y puede proporcionar una capacidad incremental sólida con el tiempo que los proyectos / características independientes pueden recoger.

Hay un costo de integración para fusionarse y ponerse al día con las nuevas características incluidas en el tronco, pero de todos modos sufrirá este dolor. Hacer que todos se desarrollen juntos en el tronco puede conducir a una situación en el salvaje oeste, mientras que la ramificación le permite escalar y elegir los puntos en los que desea tomar las amargas píldoras de integración. Actualmente estamos ampliados a más de cien desarrolladores en una docena de proyectos, cada uno con múltiples lanzamientos que usan los mismos componentes principales, y funciona bastante bien.

La belleza de esto es que puede hacer esto de forma recursiva: una rama de gran característica puede ser su propio tronco con otras ramas que se desprenden si es así. Además, las versiones finales obtienen una nueva sucursal que le brinda un lugar para realizar un mantenimiento estable.


4

Intentar gestionar el mantenimiento del código de producción actual en línea con el nuevo desarrollo es, en el mejor de los casos, problemático. Para mitigar esos problemas, el código debe ramificarse en una línea de mantenimiento una vez que se hayan completado los esfuerzos de prueba y el código esté listo para la entrega. Además, la línea principal debe ramificarse para ayudar en la estabilización de la versión, para contener los esfuerzos de desarrollo experimental o para albergar cualquier esfuerzo de desarrollo cuyo ciclo de vida se extienda a través de varias versiones.

Se debe crear una rama que no sea de mantenimiento solo cuando existe la probabilidad (o certeza) de colisiones entre el código que serían difíciles de manejar de otra manera. Si la sucursal no resuelve un problema logístico, creará uno.

El desarrollo de liberación normal ocurre en la línea principal. Los desarrolladores entran y salen de la línea principal para el trabajo de lanzamiento normal. El trabajo de desarrollo para los parches para el código de producción actual debe estar en la rama de esa versión y luego fusionarse con la línea principal una vez que el parche haya pasado la prueba y se haya implementado. El trabajo en las sucursales que no son de mantenimiento debe coordinarse caso por caso.


4

Depende del tamaño de su esfuerzo de desarrollo. Varios equipos que trabajan en paralelo no podrán trabajar de manera efectiva, todos en el mismo código (troncal). Si solo tiene un pequeño grupo de personas trabajando y su principal preocupación es cortar una rama para que pueda continuar trabajando mientras regresa a la rama para hacer correcciones de errores en el código de producción actual que funcionaría. Este es un uso trivial de ramificación y no demasiado pesado.

Si tiene mucho desarrollo paralelo, querrá tener sucursales para cada uno de los esfuerzos, pero eso también requerirá más disciplina: asegurarse de que sus sucursales se prueben y estén listas para fusionarse. La programación se fusiona para que dos grupos no intenten fusionarse al mismo tiempo, etc.

Algunas ramas están en desarrollo durante tanto tiempo que tiene que permitir fusiones del tronco a la rama para reducir la cantidad de sorpresas cuando finalmente se fusiona de nuevo con el tronco.

Tendrá que experimentar si tiene un gran grupo de desarrolladores y tener una idea de lo que funciona en su situación. Aquí hay una página de Microsoft que puede ser algo útil: http://msdn.microsoft.com/en-us/library/aa730834(VS.80).aspx


4

Estamos utilizando el tronco para el desarrollo principal y la rama para trabajos de mantenimiento de versiones. Funciona bien Pero entonces las ramas solo deben usarse para corregir errores, sin cambios importantes, especialmente en el lado de la base de datos, tenemos la regla de que solo puede ocurrir un cambio de esquema en el tronco principal y nunca en la rama.


1
¿Por qué la regla de no cambiar la base de datos en la sucursal?
Bjorn Reppen el

Solo tenemos la regla porque hace que la fusión de versiones de nuestra base de datos sea más fácil. Eso podría deberse a la forma en que estamos usando la secuencia en los nombres de los archivos de comandos para actualizar la base de datos, estoy seguro de que si hay un método diferente, los cambios en la base de datos estarían bien para cambiar en la rama.
adriaanp

2

Si vas a trabajar a través de un ciclo de lanzamiento, gran característica, te dejarán en una sucursal. De lo contrario, trabajamos en troncales y bifurcaciones para cada versión de producción en el momento de la construcción.

Las compilaciones de producción anteriores se trasladan en ese momento a old_production_ y la versión actual de productos siempre es solo producción. Todo lo que nuestro servidor de compilación sabe sobre producción es cómo implementar la rama de producción, y comenzamos esa compilación con un disparador de fuerza.


2

Seguimos el enfoque de tronco = desarrollo actual, enfoque de rama = lanzamiento (s). En el momento del lanzamiento al cliente, ramificamos el tronco y simplemente lo mantenemos rodando hacia adelante. Deberá tomar una decisión sobre cuántos lanzamientos está preparado para admitir. Cuanto más soporte, más se fusionará con las correcciones de errores. Intentamos mantener a nuestros clientes en no más de 2 lanzamientos detrás del baúl. (Por ejemplo, Dev = 1.3, versiones compatibles 1.2 y 1.1).


1

El tronco es generalmente la línea principal de desarrollo.

Las versiones se ramifican y, a menudo, el trabajo experimental o principal se realiza en las ramas y luego se fusiona con el tronco cuando está listo para integrarse con la línea principal de desarrollo.


1

El tronco generalmente debe ser su principal fuente de desarrollo. De lo contrario, pasará mucho tiempo fusionándose en nuevas funciones. Lo he visto de otra manera y generalmente genera muchos dolores de cabeza de integración de último momento.

Rotulamos nuestros lanzamientos para que podamos responder rápidamente a emergencias de producción sin distribuir el desarrollo activo.


1

Para mí, depende del software que esté usando.

Bajo CVS, simplemente trabajaría en "troncal" y nunca etiquetaría / ramificaría, porque fue realmente doloroso hacer lo contrario.

En SVN, haría mis cosas "de última generación" en el tronco, pero cuando llegara el momento de hacer un empuje del servidor, me etiquetarían adecuadamente.

Recientemente me cambié a git. Ahora encuentro que nunca trabajo en el maletero. En su lugar, uso una rama de sandbox con nombre "new-featurename" y luego me fusiono en una rama fija de "producción actual". Ahora que lo pienso, realmente debería estar haciendo ramas "release-VERSIONNUMBER" antes de volver a fusionarme en "producción actual" para poder volver a las versiones estables más antiguas ...


1

Realmente depende de qué tan bien su organización / equipo maneje las versiones y qué SCM use.

  • Si lo que sigue (en la próxima versión) se puede planificar fácilmente, es mejor desarrollarlo en el tronco. Administrar sucursales requiere más tiempo y recursos. Pero si lo siguiente no se puede planificar fácilmente (sucede todo el tiempo en organizaciones más grandes), probablemente terminaría seleccionando commits (cientos / miles) en lugar de sucursales (varios o decenas).
  • Con Git o Mercurial, administrar sucursales es mucho más fácil que cvs y subversion. Yo iría por la metodología estable de las ramas troncales / temáticas. Esto es lo que usa el equipo de git.git. leer: http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
  • Con Subversion, primero apliqué la metodología de desarrollo en el tronco. Hubo bastante trabajo en lo que respecta a la fecha de lanzamiento porque cada vez que tenía que elegir los compromisos (mi empresa no es buena para planificar). Ahora soy una especie de experto en Subversion y sé bastante bien sobre la administración de ramas en Subversion, así que me estoy moviendo hacia la metodología estable de ramas troncales / tema. Funciona mucho mejor que antes. Ahora estoy probando la forma en que funciona el equipo git.git, aunque probablemente nos quedaremos con Subversion.

1

Aquí está el diseño SVN que prefiero:

  • raíz
    • desarrollo
      • ramas
        • característica1
        • característica2
        • ...
      • maletero
    • beta
      • etiquetas
      • maletero
    • lanzamiento
      • etiquetas
      • maletero

Todo el trabajo se realiza desde el desarrollo / troncal, excepto las características principales que requieren su propia rama. Después de probar el trabajo contra el desarrollo / troncal, fusionamos los problemas probados en beta / troncal. Si es necesario, el código se prueba con el servidor beta. Cuando estamos listos para implementar algunos cambios, simplemente fusionamos las revisiones apropiadas en la versión / troncal y la implementamos.

Las etiquetas se pueden hacer en la rama beta o en la rama de lanzamiento para que podamos realizar un seguimiento de la versión específica tanto para la versión beta como para la versión.

Este diseño permite mucha flexibilidad. También nos facilita dejar las revisiones en beta / trunk mientras fusionamos otros para liberar / trunk si algunas revisiones no pasaron las pruebas en beta.


0

El método que utilizamos es el enfoque de Perforce, que se discute extensamente en el gran libro de Laura Wingerd:

http://oreilly.com/catalog/9780596101855/index.html

Si bien el libro está centrado en el rendimiento (Wingerd es un gerente de producto de Perforce), los conceptos se pueden aplicar a cualquiera o todos los VCS.

El enfoque de rendimiento (y plataforma) nos ha servido muy bien. Se usa en muchas empresas (google, Intuit y, según he oído, el propio Microsoft Windows).

Vale la pena leer el libro.



0

No hay una respuesta única para la pregunta de la convención de subversión en mi humilde opinión.

Realmente depende de la dinámica del proyecto y la compañía que lo utiliza. En un entorno de ritmo muy rápido, cuando una versión puede ocurrir tan a menudo como cada pocos días, si intenta etiquetar y ramificar religiosamente, terminará con un repositorio inmanejable. En dicho entorno, el enfoque de sucursal cuando sea necesario crearía un entorno mucho más sostenible.

Además, en mi experiencia, es extremadamente fácil, desde un punto de vista administrativo puro, cambiar entre metodologías svn cuando lo desee.

Los dos enfoques que he sabido que funcionan mejor son la rama cuando es necesario y la rama de cada tarea. Estos son, por supuesto, una especie de opuesto exacto entre sí. Como dije, se trata de la dinámica del proyecto.


-1

@Brian R. Bondy: Tenga en cuenta que esto no es una solución una vez que su equipo alcanza una cierta cantidad de personas / tareas manejadas en paralelo en el proyecto.

Una vez que un departamento de control de calidad está involucrado en qa, los esfuerzos necesarios para proporcionar una instalación por rama en progreso son simplemente demasiado altos. Piense en SOA / Clientes / Servidores / Servicios web / Bases de datos que deben proporcionarse por sucursal .

Esta solución también carece de la etapa de integración.


Tenemos varios controles de calidad involucrados en nuestro equipo. Prueban cada característica desde un instalador completo creado desde la sucursal antes de fusionarse.
Brian R. Bondy
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.