tortoise subir son que proyecto lock informatica create branches svn git version-control mercurial dvcs

svn - subir - ¿Qué facilita la fusión en DVCS?



tortoise svn lock (9)

Como nota histórica, el ahora arcaico sistema PRCS también conoce a antepasados ​​comunes y puede fusionarse eficientemente, aunque no fue distribuido (¡fue construido sobre los archivos RCS!). Sin embargo, significaba que se podía migrar efectivamente a git sin perder el historial.

Leí en Joel sobre software :

Con el control de versión distribuida, la parte distribuida no es realmente la parte más interesante.

La parte interesante es que estos sistemas piensan en términos de cambios, no en términos de versiones.

y en HgInit :

Cuando tenemos que fusionarnos, Subversion intenta ver ambas revisiones, mi código modificado y tu código modificado, e intenta adivinar cómo unirlas en un gran desastre profano. Generalmente falla, produciendo páginas y páginas de "conflictos de fusión" que no son realmente conflictos, simplemente lugares en los que Subversion no pudo descifrar lo que hicimos.

Por el contrario, mientras trabajábamos por separado en Mercurial, Mercurial estaba ocupado manteniendo una serie de conjuntos de cambios. Entonces, cuando queremos fusionar nuestro código, Mercurial en realidad tiene mucha más información: sabe lo que cada uno de nosotros cambió y puede volver a aplicar esos cambios, en lugar de solo mirar el producto final e intentar adivinar cómo expresarlo. juntos.

Al mirar la carpeta del repositorio del SVN, tengo la impresión de que Subversion mantiene cada revisión como conjunto de cambios . Y por lo que sé, Hg está usando tanto changeset como snapshot, mientras que Git está usando puramente snapshot para almacenar los datos.

Si mi suposición es correcta, entonces debe haber otras formas de facilitar la fusión en DVCS. ¿Que son esos?

* Actualización:

  • Estoy más interesado en la perspectiva técnica, pero las respuestas desde una perspectiva no técnica son aceptables
  • Correcciones
    1. El modelo conceptual de Git se basa exclusivamente en instantáneas. Las instantáneas se pueden almacenar como diferencias de otras instantáneas, es solo que las diferencias son solo para la optimización del almacenamiento. - Comentario de Rafał Dowgird
  • Desde una perspectiva no técnica:
    1. Es simplemente cultural: un DVCS no funcionaría en absoluto si la fusión fuera difícil, por lo que los desarrolladores de DVCS invierten mucho tiempo y esfuerzo para facilitar la fusión. Los usuarios de CVCS, OTOH, están acostumbrados a la fusión difusa, por lo que no hay ningún incentivo para que los desarrolladores lo hagan funcionar. (¿Por qué hacer algo bueno cuando tus usuarios te pagan igual por algo?)
      ...
      En resumen: el objetivo de un DVCS es tener muchos repositorios descentralizados y fusionar constantemente los cambios. Sin una buena fusión, un DVCS simplemente es inútil. Sin embargo, un CVCS aún puede sobrevivir con una combinación desagradable, especialmente si el proveedor puede condicionar a sus usuarios para evitar la bifurcación. - La answer Jörg W Mittag
  • Desde una perspectiva técnica:
    1. ¡grabar un DAG real de la historia ayuda! Creo que la principal diferencia es que CVCS no siempre registró una fusión como un conjunto de cambios con varios padres, perdiendo algo de información. - comment tonfa
    2. debido al seguimiento de fusión y el hecho más fundamental de que cada revisión conoce a sus padres . ... Cuando cada revisión (cada commit), incluyendo merge commits, conoce sus padres (para commit de fusión que significa tener / recordar más de un padre, es decir, merge tracking), puede reconstruir el diagrama (DAG = Direct Acyclic Graph) de revisión historia. Si conoce un gráfico de revisiones, puede encontrar antecesor común de las confirmaciones que desea fusionar. Y cuando su DVCS sabe cómo encontrar un ancestro común , no necesita proporcionarlo como argumento, como por ejemplo en CVS.
      .
      Tenga en cuenta que puede haber más de un antecesor común de dos (o más) confirmaciones. Git hace uso de la llamada estrategia de fusión "recursiva", que fusiona las bases de fusión (ancestro común), hasta que te queda un antecesor común virtual / efectivo (con alguna simplificación), y puede hacer una combinación simple de 3 vías. - La answer Jakub Narębski

Compruebe también ¿Cómo y / o por qué la fusión en Git es mejor que en SVN?


Creo que el DAG de conjuntos de cambios, como lo mencionaron otros, hace una gran diferencia. Los DVCS requieren un historial dividido (y fusiones) en un nivel fundamental, mientras que supongo que los CVCS: es (que son más antiguos) fueron creados desde el día 1 para rastrear revisiones y archivos primero, con soporte de fusión agregado como una idea de último momento.

Asi que:

  • La fusión es fácil de hacer y realizar un seguimiento cuando las etiquetas / ramas se rastrean por separado desde el árbol de directorios de las fuentes, por lo que todo el repositorio se puede combinar de una sola vez.
  • Como DVCS: es tiene repos locales, estos son fáciles de crear, por lo que resulta fácil mantener diferentes módulos en repositorios diferentes en lugar de rastrearlos dentro de un gran repositorio. (Así que las fusiones de todo el repositorio no causan las mismas interrupciones que en svn / cvs, donde un repositorio a menudo contiene muchos módulos no relacionados que necesitan tener historias de fusión separadas).
  • CVS / SVN permite que diferentes archivos en el directorio de trabajo provengan de diferentes revisiones, mientras que DVCS: es generalmente tiene una revisión para todo el WC, siempre (es decir, incluso si un archivo se revierte a una versión anterior, se mostrará como modificado en estado ya que es diferente del archivo en la revisión desprotegida. SVN / CVS no muestra esto siempre).

Mezclar estos conceptos (como lo hace Subversion) es, creo, un gran error. Por ejemplo, tiene ramas / etiquetas dentro del árbol de fuentes, por lo que hay que rastrear qué revisiones de archivos se han fusionado con otros archivos. Esto es claramente más complejo que simplemente rastrear qué revisiones se han fusionado.

Entonces, resumiendo:

  • DVCS: es necesita fusiones fáciles, tienen sus características basadas en eso. La decisión de diseño se hizo para que estas fusiones fueran fáciles de hacer y rastrear (a través de DAG), y se implementan otras características (ramas / etiquetas / submódulos) para adaptarse a eso, y no al revés.
  • CVCS: es tenía algunas características desde el principio (como los módulos) que facilitaban algunas cosas, pero hacen que las fusiones de todo el repositorio sean muy difíciles de implementar.

Al menos esto es lo que siento por mi experiencia con cvs, svn, git y hg. (Probablemente haya otros CVCS: es que también ha hecho esto bien).


En Git y otras fusiones de DVCS son fáciles, no por una serie mística de vistas de conjuntos de cambios (a menos que estés utilizando Darcs, con su teoría de parches, o algunos DVCS inspirados en Darcs; son minoría, sin embargo) de los que Joel habla, sino porque del seguimiento de fusión , y el hecho más fundamental de que cada revisión conoce a sus padres . Para eso necesitas (creo) confirmaciones de árboles completos / repositorios completos ... lo que lamentablemente limita la capacidad de realizar comprobaciones parciales y realizar un compromiso sobre solo un subconjunto de archivos.

Cuando cada revisión (cada confirmación), incluidas las asignaciones de fusión, conocen sus padres (para las asignaciones de fusión que significa tener / recordar más de un padre, es decir, seguimiento de fusión ), puede reconstruir el diagrama (DAG = Gráfico acíclico directo) del historial de revisión. Si conoce un gráfico de revisiones, puede encontrar antecesor común de las confirmaciones que desea fusionar. Y cuando su DVCS sabe cómo encontrar un ancestro común , no necesita proporcionarlo como argumento, como por ejemplo en CVS.

Tenga en cuenta que puede haber más de un antecesor común de dos (o más) confirmaciones. Git hace uso de la llamada estrategia de fusión "recursiva", que fusiona las bases de fusión (ancestro común), hasta que te queda un antecesor común virtual / efectivo (con alguna simplificación), y puede hacer una combinación simple de 3 vías.

El uso de Git de la detección de cambio de nombre fue creado para poder tratar con fusiones que implican el cambio de nombre de archivos. (Esto es compatible con el argumento de Jörg W Mittag de que DVCS tiene mejor soporte de fusión porque tenían que tenerlo, ya que las fusiones son mucho más comunes que en CVCS con su fusión oculta en el comando ''actualización'' en flujo de trabajo de actualización y confirmación, cf Comprender la versión Control (WIP) por Eric S. Raymond).


No hay nada en particular en los DVCS que facilita la fusión. Es simplemente cultural: un DVCS no funcionaría en absoluto si la fusión fuera difícil, por lo que los desarrolladores de DVCS invierten mucho tiempo y esfuerzo para facilitar la fusión. Los usuarios de CVCS, OTOH, están acostumbrados a la fusión difusa, por lo que no hay ningún incentivo para que los desarrolladores lo hagan funcionar. (¿Por qué hacer algo bueno cuando tus usuarios te pagan igual por algo?)

Linus Torvalds dijo en una de sus charlas de Git que cuando usaba CVS en Transmeta, reservaron una semana entera durante un ciclo de desarrollo para la fusión. Y todos simplemente aceptaron esto como el estado normal de las cosas. Hoy en día, durante una ventana de fusión, Linus realiza cientos de fusiones en pocas horas.

Los CVCS podrían tener las mismas capacidades de fusión que los DVCS, si los usuarios de CVCS simplemente acudieran a sus proveedores y dijeran que esta mierda es inaceptable. Pero están atrapados en la paradoja de Blub: simplemente no saben que es inaceptable, porque nunca han visto un sistema de fusión funcional. Ellos no saben que hay algo mejor por ahí.

Y cuando prueban un DVCS, atribuyen mágicamente todas las bondades a la parte "D".

Teóricamente, debido a la naturaleza centralizada, un CVCS debería tener mejores capacidades de fusión, ya que tienen una visión global de toda la historia, a diferencia de DVCS, cada repositorio solo tiene un pequeño fragmento.

En resumen: el objetivo de un DVCS es tener muchos repositorios descentralizados y fusionar constantemente los cambios. Sin una buena fusión, un DVCS simplemente es inútil. Sin embargo, un CVCS aún puede sobrevivir con una combinación desagradable, especialmente si el proveedor puede condicionar a sus usuarios para evitar la bifurcación.

Entonces, al igual que con todo lo demás en ingeniería de software, es una cuestión de esfuerzo.


Parte del motivo es, por supuesto, el argumento técnico de que los DVCS almacenan más información que SVN (DAG, copias) y también tienen un modelo interno más simple, por lo que es capaz de realizar fusiones más precisas, como se menciona en las otras respuestas. .

Sin embargo, probablemente una diferencia aún más importante es que, debido a que tiene un repositorio local, puede realizar confirmaciones pequeñas frecuentes y, con frecuencia, extraer y fusionar los cambios entrantes. Esto es causado más por el ''factor humano'', las diferencias en la forma en que un ser humano trabaja con un VCS centralizado versus un DVCS.

Con SVN, si actualiza y hay conflictos, SVN fusionará lo que pueda e insertará marcadores en su código donde no pueda. El gran problema con esto es que su código ya no estará en estado viable hasta que resuelva todos los conflictos.

Esto lo distrae del trabajo que está tratando de lograr, por lo que los usuarios de SVN generalmente no se fusionan mientras trabajan en una tarea. Combine esto con el hecho de que los usuarios de SVN también tienden a permitir que los cambios se acumulen en una sola confirmación grande por temor a romper las copias de trabajo de otras personas, y habrá largos períodos de tiempo entre la rama y la fusión.

Con Mercurial, puede fusionarse con los cambios entrantes con mucha mayor frecuencia entre sus compromisos incrementales más pequeños. Por definición, esto generará menos conflictos de fusión, porque trabajará en una base de código más actualizada.

Y si resulta que hay un conflicto, puede decidir posponer la fusión y hacerlo en su propio ocio. Esto en particular hace que la fusión sea mucho menos molesta.


Puede ser que los usuarios de DVCS nunca hagan cosas que dificulten la fusión como refactorizaciones que cambian y renombran / copian la mayoría de los archivos en el proyecto, o rediseñan desde API de stratch que se usan en cientos de archivos.


Un punto es que la fusión svn está sutilmente rota; vea http://blogs.open.collab.net/svn/2008/07/subversion-merg.html . Sospecho que esto está en conjunto con svn, registrando mergeinfo incluso en fusiones al azar. Agregue algunos errores simples en el manejo de casos límite, y svn como el elemento secundario actual de CVCS hace que se vean mal en comparación con todos los DVCS que lo hicieron bien.


Una cosa que encuentro más fácil con DVCS es que cada desarrollador puede fusionar sus propios cambios en el repositorio que desee. Es mucho más fácil manejar los conflictos de fusión cuando fusiona su propio código. He trabajado en lugares donde un alma pobre había solucionado conflictos de fusión al encontrar a cada desarrollador involucrado.

También con un DVCS puede hacer cosas como clonar un repositorio, fusionar el trabajo de dos desarrolladores en el clon, probar los cambios, luego fusionar desde el clon de nuevo en el repositorio principal.

Bastante genial.


Whoa, ataque de los ensayos de 5 párrafos!

En resumen, nada lo hace fácil. Es difícil, y mi experiencia indica que se producen errores. Pero:

  • DVCS lo obliga a tratar con la fusión, lo que significa tomarse unos minutos para familiarizarse con las herramientas que existen para ayudarlo. Eso solo ayuda.

  • DVCS lo alienta a que se fusione con frecuencia, lo que también ayuda.

El fragmento de hginit que citó, afirmando que Subversion no puede realizar fusiones en tres direcciones y que Mercurial se fusiona al observar todos los conjuntos de cambios en ambas ramas, es simplemente incorrecto en ambos sentidos.