397 votos

¿Cómo o por qué es la fusión en Git mejor en SVN?

He escuchado algunos lugares que uno de los principales medios distribuidos versión control sistemas shine, es mucho mejor la fusión de instrumentos tradicionales como SVN. ¿Esto es debido a las diferencias inherentes en cómo funcionan los sistemas de dos, o tienen sólo implementaciones específicas DVCS como Git/Mercurial algoritmos inteligentes fusión que SVN?

552voto

Spoike Puntos 32082

El reclamo de por qué la fusión es mejor en un DVCS que en Subversion se basa en gran medida en cómo ramificación y fusión trabajado en Subversion hace un tiempo. Subversion antes de 1.5.0 no almacenar cualquier información acerca de cuando las ramas se fusionaron, por lo tanto cuando se quiere combinar tenía que especificar un rango de revisiones que tuvo que ser fusionado.

Entonces, ¿por qué la Subversión combina chupar?

Mediten en este ejemplo:

      1   2   4     6     8
trunk o-->o-->o---->o---->o
       \
        \   3     5     7
b1       +->o---->o---->o

Cuando queremos combinar b1 cambios en el maletero nos gustaría que se emita el comando siguiente, mientras estaba parado en una carpeta que tiene el tronco desprotegido:

svn merge -r 3:7 {link to branch b1}

... que intentará combinar los cambios de b1 en tu directorio de trabajo local. Y luego confirme los cambios después de resolver los conflictos y probado el resultado. Cuando se confirma la revisión árbol tendría este aspecto:

      1   2   4     6     8   9
trunk o-->o-->o---->o---->o-->o      "the merge commit is at r9"
       \
        \   3     5     7
b1       +->o---->o---->o

Sin embargo, esta forma de especificar los rangos de las revisiones que se obtiene rápidamente de las manos cuando la versión de árbol que crece como la subversión no tenía ninguna meta datos sobre cuándo y qué revisiones consiguió unir. Reflexionar sobre lo que sucede más adelante:

           12        14
trunk  …-->o-------->o
                                     "Okay, so when did we merge last time?"
              13        15
b1     …----->o-------->o

Esto es en gran medida un problema por el diseño del repositorio de que la Subversión ha, con el fin de crear una rama que usted necesita para crear un nuevo directorio virtual en el repositorio que se casa una copia del tronco, pero no guarda ninguna información sobre cuándo y qué cosas se fusiona de nuevo. Que va a llevar a desagradables conflictos, a veces. Lo que era aún peor es que Subversion utiliza dos vías de fusión por defecto, que tiene un poco agobiante limitaciones en automático cuando la fusión de dos sucursal jefes no se comparan con su antepasado común.

Para mitigar esta Subversión ahora almacena datos de metadatos de subdivisión y fusión. Que podría resolver todos los problemas, ¿verdad?

Y ah, por cierto, Subversion sigue siendo una mierda...

En un sistema centralizado, como la subversión, los directorios virtuales de chupar. ¿Por qué? Porque todo el mundo tiene acceso a la vista de ellos... incluso la basura experimental. La ramificación es buena si quieres experimentar pero no quiero ver a todos' y sus tías experimentación. Esto es serio cognitivo de ruido. Las ramas más que añadir, más la mierda que vas a ver.

La más pública de las sucursales que tiene en un repositorio será más difícil seguir la pista de las diferentes ramas. Así que la pregunta que voy a tener es si la rama está todavía en desarrollo o si está verdaderamente muerto el que es difícil saber en cualquier centralizado sistema de control de versiones.

La mayoría del tiempo, por lo que he visto, una organización predeterminada para utilizar una gran rama de todos modos. Lo cual es una lástima ya que a su vez va a ser difícil seguir la pista de pruebas y versiones, y todo lo bueno viene de ramificación.

Entonces, ¿por qué DVCS, como Git, Mercurial y Bazaar, mejor que el de la Subversión en la ramificación y fusión?

Hay una muy sencilla razón: la ramificación es un primer concepto de clase. No hay ningún directorios virtuales por el diseño y las ramas son objetos duros en DVCS que se necesita para ser tal, con el fin de trabajar simplemente con la sincronización de repositorios (es decir. empujar y tirar).

La primera cosa que usted hace cuando usted trabaja con un DVCS es clonar repositorios (git clone, hg s clone y bzr del branch). La clonación es conceptualmente la misma cosa como la creación de una sucursal en el control de versiones. Algunos llaman a esto se bifurcan o ramificación (aunque el último es a menudo también se utiliza para referirse a la co-ubicación de las ramas), pero es la misma cosa. Cada usuario corre su propio repositorio que significa que tiene cada usuario ramificación pasando.

La versión de la estructura es no es un árbol, sino más bien un gráfico en su lugar. Más específicamente, un gráfico acíclico dirigido (DAG, es decir, un gráfico que no tiene ciclos). Realmente no es necesario insistir en los detalles de un DAG otros que cada commit que tiene uno o más de los padres de referencias (que lo de la confirmación se basa en). Así que los gráficos siguientes muestran las flechas entre las revisiones a la inversa, porque de esta.

Un ejemplo muy simple de la fusión sería esto; imagínese un repositorio central de llamados origin y de un usuario, Alice, clonar el repositorio para su máquina.

         a…   b…   c…
origin   o<---o<---o
                   ^master
         |
         | clone
         v

         a…   b…   c…
alice    o<---o<---o
                   ^master
                   ^origin/master

¿Qué sucede durante un clon es que cada revisión se copia a Alice, tal y como estaban (que es validado por el diseño único de identificación personal hash-id), y marca el lugar donde el origen de la ramas.

Alice trabaja en su repo, cometiendo en su propio repositorio y decide empujar a sus cambios:

         a…   b…   c…
origin   o<---o<---o
                   ^ master

              "what'll happen after a push?"


         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                   ^origin/master

La solución es bastante simple, lo único que el origin repositorio necesita hacer es tomar todas las nuevas revisiones y mover la rama a la versión más reciente (que git llamadas "fast-forward"):

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                             ^origin/master

El caso de uso, que he ilustrado anteriormente, aún no es necesario combinar nada. Así que el problema no es realmente con algoritmos de fusión desde tres vías algoritmo de combinación es prácticamente el mismo entre todos los sistemas de control de versiones. El problema es más acerca de la estructura de cualquier cosa.

Entonces, ¿cómo acerca de usted deme un ejemplo que tiene una real correspondencia?

Es cierto que el ejemplo anterior es muy simple, caso de uso, por lo que permite hacer mucho más retorcido de uno aunque sea más común. Recuerde que origin comenzó con tres revisiones? Así, el hombre que lo hizo, permite llamar a él, Bob, ha estado trabajando en su propia y ha hecho una confirmación en su propio repositorio:

         a…   b…   c…   f…
bob      o<---o<---o<---o
                        ^ master
                   ^ origin/master

                   "can Bob push his changes?" 

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

Ahora, Bob no puede empujar sus cambios directamente al origin repositorio. Cómo el sistema detecta este es comprobar si Bob revisiones directamente descensos de origins', que en este caso no. Cualquier intento de empuje resultará en el sistema, diciendo algo parecido a "Uh... me temo que no puedes dejar de hacer que Bob."

Así que Bob tiene que tirar y, a continuación, combinar los cambios (con git pull; o hg s pull y merge; o bzr del merge). Este es un proceso de dos pasos. Primera Bob tiene que ir a buscar las nuevas versiones, que se copia en ellas, ya que son de la origin repositorio. Ahora podemos ver que el gráfico se bifurca:

                        v master
         a…   b…   c…   f…
bob      o<---o<---o<---o
                   ^
                   |    d…   e…
                   +----o<---o
                             ^ origin/master

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

El segundo paso del proceso de extracción es la fusión de los diferentes consejos y hacer un commit de los resultados:

                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+
                             ^ origin/master

Esperemos que la mezcla no se ejecutará en los conflictos (si usted anticipa se puede hacer los dos pasos manualmente en git con fetch y merge). Lo que más tarde se debe hacer es pushear los cambios de nuevo a origin, que se traducirá en un avance rápido de mezcla ya que la combinación de cometer es un descendiente directo de la última en la origin repositorio:

                                 v origin/master
                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

                                 v master
         a…   b…   c…   f…       1…
origin   o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

Hay otra opción para combinar en git y hg, llamado de reajuste, que va a mover a Bob cambios se producen después de los últimos cambios. Ya no quiero que esta respuesta sea más detallado voy a dejar de leer el git, mercurial o bazaar docs acerca de ese lugar.

Como ejercicio para el lector, trata de dibujar un vistazo a cómo se va a trabajar con otro usuario. Igualmente, es hacer como el ejemplo de arriba con Bob. La fusión entre repositorios es más fácil de lo que usted podría pensar, porque todas las revisiones y se compromete inequívocamente identificable.

También está el tema de envío de parches entre cada desarrollador, que fue un gran problema en la Subversión que se atenúa en git, hg y bzr por inequívocamente identificable, revisiones. Una vez que alguien ha fusionado sus cambios (p. ej. hizo un merge commit) y la envía para que todos los demás en el equipo a consumir por empujar a un repositorio central o el envío de los parches, no tienen que preocuparse acerca de la combinación, porque ya pasó. Martin Fowler llama a esta forma de trabajar promiscuo de integración.

Debido a que la estructura es diferente de la Subversión, en lugar de emplear a un DAG, permite la ramificación y fusión ser hecho de una manera más fácil no sólo para el sistema, sino para el usuario también.

29voto

Andrew Aylett Puntos 16469

Históricamente, la Subversión sólo ha sido capaz de realizar una recta de dos vías de mezcla porque no almacenar cualquier información de fusión. Esto implica tomar una serie de cambios y aplicarlos a un árbol. Incluso con la información de fusión, esto es todavía la más comúnmente utilizado para la mezcla de la estrategia.

Git utiliza una 3-forma algoritmo de combinación por defecto, que consiste en encontrar un antepasado común a los jefes de estado que se van a combinar y hacer uso de los conocimientos que existe en ambos lados de la combinación. Esto permite a Git para ser más inteligente para evitar conflictos.

Git también tiene algunos sofisticados cambiar el nombre de hallazgo código, que también ayuda. Es no almacenar conjuntos de cambios o almacenar cualquier información de seguimiento-sólo se almacena el estado de los archivos en cada commit y utiliza la heurística para localizar cambia el nombre y código de los movimientos como sea necesario (el almacenamiento en disco es más complicado que esto, pero la interfaz se presenta a la capa de lógica expone sin seguimiento).

11voto

daniel kullmann Puntos 2619

Una cosa que no ha sido mencionado en las otras respuestas, y que realmente es una gran ventaja de un DVCS, es que se puede cometer localmente antes de introducir los cambios. En el SVN, cuando he tenido algún cambio que yo quería hacer el check in, y alguien ya había hecho un commit en la misma rama en el ínterin, esto significaba que yo tenía que hacer una svn update antes de que yo pudiera cometer. Esto significa que mis cambios, y los cambios de la otra persona, ahora están mezclados, y no hay manera de anular la mezcla (como con git reset o hg update -C), debido a que no hay comprometerse a regresar. Si la combinación no es trivial,esto significa que usted no puede continuar trabajando en su función antes de haber limpiado el resultado de la combinación.

Pero entonces, tal vez eso es sólo una ventaja para las personas que son demasiado tonto para utilizar distintas ramas (si mal no recuerdo, sólo teníamos una rama que se utilizó para el desarrollo de vuelta en la empresa donde yo solía SVN).

10voto

Peter Puntos 479

He leído la aceptación de respuesta. Es simplemente equivocada.

SVN fusión puede ser un dolor, y también puede ser tedioso. Pero, ignorar cómo funciona realmente un minuto. No hay ninguna información que Git se mantiene o se puede derivar que SVN no también mantener o pueden derivar. Lo que es más importante, no hay ninguna razón por qué mantener separado (a veces parcial) copias de la versión del sistema de control te proporcionará más información real. Las dos estructuras son completamente equivalentes.

Suponga que usted quiere hacer "inteligente cosa" Git es "mejor". Y eres cosa es comprobado en el SVN.

Convertir el SVN en el equivalente a Git forma, hacerlo en Git, y, a continuación, comprobar el resultado, tal vez el uso de múltiples comete algo más de las ramas. Si usted puede imaginar de una forma automatizada para activar un SVN problema en un Git problema, Git no tiene ninguna ventaja fundamental.

Al final del día, cualquier sistema de control de versiones me deja

1. Generate a set of objects at a given branch/revision.
2. Provide the difference between a parent child branch/revisions.

Además, para la fusión es también útil (o crítica) para saber

3. The set of changes have been merged into a given branch/revision.

Mercurial, Git y Subversion (ahora de forma nativa, utilizando previamente svnmerge.py) todo puede proporcionar todos los tres elementos de la información. Con el fin de demostrar algo fundamentalmente mejor con DVC, por favor, señalar algunos cuarta pieza de información que está disponible en Git/Mercurial/DVC no disponible en el SVN / centralizado de VC.

Eso no quiere decir que no es mejor de herramientas!

8voto

used2could Puntos 3409

SVN pistas archivos mientras Git rastrea cambios de contenido . Es lo suficientemente inteligente rastrear un bloque de código que fue refactorizado de archivo de clase de una a otra. Usan dos enfoques diferentes completos para rastrear su origen.

Utilizar SVN pesadamente, pero estoy muy contento con las pocas veces que he usado Git.

Lee un buen si tienes el tiempo: por qué elegí Git

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X