¿Hay alguna diferencia entre las fusiones en svn en comparación con git o mercurial?

12

A mi entender, SVN es 'Fácil de ramificar. Difícil de fusionar '. ¿Porqué es eso? ¿Hay alguna diferencia en cómo se fusionan?

    
pregunta 13.01.2012 - 06:18

2 respuestas

21

Consulte mi respuesta de desbordamiento de pila para ver una situación muy concreta en la que Mercurial (y Git) se fusiona sin problemas y donde Subversion Te presenta un conflicto falso. La situación es una simple refactorización realizada en una rama donde cambia el nombre de algunos archivos.

Con respecto a la respuesta de tdammers, hay una serie de malentendidos allí:

  • Subversion, Mercurial y Git realizan un seguimiento de las instantáneas del proyecto en todo el repositorio. Al llamarlos versiones , revisiones o conjuntos de cambios no hay diferencia. Todas son instantáneas atómicas de un conjunto de archivos.

  • El tamaño de tus confirmaciones no hace ninguna diferencia cuando se trata de fusionar. Los tres sistemas se fusionan con el algoritmo de combinación de tres vías estándar y las entradas a ese algoritmo son

    • mayor versión de ancestro común
    • versión en una rama
    • versión en otra rama

    no importa cómo se crearon las dos versiones de rama. Puede haber usado 1000 confirmaciones pequeñas desde la versión anterior, o puede haber utilizado 1 confirmación. Todo lo que importa es la versión final de los archivos. (¡Sí, esto es sorprendente! Sí, muchas guías de DVCS hacen que esto sea terriblemente incorrecto).

También plantea algunos puntos positivos sobre las diferencias:

  • Subversion tiene algún "vudú" en el que puedes combinar desde /trunk en, por ejemplo, /branches/foo . Mercurial y Git no usan este modelo; las ramas se modelan directamente en la historia. Por lo tanto, la historia se convierte en un gráfico acíclico dirigido en lugar de ser lineal. Este es un modelo mucho más simple que el utilizado por Subversion y elimina varios casos de esquina.

  • Puedes retrasar una fusión fácilmente o incluso dejar que alguien más la maneje. Si hg merge le da un montón de conflictos, entonces puede pedirle a su compañero de trabajo que le envíe hg pull y entonces él tiene exactamente el mismo estado. Entonces él puede hg merge y quizás él es mejor resolviendo conflictos que tú.

    Esto es muy difícil con Subversion, donde debe actualizar antes que puede confirmar. No puede simplemente ignorar los cambios en el servidor y seguir comprometiéndose en su propia rama anónima. En general, Subversion te obliga a jugar con una copia de trabajo sucia cuando svn update . Esto es un poco arriesgado ya que no ha guardado sus cambios en ningún lugar seguro. Git y Mercurial le permiten cometer primero, y luego actualizar y fusionar según sea necesario.

La verdadera razón por la que Git y Mercurial son mejores en la fusión que en Subversion es una cuestión de implementación. Hay conflictos de cambio de nombre que Subversion simplemente no puede manejar, incluso si está claro cuál es la respuesta correcta. Mercurial y Git los manejan con facilidad. Pero no hay razón por la que Subversion no pueda manejar eso también, ya que estar centralizado no es la razón.

    
respondido por el Martin Geisler 13.01.2012 - 10:41
6

El problema principal radica en la forma en que estos sistemas representan una estructura de directorios versionada.

El concepto básico de Subversion en torno al cual gira todo el sistema es el de una versión (o, en svn lingo, "revisión"): una instantánea de un archivo en un punto determinado. Mientras la historia sea perfectamente lineal, todo está bien, pero si necesita combinar cambios de dos líneas de desarrollo independientes, svn tiene que comparar las versiones actuales de ambas, y luego hacer una comparación de tres vías entre la última versión compartida y las dos versiones de cabeza. Las líneas que aparecen cambiadas en una de las cabezas, pero no en la otra, pueden resolverse fácilmente; las líneas que se desvían exactamente de la misma manera en ambas cabezas son más difíciles, pero generalmente factibles; las líneas que se desvían de diferentes maneras son lo que hace que svn diga "No puedo resolver esto, humano, resuélvalo por favor".

Por el contrario, git y mercurial siguen conjuntos de cambios en lugar de versiones. El repositorio completo es un árbol de conjuntos de cambios, cada uno dependiendo de un padre, donde un conjunto de cambios padre puede tener cualquier número de hijos, y la raíz del árbol representa un directorio vacío. En otras palabras, git / hg dice "primero no tenía nada, luego se aplicó este parche, luego ese parche, etc.". Cuando necesita fusionar dos líneas de desarrollo, git / hg no solo sabe cómo se ve cada jefe en la actualidad, y cómo se veía la última versión común, sino que también sabe cómo ocurrió la transición, lo que permite una fusión mucho más inteligente.

Otra cosa que facilita la fusión en un DVCS es una consecuencia indirecta de la separación de los conceptos de commit y push , y de permitir todo tipo de combinaciones cruzadas entre cualquier Dos clones del mismo repositorio en cualquier momento. Con svn, las personas tienden a realizar grandes conjuntos de cambios con cambios a menudo no relacionados, porque un compromiso también es una actualización en el repositorio central que afecta a todos los demás miembros del equipo; Si cometes una versión rota, todos estarán enojados contigo. Dado que la mayoría de las configuraciones involucran un servidor svn en red, la confirmación también involucra el bombeo de datos a través de la red, lo que significa que la introducción introduce un retraso considerable en el flujo de trabajo (especialmente cuando su copia de trabajo está desactualizada y usted tiene que extraer primero). Con git y mercurial, el compromiso ocurre localmente, y debido a que ambos son muy eficientes en el manejo de sistemas de archivos locales, generalmente termina instantáneamente. Como resultado, las personas (una vez que se acostumbran) cometen pequeños cambios incrementales, y luego, cuando funciona, empujan una docena o más de compromisos de una sola vez. Luego, cuando llega el momento de la fusión, el SCM tiene una información mucho más detallada y puede hacer un mejor trabajo para resolver conflictos de forma segura y automática.

Y luego están los bonitos detalles que facilitan las cosas aún más:

  • Puedes tener varias cabezas y aún así comprometerte con cualquiera; a diferencia de la subversión, no es necesario combinar la extracción, la actualización y la combinación antes de volver a realizar la confirmación; los múltiples jefes permanecen así hasta que elijas la fusión
  • Los directorios no son tratados especialmente; en cambio, la ruta solo se considera un nombre de archivo grande, y todos los directorios deben estar en la misma revisión en todo momento. Esto significa que no puede hacer el vudú de subversión en el que las subcarpetas de un proyecto se encuentran en diferentes revisiones, pero también significa que es menos probable que la copia de trabajo se convierta en un gran desorden incontrolable, y lo que es más interesante, un movimiento no se representa como una eliminación -y-add (que se rompería completamente en svn si no fuera por los metadatos de actualización), sino simplemente como cambio de nombre; Si mueves un archivo, se conserva todo su historial; la fusión puede incluso aplicar cambios al archivo movido que se realizó en una versión no movida del mismo archivo después de el movimiento, en otra rama
  • La mayoría de las veces, en realidad ni siquiera necesita para bifurcar: en su lugar, simplemente clonar todo el repositorio. La clonación es barata, especialmente si se realiza en el mismo sistema de archivos, y si decides deshacerte del clon, simplemente eliminas el directorio en el que se encuentra y eso es todo. Ni siquiera necesitas usar hg o git para eso.
  • Hay pocas restricciones (si las hay) en lo que puedes combinar. Puede tener seis clones del mismo repositorio, y combinar (o más bien, empujar o tirar; a menudo no se requiere una fusión explícita) de A a B, luego de C a B, luego de B a D, luego de C a D, B atrás a A, D a E, en cualquier momento y con la frecuencia que desee.
  • Puede probar una combinación clonando uno de los repositorios que desea combinar y luego extrayéndolo desde el otro. Si hace lo que quiere, puede retroceder al objetivo real; si no lo hace, deseche el clon y comience de nuevo.
respondido por el tdammers 13.01.2012 - 08:23

Lea otras preguntas en las etiquetas