¿Por qué es más fácil ramificar y fusionar en Mercurial que en Subversion?

92

Manejar múltiples fusiones en ramas en Subversion o CVS es solo una de esas cosas que debe experimentarse. Es extraordinariamente más fácil realizar un seguimiento de las ramas y fusiones en Mercurial (y probablemente en cualquier otro sistema distribuido) pero no sé por qué. ¿Alguien más lo sabe?

Mi pregunta surge del hecho de que con Mercurial puede adoptar una práctica de trabajo similar a la del repositorio central de Subversiones / CVS y todo funcionará bien. Puede realizar múltiples fusiones en la misma rama y no necesitará interminables trozos de papel con números de confirmación y nombres de etiquetas.

Sé que la última versión de Subversion tiene la capacidad de rastrear fusiones en ramas para que no tengas el mismo grado de molestia, pero fue un desarrollo enorme e importante de su lado y todavía no hace todo lo que haría el equipo de desarrollo. me gusta hacer.

Debe haber una diferencia fundamental en la forma en que funciona todo.

Nick Pierpoint
fuente

Respuestas:

115

En Subversion (y CVS), el repositorio es lo primero y más importante. En git y mercurial no existe realmente el concepto de repositorio de la misma manera; aquí los cambios son el tema central.

+1

La molestia en CVS / SVN proviene del hecho de que estos sistemas no recuerdan la paternidad de los cambios. En Git y Mercurial, una confirmación no solo puede tener varios hijos, ¡también puede tener varios padres!

Eso se puede observar fácilmente usando una de las herramientas gráficas, gitko hg view. En el siguiente ejemplo, la rama n. ° 2 se bifurcó desde la n. ° 1 en la confirmación A y desde entonces se fusionó una vez (en M, se fusionó con la confirmación B):

o---A---o---B---o---C         (branch #1)
     \       \
      o---o---M---X---?       (branch #2)

Observe cómo A y B tienen dos hijos, mientras que M tiene dos padres . Estas relaciones se registran en el repositorio. Digamos que el mantenedor de la rama # 2 ahora quiere fusionar los últimos cambios de la rama # 1, puede emitir un comando como:

$ git merge branch-1

y la herramienta sabrá automáticamente que la base es B - porque se registró en el compromiso M, un antepasado de la punta de # 2 - y que tiene que fusionar lo que sucedió entre B y C. CVS no registra esta información , ni SVN antes de la versión 1.5. En estos sistemas, el gráfico se vería así:

o---A---o---B---o---C         (branch #1)
     \    
      o---o---M---X---?       (branch #2)

donde M es solo un compromiso gigantesco "aplastado" de todo lo que sucedió entre A y B, aplicado sobre M. Tenga en cuenta que después de que se realiza la escritura, no queda rastro (excepto potencialmente en comentarios legibles por humanos) de donde M no se originó ni de cuántas confirmaciones se colapsaron juntas, lo que hace que la historia sea mucho más impenetrable.

Peor aún, realizar una segunda fusión se convierte en una pesadilla: uno tiene que averiguar cuál era la base de fusión en el momento de la primera fusión (¡y uno tiene que saber que ha habido una fusión en primer lugar!), Luego presentar eso información a la herramienta para que no intente reproducir A..B encima de M. Todo esto es bastante difícil cuando se trabaja en estrecha colaboración, pero es simplemente imposible en un entorno distribuido.

Un problema (relacionado) es que no hay forma de responder a la pregunta: "¿X contiene B?" donde B es una corrección de errores potencialmente importante. Entonces, ¿por qué no registrar esa información en la confirmación, ya que se conoce en el momento de la fusión?

PD. - No tengo experiencia con las capacidades de grabación combinada de SVN 1.5+, pero el flujo de trabajo parece ser mucho más artificial que en los sistemas distribuidos. Si ese es el caso, probablemente se deba a que, como se mencionó en el comentario anterior, el enfoque se centra en la organización del repositorio en lugar de en los cambios en sí.

Damien Diederen
fuente
6
SVN 1.5+ de hecho pondría una propiedad SVN en el compromiso de fusión M listando los compromisos fusionados que contiene, en otras palabras, AB. Entonces tienes la misma información.
Simon D
Mas o menos. Técnicamente, el seguimiento de fusiones de SVN es similar a lo que Git llama "selección selectiva", con magia adicional para que sea más fácil para el usuario; es semánticamente diferente de lo que hacen Git, Hg y Bzr cuando se fusionan. Supongo que no supone una gran diferencia en la práctica siempre que no te importe el DAG ( eagain.net/articles/git-for-computer-scientists ).
Damien Diederen
2
Ay de que no haya un botón +100. Gracias.
Charlie Flowers
Supongo que la característica SVN 1.5 de la que estás hablando es el uso de la svn:mergeinfopropiedad.
MatrixFrog
@MatrixFrog: Sí, esto es exactamente lo que svn:mergeinfohace.
sleske
12

Porque Subversion (al menos la versión 1.4 y anteriores) no realiza un seguimiento de lo que se ha fusionado. Para Subversion, la fusión es básicamente lo mismo que cualquier confirmación, mientras que en otro control de versión como Git, se recuerda lo que se ha fusionado.

htanata
fuente
7

Sin ser tocado por ninguna de las respuestas ya proporcionadas, Hg ofreció capacidades de fusión superiores porque utiliza más información al fusionar cambios ( hginit.com ):

Por ejemplo, si cambio un poco una función y luego la muevo a otro lugar, Subversion realmente no recuerda esos pasos, por lo que cuando llega el momento de fusionar, podría pensar que una nueva función apareció de la nada. . Mientras que Mercurial recordará esas cosas por separado: función cambiada, función movida, lo que significa que si también cambió un poco esa función, es mucho más probable que Mercurial fusione con éxito nuestros cambios.

Por supuesto, recordar lo que se fusionó por última vez (el punto abordado por la mayoría de las respuestas proporcionadas aquí) también es una gran victoria.

Sin embargo, ambas mejoras son cuestionables ya que subversion 1.5+ almacena información adicional de fusión en forma de propiedades de subversión: esa información está disponible, no hay ninguna razón obvia por la que la fusión de subversión no pueda implementar la fusión con tanto éxito como Hg o Git. Sin embargo, no sé si lo hace, pero ciertamente parece que los desarrolladores de Subversion están en camino de solucionar este problema.

Tomislav Nakic-Alfirevic
fuente
4

Supongo que esto podría deberse en parte a que Subversion tiene la idea de un servidor central junto con una línea de tiempo absoluta de revisiones. Mercurial está verdaderamente distribuido y no tiene tal referencia a una línea de tiempo absoluta. Esto permite que los proyectos de Mercurial formen jerarquías de ramas más complicadas para agregar funciones y ciclos de prueba por subproyecto; sin embargo, los equipos ahora necesitan mantenerse al tanto de las fusiones de manera mucho más activa para mantenerse al día, ya que no pueden simplemente presionar la actualización y terminar. .

Andy malvado
fuente
3

En Subversion (y CVS), el repositorio es lo primero y más importante. En git y mercurial no existe realmente el concepto de repositorio de la misma manera; aquí los cambios son el tema central.

Tampoco he pensado mucho en cómo lo implementaría, pero mi impresión (basada en la amarga experiencia y mucha lectura) es que esta diferencia es lo que hace que la fusión y la ramificación sean mucho más fáciles en los sistemas que no están basados ​​en repositorios.

Stephen Darlington
fuente
1

Solo tengo experiencia con Subversion, pero puedo decirles que la pantalla de combinación en TortoiseSVN es horriblemente complicada. Por suerte, incluyen un botón de ejecución en seco para que puedas ver si lo estás haciendo bien. La complicación está en la configuración de lo que desea fusionar con dónde. Una vez que haya configurado eso para la fusión, la fusión generalmente funciona bien. Luego, debe resolver todos y cada uno de los conflictos y luego enviar su copia de trabajo fusionada al repositorio.

Si Mercurial puede facilitar la configuración de la combinación, puedo decir que la combinación sería un 100% más fácil que Subversion.

Lobos Rojos
fuente