Según tengo entendido, 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 una situación muy concreta en la que Mercurial (y Git) se fusiona sin problemas y donde Subversion le presenta un conflicto falso. La situación es una refactorización simple realizada en una rama donde se cambia el nombre de algunos archivos.
Con respecto a la respuesta de tdammers, hay una serie de malentendidos allí:
Subversion, Mercurial y Git siguen todas las instantáneas del proyecto en todo el repositorio. Llamarlos versiones , revisiones o conjuntos de cambios no hace ninguna diferencia. Todas son instantáneas lógicamente atómicas de un conjunto de archivos.
El tamaño de sus confirmaciones no hace ninguna diferencia cuando se trata de fusionar. Los tres sistemas se fusionan con el algoritmo de fusión estándar de tres vías y las entradas a ese algoritmo son
No importa cómo se crearon las dos versiones de ramificación. Puede haber usado 1000 pequeñas confirmaciones desde la versión ancestral, o puede haber usado 1 confirmación. Lo único que importa es la versión final de los archivos. (¡Sí, esto es sorprendente! Sí, muchas guías de DVCS se equivocan terriblemente).
También plantea algunos buenos puntos sobre las diferencias:
Subversion tiene algo de "vudú" en el que puede fusionarse /trunk
, por ejemplo /branches/foo
. Mercurial y Git no usan este modelo: las ramas se modelan directamente en el historial. 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 esto elimina una serie de casos de esquina.
Puede retrasar fácilmente una fusión o incluso dejar que otra persona lo maneje. Si hg merge
le da una tonelada de conflictos, puede pedirle a su compañero de trabajo que lo hg pull
haga y luego tiene exactamente el mismo estado. Entonces él puede hg merge
y tal vez sea mejor para resolver conflictos que tú.
Esto es muy difícil con Subversion, donde debe actualizar antes de poder realizar la confirmación. 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 sucia cuando trabajassvn update
. Esto es un poco arriesgado ya que no ha almacenado sus cambios en ningún lugar seguro. Git and Mercurial te permite confirmar primero, y luego actualizar y combinar según sea necesario.
La verdadera razón por la que Git y Mercurial son mejores para la fusión que 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 fácilmente. Pero no hay ninguna razón por la que Subversion no pueda manejarlos también: estar centralizado ciertamente no es la razón.
trunk
en SVN. Con un DVCS puede comprometerse sin compartir, pero en SVNsvn commit
afectará directamente a otros que trabajan en la misma rama. Incluso si los dos trabajamos en una sucursal en SVN, no puedo comprometer mi trabajo sin tener que fusionarme inmediatamente con tu trabajo. Eso hace que las confirmaciones sean algo aterradoras, ¡lo cual es una propiedad aterradora para un sistema de control de versiones! :-)El problema central 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. Siempre y cuando el historial sea perfectamente lineal, todo está bien, pero si necesita fusionar los cambios de dos líneas de desarrollo independientes, svn tiene que comparar las versiones actuales de ambos, y luego hacer una comparación de tres vías entre la última versión compartida y las dos versiones principales. 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, por favor resuélvelo por mí".
Por el contrario, git y mercurial rastrean conjuntos de cambios en lugar de versiones. El repositorio completo es un árbol de conjuntos de cambios, cada uno de los cuales depende 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 cabeza actualmente, y cómo se veía la última versión común, también sabe cómo sucedió la transición, permitiendo una fusión mucho más inteligente.
Otra cosa que facilita la fusión en un DVCS es una consecuencia indirecta de separar los conceptos de commit y push, y de permitir todo tipo de combinaciones cruzadas entre dos clones del mismo repositorio en cualquier momento. Con svn, las personas tienden a comprometer grandes conjuntos de cambios con cambios a menudo no relacionados, porque una confirmación 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 se enojarán contigo. Dado que la mayoría de las configuraciones involucran un servidor svn en red, la confirmación también implica el bombeo de datos a través de la red, lo que significa que la confirmación introduce un retraso considerable en el flujo de trabajo (especialmente cuando su copia de trabajo está desactualizada y debe extraerla primero). Con git y mercurial, el commit ocurre localmente, y debido a que ambos son muy eficientes en el manejo de sistemas de archivos locales, generalmente finaliza instantáneamente. Como resultado, las personas (una vez que se acostumbran) cometen pequeños cambios incrementales, y luego, cuando funciona, Empuje una docena de compromisos de una vez Luego, cuando llega el momento de la fusión, el SCM tiene información mucho más detallada, y puede hacer un mejor trabajo resolviendo conflictos de manera segura y automática.
Y luego están los bonitos detalles que hacen las cosas aún más fáciles:
fuente
hg mv
ohg addremove --similarity...
), mientras que Git usa heurística, pero ambos manejan los cambios de nombre . ¡Puedo obtener un conflicto de árbol incluso con una diferencia de 1 cadena en los archivos combinados! Tienes que volver a aprender algunos aspectos de Subversion, lo siento.rename a b
comocopy a b; remove a
y ambos lo hacen en una confirmación atómica. La diferencia en el comportamiento de fusión se debe al manejo diferente de los casos de esquina y a que Subversion permite más fusiones que Mercurial y Git. Finalmente, Git detecta los cambios de nombre en el momento de la fusión y el registro; estamos pensando en agregar esto también en Mercurial.