¿Qué tiene de difícil la fusión de SVN?

28

Posible duplicado:
soy un geek de Subversion, ¿por qué debería considerar o no considerar Mercurial o Git o cualquier otro DVCS?

De vez en cuando, escuchas a alguien decir que el control de versión distribuido (Git, HG) es inherentemente mejor que el control de versión centralizado (como SVN) porque la fusión es difícil y dolorosa en SVN. La cuestión es que nunca tuve problemas para fusionarme en SVN, y dado que solo escuchas esa afirmación hecha por los defensores de DVCS, y no por los usuarios reales de SVN, tiende a recordarme esos anuncios desagradables en la televisión donde trata de venderte algo que no necesitas haciendo que los torpes actores pretendan que lo que ya tienes y funciona bien es increíblemente difícil de usar.

Y el caso de uso que siempre se menciona es volver a fusionar una sucursal, lo que nuevamente me recuerda a esos anuncios de productos de moda; si sabes lo que estás haciendo, no deberías (y nunca deberías) volver a fusionar una sucursal en primer lugar. (¡Por supuesto, es difícil de hacer cuando estás haciendo algo fundamentalmente incorrecto y tonto!)

Entonces, descontando el ridículo caso de uso de Strawman, ¿qué hay en la fusión de SVN que es inherentemente más difícil que la fusión en un sistema DVCS?

Mason Wheeler
fuente
66
Todavía tengo que trabajar en un entorno en el que se fusionen sucursales de meses de duración y utilicen el control de versiones distribuido. Los únicos lugares en los que he trabajado que tienen ramas tan longevas utilizan TFS / Subversion. Espero que ramas tan longevas también sean difíciles de fusionar con DVCS.
Oded
13
@MasonWheeler Estoy perplejo. ¿Para qué utilizas un VCS? He visto y leído que una (de las muchas) prácticas recomendadas es tener ramas de características. La fusión de nuevo a la troncal es obligatoria en ese caso. ¿O entendí mal algo? (sí, la metáfora del árbol se rompe, pero no fue tan útil comenzar con la OMI)
Andres F.
99
@MasonWheeler: Creo que estás tomando la analogía del árbol demasiado literalmente.
cuál es el
8
@MasonWheeler, ¿de cuántos entornos de desarrollo diferentes tiene experiencia, si nunca ha oído hablar de volver a fusionarse? Algunas tiendas tienen un tronco estable y ramas experimentales, en cuyo caso la recolección de cerezas exitosas de regreso a establos es un evento regular.
itsbruce

Respuestas:

25

Es porque svn carecía de las estructuras de datos adecuadas para determinar con precisión el último ancestro común de las dos ramas. Eso no es un gran problema para una rama que solo se fusiona una vez, pero puede causar muchos conflictos de fusión erróneos en situaciones en las que varias ramas se fusionan varias veces.

No sigo svn muy de cerca, pero entiendo que esos problemas técnicos particulares se han solucionado en versiones recientes. Sin embargo, no se solucionó lo suficientemente temprano como para disipar el mito, y las personas que probaron DVCS para las fusiones se han quedado con él por otras razones.

Karl Bielefeldt
fuente
47

si sabes lo que estás haciendo, no deberías (y nunca deberías) volver a fusionar una sucursal en primer lugar. (¡Por supuesto, es difícil de hacer cuando estás haciendo algo fundamentalmente incorrecto y tonto!)

Y ahí radica la fuente de su confusión y todo el problema en general.

Dices que fusionar ramas es "fundamentalmente incorrecto y tonto". Bueno, ese es exactamente el problema: estás pensando en las ramas como cosas que no deberían fusionarse. ¿Por qué? Porque eres un usuario SVN que sabe que fusionar sucursales es difícil . Por lo tanto, nunca lo haces y animas a otros a que no lo hagan. Usted ha sido entrenado para evitar la fusión; Ha desarrollado técnicas que utiliza para evitar la fusión.

Soy un usuario de Mercurial. Incluso en mis propios proyectos, donde soy el único desarrollador, fusiono sucursales todo el tiempo . Tengo una rama de lanzamiento, en la que puse una solución. Bueno, fusiono eso nuevamente en la línea principal para que la solución vaya allí.

Si estuviera usando SVN, adoptaría una estructura completamente diferente de la base de código. ¿Por qué? Porque SVN hace que las fusiones sean difíciles y, por lo tanto, desarrollas modismos y técnicas para evitar hacer fusiones complejas.

Los DVCS facilitan las fusiones complejas porque son el estado predeterminado . Todo es una rama, más o menos, en un DVCS. Por lo tanto, toda su estructura está construida desde cero para facilitar la fusión. Esto le permite desarrollar un flujo de trabajo que usa la fusión a diario, en lugar del flujo de trabajo SVN donde nunca usa la fusión.

El hecho simple es este: debe acercarse a un DVCS de una manera diferente que SVN. Debería usar los modismos apropiados para estos tipos muy diferentes de sistemas de control de versiones. En SVN, adoptas modismos que no implican fusión porque las fusiones son difíciles. En DVCS, adoptas expresiones idiomáticas que con frecuencia usan fusiones porque no son gran cosa.

Herramienta adecuada para el trabajo correcto.

La cuestión es que el flujo de trabajo centrado en la fusión es mucho más agradable y fácil de usar que el flujo de trabajo de estilo SVN donde no se fusionan las cosas. Es más fácil ver cuándo se introdujo algo de la rama de lanzamiento en la rama de desarrollo. Es más fácil ver las diversas interacciones entre las ramas. Es fácil crear ramas de prueba para cosas, luego cortarlas si la prueba no funciona. Y así.

Realmente, Joel explica esto mucho mejor que yo . Deberías tener una buena lectura de eso.

Nicol Bolas
fuente
15
@Mason: ¿Cómo es que eso no es entrenamiento? Usted fue entrenado para usar SVN en un estilo SVN. Y el estilo SVN es no usar la fusión. Por lo tanto, fue entrenado para no usar o incluso considerar fusionar cosas. Por eso nunca se te ocurrió; porque usaste un sistema que lo hace difícil.
Nicol Bolas
55
Hay una gran diferencia entre "no entrenado para" y "no entrenado para".
Mason Wheeler
8
@MasonWheeler: No, no lo hay. Si no se le enseña correctamente cómo hacer algo, entonces está capacitado implícitamente para no hacerlo. No está en su repertorio de expresiones idiomáticas que puede emplear para resolver un problema. Por lo tanto, no puede usarlo para resolver problemas. El efecto no es diferente de que le digan que no se fusione, porque incluso si quisiera, no sabe cómo. La forma en que descartas un buen argumento como "el mismo terreno viejo y cansado" es evidencia de esto. No piensas en fusionar como una herramienta; piensas en ello como la excepción o algo inusual. Algo para ser cuestionado en lugar de ser usado.
Nicol Bolas
99
@MasonWheeler: ¿Quién eres tú para decidir " lo están haciendo mal "? No utiliza DVCS, por lo que no tiene experiencia con el flujo de trabajo de DVCS. No tienes idea de si es útil para los programadores o no, ya que no tienes experiencia con él. Entonces, ¿qué autoridad tienes para decir que está "mal" solo porque SVN no lo permite? Es como decir que las clases, las funciones virtuales y las plantillas están mal porque C no las tiene.
Nicol Bolas
3
@MasonWheeler: ¿ así? : P . La ramificación y fusión de SVN hace lo mismo: la metáfora ya está rota. No veo realmente cómo algo como esto es tan difícil de entender, especialmente si incluye alguna sensata cometen los comentarios ..
naught101
21

No hay nada demasiado difícil sobre la fusión de SVN ... más ... si sigues la filosofía correcta

Lo que veo en la mayoría de las otras respuestas parece provenir de personas que no han usado SVN en mucho tiempo. Como alguien menciona con precisión: "no se solucionó lo suficientemente temprano como para disipar el mito".

Desde mi experiencia actual de usar SVN 1.6 a 1.8 en un proyecto heredado que heredé recientemente, SVN ha recorrido un largo camino para hacer que la fusión sea mucho más fácil. Sin embargo, no es infalible, y creo que no sufre fácilmente que los usuarios se desvíen del uso previsto.

Si bien conocía a SVN bastante bien y, mientras tanto, también había probado Mercurial para proyectos personales, nunca había hecho muchas ramificaciones en SVN antes de este proyecto. Hubo un poco de prueba y error y tuve muchos conflictos de fusión inesperados cuando comencé.

En última instancia, sin embargo, me di cuenta de que cada vez que recibía uno (u otro problema), era porque no había hecho las cosas correctamente (también conocido como "la forma SVN" - posiblemente, la forma correcta de control de versiones). Creo que aquí es donde radica la dificultad: no puedes hacer lo que quieras de una manera desorganizada y esperar que SVN funcione perfectamente, especialmente con fusiones. Las fusiones requieren una disciplina rigurosa de los usuarios antes de mostrar su verdadero poder.

Aquí hay cosas que he notado que son recomendaciones sólidas, si no requisitos, para un uso limpio de las fusiones:

  • Use una versión reciente de SVN (1.6 y superior en mi opinión). Cada vez se realizan más automatización y controles por usted.
  • Utilice la estructura predeterminada "tronco, ramas, etiquetas" y aplique su filosofía (no se comprometa con las etiquetas). SVN no comprobará nada por ti. Si usa una etiqueta como una rama (ese es el estado en el que encontré el repositorio del proyecto), aún puede funcionar, pero debe ser coherente.
  • Sepa qué ramas son y cuándo crearlas. Lo mismo con las etiquetas.
  • Mantenga las ramas laterales actualizadas con su rama de origen (generalmente troncal, pero puede ramificarse desde cualquier rama técnicamente). Esto es obligatorio SI desea que SVN haga auto-fusiones. SVN 1.8 en realidad le impide fusionarse automáticamente si las cosas no están actualizadas, y también si tiene modificaciones pendientes en su copia de trabajo (este comportamiento parece haber desaparecido nuevamente en 1.8.5).
  • Realiza los compromisos "adecuados". Solo deben contener modificaciones en un concepto muy específico. Tanto como sea posible, deben contener una pequeña cantidad de cambio. Usted no quiere tener una única confirmación contener alguna corrección sobre dos errores independientes, por ejemplo. Si ya ha corregido ambos y están en el mismo archivo, debe almacenar los cambios de un error para que pueda confirmar solo los cambios del otro primero y luego confirmar el segundo conjunto de cambios. Tenga en cuenta que TortoiseSVN permite esto fácilmente a través de "Restaurar después de confirmar".
    • Hacerlo hace posible revertir un conjunto de cambios independiente específico Y hace posible fusionar dicho conjunto en otra rama. Sí, SVN le permite fusionar revisiones seleccionadas.
  • Si alguna vez usa sub-ramas (bifurcando del tronco, luego bifurcando esa nueva rama), respete la jerarquía. Si actualiza la sub-rama con el tronco o viceversa, le va a doler un poco. Las fusiones deben estar en cascada hacia abajo o hacia arriba en la jerarquía.
    • Después de unos meses de experimentar, puedo garantizar que esta podría ser la parte más importante. Intenté crear dos sub-ramas del mismo tronco y luego fusionar bits entre las sub-ramas, o, a veces, entre las sub-sub-ramas de ambos lados. Esto puede disparar SVN (o el usuario). Puede funcionar bien si está fusionando revisiones específicas. La fusión automática puede tener problemas con ella.
    • He tenido problemas específicamente al sincronizar la sub-rama A con la troncal, y luego intentar fusionar algo de la sub-rama A en la sub-rama B. SVN parece pensar que la revisión "sincronizar desde la troncal" debería fusionarse legítimamente en la sub-rama B y esto lleva a una masa de conflictos.
  • En la medida de lo posible, fusionarse desde la raíz de la rama. De lo contrario, SVN sólo mantendrá un registro de las fusiones realizadas para la sub-carpeta y cuando se hace tratar de auto-fusión de la raíz, se pueden obtener advertencias sobre la falta de revisiones sin combinar. Se puede solucionar simplemente fusionándolos desde la raíz, pero es mejor evitar la confusión.
  • Ten cuidado con qué rama te comprometes. Si usa Switch para que su copia de trabajo apunte a varias ramas a lo largo del tiempo, asegúrese de dónde se compromete.
    • Es especialmente malo si realmente no quieres el cambio en esa rama. Todavía no lo tengo claro, pero dependiendo de cómo lo elimine / transfiera a la rama correcta (revertir, fusionar), puede obtener algo desordenado. Es reparable, pero tendrá que fusionar revisión por revisión para evitar o resolver conflictos potenciales de inmediato, o tendrá que arreglar un conflicto posiblemente más complejo después de la fusión automática.
  • No mantenga las ramas intactas por mucho tiempo. En realidad, no es cuestión de tiempo, sino de cuántas revisiones se comprometieron con la rama y el tronco y cuánto cambiaron en ellas. Las fusiones entre dos ramas, las combinaciones de 3 vías, siempre se comparan con la revisión común más reciente entre las ramas. Cuantos más cambios intermedios, más cambios fallará la fusión automática. Esto es, por supuesto, mucho peor si cambió la estructura de su código mientras tanto (archivos movidos o renombrados).

Si no sigue lo anterior, es muy probable que tenga conflictos. Siempre son solucionables, pero no son terriblemente divertidos para pasar el tiempo.

Ah, una cosa más sobre la fusión donde, de todo lo que he leído y probado, SVN realmente apesta: archivos / carpetas eliminados / movidos / renombrados. Aparentemente , SVN todavía no puede lidiar con un archivo que se renombra, elimina o mueve en una rama, y ​​su versión original se modifica en otra rama ... y luego se fusionan. Simplemente no sabrá a dónde se dirigió el archivo de una manera y "olvidará" los cambios de la otra manera. Obviamente, un cambio no tiene solución (puede eliminar o cambiar el archivo, no puede hacer ambas cosas), pero la aplicación de cambios a los archivos movidos / renombrados debería funcionar y no funciona. Esperemos que esto se arregle pronto.

Entonces, en general, ¿es fácil la fusión de SVN? Supongo que no. No de una manera despreocupada, seguro. ¿Es malo ? No lo creo. Solo te escupe en la cara cuando lo usas de manera incorrecta y no piensas lo suficiente sobre lo que estás haciendo.

Basado en esto, puedo ver por qué la gente podría preferir Mercurial (por ejemplo), ya que es un poco más indulgente con estas cosas desde mi experiencia y tenía todo automatizado desde el primer momento (al menos desde las primeras versiones con las que comencé). Sin embargo, SVN se ha recuperado bastante, por lo que ya no es digno de tanta embestida.

leokhorn
fuente
Conflictos de árbol: sí, SVN tiene dificultades con estos, aunque TBH también lo hace con cualquier otro SCM. Git tiene algunas heurísticas para tratar de averiguar si los archivos que han sido renombrados o movidos son los mismos, pero no siempre (¡no se puede!) Hacerlo bien. Creo que SVN debería esforzarse para que la resolución de estos conflictos sea más fácil de entender.
gbjbaanb
@gbjbaanb: Ofrece "Reparar movimiento" como lo hace Mercurial, aunque no ofrece heurística. Debe decirle qué archivos eliminados y agregados son, de hecho, los mismos. Definitivamente margen de mejora.
leokhorn
Todo esto suena genial cuando eres la única persona que trabaja en el proyecto ... Pero si tienes un equipo de buen tamaño y todos lo están utilizando, la "forma SVN" (que nadie parece estar de acuerdo exactamente en qué es eso) se fusiona siguen siendo una PITA. El hecho es que svn realmente no es tan compatible con el flujo de trabajo de ramificación. La "forma SVN" sería ni siquiera crear ramas y usar un SDLC en cascada. Dicho todo esto, he tenido problemas con las fusiones de Git en el pasado en grandes proyectos con varias personas trabajando en él. Pero, todavía parecían ser mucho menos dolorosos.
ryoung
Mi experiencia es que si está trabajando con personas a las que no les importa cómo funciona el sistema de control de versiones, SVN es mucho más fácil de usar en el día a día. He trabajado solo en unos pocos equipos de DVCS, pero invariablemente un número considerable del equipo no tiene un buen comportamiento de control de revisión y contamina el repositorio para todos. En Subversion, los no entrenados generalmente se mantienen alejados de las sucursales, por lo que consiguen que los "expertos" lo hagan por ellos y se los gestiona adecuadamente. De acuerdo, esta experiencia es solo mía y preferiría trabajar solo con programadores que supieran cómo funcionaban sus herramientas ...
dash-tom-bang
5

Los modelos de datos internos son fundamentalmente diferentes.

Básicamente, en SVN, cuando miras el historial de una rama, solo ves lo que ha sucedido en esa rama. Entonces, cuando se fusiona de rama Ben rama A, el historial de la rama Acontendrá una gran confirmación que contiene todos los cambios realizados explícitamente Bdesde que se bifurcó.

En las primeras versiones de SVN, si tenía que fusionar una rama Ben Aotra una vez más, tenía que especificar manualmente qué rango de revisión de la rama Bquería fusionar para evitar fusionar las mismas revisiones dos veces. El desarrollador inteligente, por supuesto, usaría un mensaje de confirmación como 'Combinado en B: 1234'.

SVN 1.5 "solucionó" esto. Pero no cambió cómo se aplican fundamentalmente las fusiones. Simplemente agregó algunos metadatos adicionales a la rama A, informando a SVN que la revisión 1234 se había fusionado, permitiendo que SVN elija automáticamente el rango de revisión correcto.

Pero esta solución es básicamente una solución para un modelo de datos que fundamentalmente no admite el seguimiento de lo que se ha fusionado.

Fusionar dos ramas es un ejemplo relativamente simple. Pero imaginando este escenario más complejo

  1. Crea una rama Adesde aquí trunky realiza algunas confirmaciones aquí
  2. Crear rama Bde Ay hacer algunos hace aquí
  3. Hacer algunas confirmaciones trunkyA
  4. Fusionarse Bentrunk
  5. Fusionarse AenB
  6. Fusionarse Aentrunk
  7. Combinar Ben trunk(esto en realidad no debería hacer nada)

Manejar esto correctamente usando el modelo de metadatos se vuelve extremadamente complejo (no sé si SVN realmente maneja este escenario correctamente, y no me siento inclinado a probarlo).

Manejar este escenario en git es extremadamente simple.

En git, cada vez que confirma, el objeto interno que representa esa confirmación contiene una referencia al encabezado anterior. Cuando se fusiona en una rama, la confirmación contiene referencias al encabezado anterior de todas las ramas que se fusionan (puede fusionar más de una rama a la vez en git)

Por lo tanto, cuando examina el historial de una sola confirmación en git, puede ver todo el historial, puede ver cuándo se ramificó, cuándo se fusionó y puede ver el historial de ambas ramas entre la ramificación y la fusión.

Por lo tanto, cuando se fusiona en una rama que se ha fusionado parcialmente, es extremadamente simple determinar qué se ha fusionado y qué no.

No tengo experiencia con Mercurial, pero sospecho que su funcionamiento interno es similar al de git.

Básicamente, para SVN, era un objetivo de diseño hacer que la ramificación fuera barata. Pero en git, era un objetivo de diseño hacer que la fusión fuera barata.

Por último, la última vez que utilicé SVN, no fue capaz de manejar fusiones, donde se cambió el nombre de un archivo en una rama y se modificó en otra.

Pete
fuente
1

He realizado una buena combinación de SVN, incluida una rama de desarrollo y lanzamiento de larga duración. En general sobreviví. La fusión siempre es complicada, pero con DCVS la desventaja no es terriblemente mala: todo es local, así que solo actualice a una buena revisión conocida y continúe. Mientras que con SVN sucedió mucho en el lado del servidor, la recuperación fue fea, por lo general, implicaba borrar la copia local y luego revisar una nueva rama limpia para volver a intentarlo. No fue malo en mi caso: una conexión gigabit a la caja SVN ayuda. Pero tuvimos algunos contratistas que tuvieron muchos problemas con esto ya que estaban en conexiones lentas, por lo que todo tomó una eternidad, incluidas las fusiones.

Wyatt Barnett
fuente
extrapolando en lo que respecta a la conexión lenta, trabajar desde un servidor remoto externo también genera errores de conexión caídos cuando se realizan actualizaciones grandes> <No es nada divertido.
jxramos
-1

Sí, yo también hago eso. Actualmente tengo 12 máquinas virtuales para diferentes versiones (ramas) del proyecto del que formo parte en el trabajo. Cuando tengo que corregir un error en una versión anterior, lo soluciono y luego lo combino en las ramas para las versiones más nuevas. Pero eso es ahora volver a fusionar una rama completa, de eso es de lo que estoy hablando aquí.

Aquí yace una de las cosas más bonitas de git. No es heredar sobre DVCS, es algo en lo que Git sobresale. Puede combinar revisiones específicas de cualquier rama en otra rama. Básicamente solo toma el diff y lo aplica a la otra rama, pero realiza el seguimiento y es mucho más automático.

Entonces, si tiene branch 2.0 y branch 3.0 y descubre un error en 2.0, puede solucionarlo en 2.0 y tomar el conjunto de revisiones que lo resuelven y fusionar solo esas revisiones en la rama 3.0. No creo que SVN tenga otra forma de hacerlo que no sea tomar manualmente los diferenciales para cada revisión y aplicarlos

Por supuesto, el algoritmo de fusión automática también parece funcionar mucho más suavemente y git se creó desde cero en el modelo "hacer una rama para todas las cosas", por lo que la ramificación es realmente suave y fácil. Parece natural ramificarse a menudo con lo livianas que son sus ramas.

Earlz
fuente
Además, me imagino que mercurial tiene una funcionalidad similar
Earlz
2
En realidad, puedes hacer exactamente lo mismo en SVN. Lo hago todo el tiempo. El comando Combinar SVN puede extraer una revisión (o rango de revisiones) de una rama diferente y aplicarla a su copia de trabajo, y luego la confirma.
Mason Wheeler
2
@MasonWheeler Tenga en cuenta que gran parte del sentimiento anti-svn se dirigió a versiones anteriores a la 1.5 (cuando svn obtuvo el seguimiento de fusión). Y, por supuesto, mucho de eso es fanboyism inútil ...
Yannis
3
@MasonWheeler, consulte también stackoverflow.com/a/4215199/69742. Esta publicación se reduce a DVCS y realiza un seguimiento de los conjuntos de cambios, no las versiones . Los conjuntos de cambios son intrínsecamente fáciles de tomar y combinar ... las versiones no tanto porque requieren contexto
Earlz
@MasonWheeler oh y este: stackoverflow.com/questions/2471606/…
Earlz