A mi entender, SVN es 'Fácil de ramificar. Difícil de fusionar '. ¿Porqué es eso? ¿Hay alguna diferencia en cómo se fusionan?
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
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.
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: