Git y Mercurial - Comparar y contrastar

520

Hace un tiempo que uso Subversion para mis proyectos personales.

Cada vez escucho más cosas buenas sobre Git y Mercurial, y DVCS en general.

Me gustaría darle un giro a todo el DVCS, pero no estoy muy familiarizado con ninguna de las opciones.

¿Cuáles son algunas de las diferencias entre Mercurial y Git?

Nota: Estoy no tratar de averiguar cuál es el "mejor" o incluso cuál debo empezar. Principalmente busco áreas clave donde sean similares y donde sean diferentes, porque me interesa saber cómo difieren en términos de implementación y filosofía.

TM.
fuente

Respuestas:

451

Descargo de responsabilidad: uso Git, sigo el desarrollo de Git en la lista de correo de git e incluso contribuyo un poco a Git (principalmente gitweb). Conozco Mercurial de la documentación y algunos de la discusión en el canal #revctrl IRC en FreeNode.

Gracias a todas las personas en el canal #mercurial IRC que brindaron ayuda sobre Mercurial para este artículo.



Resumen

Aquí sería bueno tener alguna sintaxis para la tabla, algo así como en la extensión PHPMarkdown / MultiMarkdown / Maruku de Markdown

  • Estructura del repositorio: Mercurial no permite fusiones de pulpos (con más de dos padres), ni etiquetar objetos sin compromiso.
  • Etiquetas: Mercurial utiliza .hgtagsarchivos versionados con reglas especiales para etiquetas por repositorio, y también tiene soporte para etiquetas locales en .hg/localtags; en Git, las etiquetas son referencias que residen en el refs/tags/espacio de nombres y, de forma predeterminada, se siguen automáticamente al buscar y requieren un empuje explícito.
  • Sucursales: en Mercurial, el flujo de trabajo básico se basa en cabezas anónimas ; Git usa ramas con nombre ligero y tiene un tipo especial de ramas (ramas de seguimiento remoto ) que siguen a las ramas en el repositorio remoto.
  • Nomenclatura y rangos de revisión : Mercurial proporciona números de revisión , locales al repositorio, y basa las revisiones relativas (contando desde la punta, es decir, la rama actual) y rangos de revisión en esta numeración local ; Git proporciona una forma de referirse a la revisión en relación con la punta de la rama, y ​​los rangos de revisión son topológicos (basados ​​en el gráfico de revisiones)
  • Mercurial usa el seguimiento de cambio de nombre , mientras que Git usa la detección de cambio de nombre para tratar los cambios de nombre de archivo
  • Red: Mercurial admite los protocolos "inteligentes" SSH y HTTP, y el protocolo HTTP estático; El Git moderno admite los protocolos "inteligentes" SSH, HTTP y GIT, y el protocolo "tonto" HTTP (S). Ambos tienen soporte para archivos de paquetes para el transporte fuera de línea.
  • Mercurial usa extensiones (complementos) y API establecida; Git tiene capacidad de escritura y formatos establecidos.

Hay algunas cosas que difieren de Mercurial de Git, pero hay otras cosas que las hacen similares. Ambos proyectos toman prestadas ideas el uno del otro. Por ejemplo, el hg bisectcomando en Mercurial (anteriormente extensión bisecta ) se inspiró en el git bisectcomando en Git, mientras que la idea de git bundlese inspiró en hg bundle.

Estructura del repositorio, almacenando revisiones

En Git hay cuatro tipos de objetos en su base de datos de objetos: objetos blob que contienen el contenido de un archivo, objetos de árbol jerárquico que almacenan la estructura del directorio, incluidos los nombres de archivo y las partes relevantes de los permisos de archivo (permiso ejecutable para archivos, que es un enlace simbólico) , confirme el objeto que contiene información de autoría, apunte a la instantánea del estado del repositorio en la revisión representada por una confirmación (a través de un objeto de árbol del directorio superior del proyecto) y referencias a cero o más confirmaciones principales, y etiquete objetos que hagan referencia a otros objetos y puedan ser firmado con PGP / GPG.

Git utiliza dos formas de almacenar objetos: formato suelto , donde cada objeto se almacena en un archivo separado (esos archivos se escriben una vez, y nunca se modifican), y formato empaquetado donde muchos objetos se almacenan comprimidos delta en un solo archivo. El hecho de que la referencia a un nuevo objeto se escribe (atómicamente, usando el truco de crear + renombrar) proporciona la atomicidad de las operaciones después de escribir un objeto.

Los repositorios de Git requieren mantenimiento periódico git gc(para reducir el espacio en disco y mejorar el rendimiento), aunque actualmente Git lo hace automáticamente. (Este método proporciona una mejor compresión de los repositorios).

Mercurial (por lo que yo entiendo) almacena el historial de un archivo en un registro de archivos (juntos, creo, con metadatos adicionales como seguimiento de cambio de nombre y algo de información auxiliar); utiliza una estructura plana llamada manifiesto para almacenar la estructura del directorio y una estructura llamada registro de cambios que almacena información sobre los conjuntos de cambios (revisiones), incluido el mensaje de confirmación y cero, uno o dos padres.

Mercurial utiliza el diario de transacciones para proporcionar la atomicidad de las operaciones y se basa en truncar los archivos para limpiarlos después de una operación fallida o interrumpida. Los Revlogs son solo para agregar.

Al observar la estructura del repositorio en Git versus Mercurial, se puede ver que Git es más como una base de datos de objetos (o un sistema de archivos con contenido de contenido), y Mercurial más como una base de datos relacional tradicional de campo fijo.

Diferencias:
en Git, los objetos del árbol forman una estructura jerárquica ; en el archivo de manifiesto Mercurial es una estructura plana . En Git blob object, almacene una versión del contenido de un archivo; en Mercurial Filelog almacena el historial completo de un solo archivo (si no tenemos en cuenta aquí ninguna complicación con los cambios de nombre). Esto significa que hay diferentes áreas de operaciones donde Git sería más rápido que Mercurial, todas las demás cosas se consideran iguales (como fusiones o mostrar el historial de un proyecto) y áreas donde Mercurial sería más rápido que Git (como aplicar parches o mostrar historial de un solo archivo).Este problema puede no ser importante para el usuario final.

Debido a la estructura de registro fijo de la estructura de registro de cambios de Mercurial , los compromisos en Mercurial solo pueden tener hasta dos padres ; commits en Git puede tener más de dos padres (llamada "fusión de pulpo"). Si bien puede (en teoría) reemplazar la fusión de pulpo por una serie de fusiones de dos padres, esto podría causar complicaciones al convertir entre repositorios Mercurial y Git.

Hasta donde sé, Mercurial no tiene el equivalente de etiquetas anotadas (objetos de etiqueta) de Git. Un caso especial de etiquetas anotadas son etiquetas firmadas (con firma PGP / GPG); el equivalente en Mercurial se puede hacer usando GpgExtension , cuya extensión se distribuye junto con Mercurial. No puede etiquetar objetos sin compromiso en Mercurial como puede hacerlo en Git, pero eso no es muy importante, creo (algunos repositorios de git usan blob etiquetado para distribuir la clave PGP pública para verificar etiquetas firmadas).

Referencias: ramas y etiquetas

En Git, las referencias (ramas, ramas y etiquetas de seguimiento remoto) residen fuera del DAG de las confirmaciones (como deberían). Las referencias en el refs/heads/espacio de nombres ( ramas locales ) apuntan a commits, y generalmente se actualizan con "git commit"; apuntan a la punta (cabeza) de la rama, por eso ese nombre. Las referencias en el refs/remotes/<remotename>/espacio de nombres ( ramas de seguimiento remoto ) apuntan a comprometerse, siguen ramas en el repositorio remoto <remotename>y se actualizan mediante "git fetch" o equivalente. Las referencias en el refs/tags/espacio de nombres ( etiquetas ) generalmente apuntan a commits (etiquetas livianas) u objetos de etiqueta (etiquetas anotadas y firmadas), y no están destinados a cambiar.

Etiquetas

En Mercurial puede dar un nombre persistente a la revisión usando la etiqueta ; Las etiquetas se almacenan de manera similar a los patrones de ignorar. Significa que las etiquetas visibles globalmente se almacenan en un .hgtagsarchivo controlado por revisión en su repositorio. Eso tiene dos consecuencias: primero, Mercurial tiene que usar reglas especiales para este archivo para obtener la lista actual de todas las etiquetas y actualizar dicho archivo (por ejemplo, lee la revisión más reciente del archivo, no la versión actualmente desprotegida); segundo, debe realizar cambios en este archivo para que la nueva etiqueta sea visible para otros usuarios / otros repositorios (por lo que yo entiendo).

Mercurial también admite etiquetas locales , almacenadas hg/localtags, que no son visibles para otros (y, por supuesto, no son transferibles)

En Git, las etiquetas son referencias nominales fijas (constantes) a otros objetos (generalmente objetos de etiqueta, que a su vez apuntan a confirmaciones) almacenados en el refs/tags/espacio de nombres. De forma predeterminada, cuando se busca o empuja un conjunto de revisiones, git busca o empuja automáticamente etiquetas que apuntan a las revisiones que se buscan o empujan. Sin embargo, puede controlar hasta cierto punto qué etiquetas se obtienen o se envían.

Git trata las etiquetas livianas (apuntando directamente a commits) y las etiquetas anotadas (apuntando a objetos de etiqueta, que contienen mensajes de etiqueta que opcionalmente incluyen la firma PGP, que a su vez apuntan a commit) de manera ligeramente diferente, por ejemplo, por defecto, considera solo las etiquetas anotadas cuando describe se compromete a usar "git describe".

Git no tiene un equivalente estricto de etiquetas locales en Mercurial. Sin embargo, las mejores prácticas de git recomiendan configurar un repositorio desnudo público separado, en el que empuje los cambios listos, y desde el que otros clonan y obtienen. Esto significa que las etiquetas (y ramas) que no inserta son privadas para su repositorio. Por otro lado, también puede usar un espacio de nombres que no sea heads, remoteso tags, por ejemplo, local-tagspara etiquetas locales.

Opinión personal: en mi opinión, las etiquetas deben residir fuera del gráfico de revisión, ya que son externas (son punteros en el gráfico de revisiones). Las etiquetas deben ser no versionadas, pero transferibles. La elección de Mercurial de utilizar un mecanismo similar al de ignorar archivos significa que debe tratarse .hgtagsespecialmente (el archivo en árbol es transferible, pero ordinario está versionado) o tiene etiquetas que son locales solamente ( .hg/localtagsno está versionado, pero intransferible).

Ramas

En Git, la rama local (punta de rama o encabezado de rama) es una referencia con nombre a una confirmación, donde se pueden desarrollar nuevas confirmaciones. Branch también puede significar una línea activa de desarrollo, es decir, todos los commits accesibles desde la punta de la branch. Las sucursales locales residen en el refs/heads/espacio de nombres, por lo que, por ejemplo, el nombre completo de la sucursal 'maestra' es 'refs / heads / master'.

La rama actual en Git (es decir, la rama desprotegida y la rama donde irá la nueva confirmación) es la rama a la que hace referencia la referencia HEAD. Uno puede tener HEAD apuntando directamente a un commit, en lugar de ser una referencia simbólica; Esta situación de estar en una rama anónima sin nombre se llama HEAD separada ("git branch" muestra que estás en '(sin rama)').

En Mercurial hay sucursales anónimas (jefes de sucursal), y uno puede usar marcadores (a través de la extensión de marcador ). Dichas ramas de marcadores son puramente locales, y esos nombres eran (hasta la versión 1.6) no transferibles usando Mercurial. Puede usar rsync o scp para copiar el .hg/bookmarksarchivo a un repositorio remoto. También puede usar hg id -r <bookmark> <url>para obtener la identificación de revisión de una sugerencia actual de un marcador.

Desde 1.6 los marcadores se pueden empujar / tirar. La página BookmarksExtension tiene una sección sobre Trabajar con repositorios remotos . Hay una diferencia en que en Mercurial los nombres de marcadores son globales , mientras que la definición de 'remoto' en Git describe también el mapeo de los nombres de las ramas de los nombres en el repositorio remoto a los nombres de las ramas locales de seguimiento remoto; por ejemplo, el refs/heads/*:refs/remotes/origin/*mapeo significa que uno puede encontrar el estado de la rama 'maestra' ('refs / heads / master') en el repositorio remoto en la rama de seguimiento remoto 'origen / maestro' ('refs / remotes / origin / master').

Mercurial también se denomina ramas con nombre , donde el nombre de la rama está incrustado en una confirmación (en un conjunto de cambios). Dicho nombre es global (transferido al buscar). Esos nombres de rama se registran permanentemente como parte de los metadatos del conjunto de cambios. Con Mercurial moderno puede cerrar la "rama con nombre" y dejar de grabar el nombre de la rama. En este mecanismo, las puntas de las ramas se calculan sobre la marcha.

En mi opinión, las "ramas con nombre" de Mercurial deberían llamarse etiquetas de compromiso , porque es lo que son. Hay situaciones en las que la "rama con nombre" puede tener múltiples sugerencias (múltiples confirmaciones sin hijos) y también puede consistir en varias partes disjuntas del gráfico de revisiones.

No hay equivalente de esas "ramas incrustadas" de Mercurial en Git; Además, la filosofía de Git es que si bien se puede decir que la rama incluye alguna confirmación, no significa que una confirmación pertenezca a alguna rama.

Tenga en cuenta que la documentación de Mercurial todavía propone utilizar clones separados (repositorios separados) al menos para ramas de larga duración (rama única por flujo de trabajo de repositorio), también conocido como ramificación por clonación .

Ramas en empujar

Mercurial por defecto empuja todas las cabezas . Si desea empujar una sola rama ( cabeza simple ), debe especificar la revisión de la punta de la rama que desea empujar. Puede especificar la sugerencia de la rama por su número de revisión (local al repositorio), por identificador de revisión, por nombre de marcador (local al repositorio, no se transfiere) o por el nombre de la rama incrustada (rama nombrada).

Por lo que yo entiendo, si empuja un rango de revisiones que contienen confirmaciones marcadas como en alguna "rama con nombre" en el lenguaje Mercurial, tendrá esta "rama con nombre" en el repositorio al que empuja. Esto significa que los nombres de tales ramas incrustadas ("ramas con nombre") son globales (con respecto a los clones de un repositorio / proyecto dado).

Por defecto (sujeto a la push.defaultvariable de configuración) "git push" o "git push < remote >" Git empujaría ramas coincidentes , es decir, solo aquellas ramas locales que ya tienen su equivalente presente en el repositorio remoto en el que ingresas. Puede usar la --allopción to git-push ("git push --all") para empujar todas las ramas , puede usar "git push < remote > < branch >" para empujar una rama determinada , y puede usar "git push < remoto > CABEZA "para empujar la rama actual .

Todo lo anterior supone que Git no está configurado qué ramas empujar a través de remote.<remotename>.push variables de configuración.

Ramas en busca

Nota: aquí utilizo la terminología de Git donde "buscar" significa descargar cambios desde el repositorio remoto sin integrar esos cambios con el trabajo local. Esto es lo que hace " git fetch" y " hg pull".

Si lo entiendo correctamente, Mercurial busca de forma predeterminada todas las cabezas del repositorio remoto, pero puede especificar la rama para obtener a través de " hg pull --rev <rev> <url>" o " hg pull <url>#<rev>" para obtener una sola rama . Puede especificar <rev> utilizando el identificador de revisión, el nombre de "rama con nombre" (rama incrustada en el registro de cambios) o el nombre del marcador. Sin embargo, el nombre del marcador (al menos actualmente) no se transfiere. Todas las revisiones de "ramas con nombre" que reciba pertenecen para ser transferidas. "hg pull" almacena las puntas de las ramas que obtuvo como cabezas anónimas y sin nombre.

En Git por defecto (para 'origen' remoto creado por "git clone", y para controles remotos creados usando "git remote add") " git fetch" (o " git fetch <remote>") obtiene todas las ramas del repositorio remoto (desde el refs/heads/espacio de nombres), y las almacena en refs/remotes/espacio de nombres Esto significa, por ejemplo, que la rama llamada 'maestro' (nombre completo: 'refs / heads / master') en el 'origen' remoto se almacenaría (guardaría) como la rama de seguimiento remoto 'origen / maestro' (nombre completo: 'refs / controles remotos / origen / maestro ').

Puede obtener una sola rama en Git utilizando git fetch <remote> <branch>: Git almacenaría las ramas solicitadas en FETCH_HEAD, que es algo similar a las cabezas sin nombre de Mercurial.

Esos son solo ejemplos de casos predeterminados de poderosa sintaxis Git de refspec : con refspecs puede especificar y / o configurar qué ramas desea obtener y dónde almacenarlas. Por ejemplo, el caso predeterminado "buscar todas las ramas" está representado por '+ refs / heads / *: refs / remotes / origin / *' comodín refspec, y "buscar una sola rama" es la abreviatura de 'refs / heads / <branch>:' . Las Refspecs se utilizan para asignar nombres de ramas (referencias) en el repositorio remoto a nombres de referencias locales. Pero no necesita saber (mucho) sobre las especificaciones técnicas para poder trabajar eficazmente con Git (gracias principalmente al comando "git remote").

Opinión personal: Personalmente, creo que las "ramas con nombre" (con los nombres de las ramas incrustados en los metadatos del conjunto de cambios) en Mercurial son diseños equivocados con su espacio de nombres global, especialmente para un sistema de control de versiones distribuido . Por ejemplo, tomemos un caso en el que tanto Alice como Bob tienen "rama nombrada" llamada 'for-joe' en sus repositorios, ramas que no tienen nada en común. Sin embargo, en el repositorio de Joe esas dos ramas serían maltratadas como una sola rama. Entonces, de alguna manera, se te ocurrió una convención que protege contra los enfrentamientos de nombres de sucursales. Esto no es problema con Git, donde en el repositorio de Joe la rama 'for-joe' de Alice sería 'alice / for-joe', y de Bob sería 'bob / for-joe'.

Las "sucursales de marcadores" de Mercurial carecen actualmente de un mecanismo de distribución central.

Diferencias:
Esta área es una de las principales diferencias entre Mercurial y Git, como dijeron James Woodyatt y Steve Losh en sus respuestas. Mercurial, por defecto, utiliza líneas de código anónimas y ligeras, que en su terminología se llaman "cabezas". Git usa ramas con nombre livianas, con mapeo inyectivo para mapear nombres de ramas en repositorio remoto a nombres de ramas de seguimiento remoto. Git "lo obliga" a nombrar ramas (bueno, con la excepción de una sola rama sin nombre, situación llamada HEAD separada), pero creo que esto funciona mejor con flujos de trabajo con muchas ramas, como el flujo de trabajo de ramas temáticas, lo que significa múltiples ramas en un solo paradigma de repositorio.

Nombrando revisiones

En Git hay muchas formas de nombrar revisiones (descritas, por ejemplo, en la página de manual de git rev-parse ):

  • El nombre completo del objeto SHA1 (cadena hexadecimal de 40 bytes) o una subcadena de este tipo que es única dentro del repositorio
  • Un nombre de referencia simbólico, por ejemplo, 'maestro' (que se refiere a la rama 'maestro'), o 'v1.5.0' (que se refiere a la etiqueta), o 'origen / siguiente' (que se refiere a la rama de seguimiento remoto)
  • Un sufijo ^para el parámetro de revisión significa el primer padre de un objeto de compromiso, ^nsignifica el enésimo padre de un compromiso de fusión. Un sufijo ~npara el parámetro de revisión significa enésimo antecesor de una confirmación en línea recta de primer padre. Esos sufijos se pueden combinar para formar un especificador de revisión siguiendo la ruta desde una referencia simbólica, por ejemplo, 'pu ~ 3 ^ 2 ~ 3'
  • Salida de "git describe", es decir, una etiqueta más cercana, opcionalmente seguida de un guión y una serie de confirmaciones, seguidas de un guión, una 'g' y un nombre de objeto abreviado, por ejemplo 'v1.6.5.1-75- g5bf8097 '.

También hay especificadores de revisión que involucran reflog, no mencionados aquí. En Git, cada objeto, ya sea commit, tag, tree o blob, tiene su identificador SHA-1; hay una sintaxis especial como, por ejemplo, 'next: Documentation' o 'next: README' para referirse al árbol (directorio) o blob (contenido del archivo) en la revisión especificada.

Mercurial también tiene muchas formas de nombrar conjuntos de cambios (descritos, por ejemplo, en la página de manual de hg ):

  • Un entero simple se trata como un número de revisión. Hay que recordar que los números de revisión son locales para el repositorio dado ; en otro repositorio pueden ser diferentes.
  • Los enteros negativos se tratan como desplazamientos secuenciales desde la punta, con -1 que denota la punta, -2 que denota la revisión anterior a la punta, y así sucesivamente. También son locales para el repositorio.
  • Un identificador de revisión único (cadena hexadecimal de 40 dígitos) o su prefijo único.
  • Un nombre de etiqueta (nombre simbólico asociado con la revisión dada), o un nombre de marcador (con extensión: nombre simbólico asociado con la cabeza dada, local al repositorio), o una "rama con nombre" (etiqueta de compromiso; la revisión dada por "rama con nombre" es punta (confirmación sin hijos) de todas las confirmaciones con una etiqueta de confirmación dada, con el número de revisión más grande si hay más de una sugerencia)
  • El nombre reservado "tip" es una etiqueta especial que siempre identifica la revisión más reciente.
  • El nombre reservado "nulo" indica la revisión nula.
  • El nombre reservado "." indica el directorio de trabajo principal.

Diferencias
Como puede ver al comparar las listas anteriores, Mercurial ofrece números de revisión, locales al repositorio, mientras que Git no. Por otro lado, Mercurial ofrece compensaciones relativas solo desde 'punta' (rama actual), que son locales al repositorio (al menos sin ParentrevspecExtension ), mientras que Git permite especificar cualquier confirmación de seguimiento desde cualquier punta.

La revisión más reciente se llama HEAD en Git y "tip" en Mercurial; no hay revisión nula en Git. Tanto Mercurial como Git pueden tener muchas raíces (pueden tener más de una confirmación sin padres; esto generalmente es el resultado de la unión de proyectos anteriormente separados).

Ver también: Muchos tipos diferentes de artículo de especificadores de revisión en el blog de Elijah (newren's).

Opinión personal: creo que los números de revisión están sobrevalorados (al menos para el desarrollo distribuido y / o el historial no lineal / ramificado). Primero, para un sistema de control de versiones distribuido tienen que ser locales para el repositorio, o requieren tratar algún repositorio de manera especial como una autoridad central de numeración. En segundo lugar, los proyectos más grandes, con un historial más largo, pueden tener varias revisiones en el rango de 5 dígitos, por lo que ofrecen una ligera ventaja sobre los identificadores de revisión acortados a 6-7 caracteres, e implican un pedido estricto, mientras que las revisiones son solo parcialmente ordenadas (quiero decir aquí que las revisiones n y n + 1 no necesitan ser padre e hijo).

Rangos de revisión

En Git, los rangos de revisión son topológicos . La A..Bsintaxis comúnmente vista , que para el historial lineal significa un rango de revisión que comienza en A (pero excluye A) y termina en B (es decir, el rango está abierto desde abajo ), es una forma abreviada ("azúcar sintáctico") para ^A B, que para los comandos de recorrido de historia significa todo commits accesibles desde B, excluyendo aquellos accesibles desde A. Esto significa que el comportamiento del A..Brango es completamente predecible (y bastante útil) incluso si A no es ancestro de B: A..Bsignifica entonces el rango de revisiones del ancestro común de A y B (fusionar base ) a la revisión B.

En Mercurial, los rangos de revisión se basan en el rango de números de revisión . El rango se especifica utilizando la A:Bsintaxis y, al contrario que Git, el rango actúa como un intervalo cerrado . También el rango B: A es el rango A: B en orden inverso, que no es el caso en Git (pero vea la nota a continuación sobre la A...Bsintaxis). Pero tal simplicidad tiene un precio: el rango de revisión A: B solo tiene sentido si A es antepasado de B o viceversa, es decir, con historia lineal; de lo contrario (supongo que) el rango es impredecible, y el resultado es local al repositorio (porque los números de revisión son locales al repositorio).

Esto se soluciona con Mercurial 1.6, que tiene un nuevo rango de revisión topológica , donde 'A..B' (o 'A :: B') se entiende como el conjunto de conjuntos de cambios que son descendientes de X y ancestros de Y. Esto es , Supongo, equivalente a '--ancestry-path A..B' en Git.

Git también tiene notación A...Bpara diferencia simétrica de revisiones; significa A B --not $(git merge-base A B), lo que significa que todas las confirmaciones accesibles desde A o B, pero excluyendo todas las confirmaciones alcanzables desde ambos (alcanzables desde ancestros comunes).

Renombra

Mercurial utiliza el seguimiento de cambio de nombre para tratar los cambios de nombre de los archivos. Esto significa que la información sobre el hecho de que se cambió el nombre de un archivo se guarda en el momento de la confirmación; en Mercurial, esta información se guarda en la forma "diff mejorada" en los metadatos del registro de archivos (registro de archivos). La consecuencia de esto es que debe usar hg rename/ hg mv... o debe recordar ejecutar hg addremovepara hacer una detección de cambio de nombre basada en similitudes.

Git es único entre los sistemas de control de versiones, ya que utiliza la detección de cambio de nombre para tratar los cambios de nombre de archivo. Esto significa que el hecho de que se cambió el nombre del archivo se detecta en el momento en que se necesita: cuando se realiza una fusión o cuando se muestra una diferencia (si se solicita / configura). Esto tiene la ventaja de que el algoritmo de detección de cambio de nombre se puede mejorar y no se congela en el momento de la confirmación.

Tanto Git como Mercurial requieren el uso de la --followopción para seguir los cambios de nombre al mostrar el historial de un solo archivo. Ambos pueden seguir los cambios de nombre cuando se muestra el historial en línea de un archivo en git blame/ hg annotate.

En Git, el git blamecomando puede seguir el movimiento del código, también mover (o copiar) el código de un archivo a otro, incluso si el movimiento del código no forma parte del cambio de nombre del archivo. Hasta donde yo sé, esta característica es exclusiva de Git (en el momento de la redacción, octubre de 2009).

Protocolos de red

Tanto Mercurial como Git tienen soporte para buscar y empujar a repositorios en el mismo sistema de archivos, donde la URL del repositorio es solo una ruta del sistema de archivos al repositorio. Ambos también tienen soporte para recuperar archivos de paquete .

Soporte Mercurial para buscar y empujar a través de SSH y protocolos HTTP. Para SSH, se necesita una cuenta de shell accesible en la máquina de destino y una copia de hg instalada / disponible. Para el acceso HTTP hg-servese requiere la ejecución del script Mercurial CGI, y Mercurial debe instalarse en la máquina del servidor.

Git admite dos tipos de protocolos utilizados para acceder al repositorio remoto:

  • Los protocolos "inteligentes" , que incluyen el acceso a través de SSH y a través del protocolo personalizado git: // (by git-daemon), requieren tener instalado git en el servidor. El intercambio en esos protocolos consiste en que el cliente y el servidor negocien sobre qué objetos tienen en común y luego generen y envíen un paquete. Modern Git incluye soporte para el protocolo HTTP "inteligente".
  • Los protocolos "tontos" , que incluyen HTTP y FTP (solo para buscar) y HTTPS (para enviar a través de WebDAV), no requieren que git esté instalado en el servidor, pero sí requieren que el repositorio contenga información adicional generada por git update-server-info(generalmente se ejecuta desde un enlace ) El intercambio consiste en que el cliente recorre la cadena de confirmación y descarga objetos sueltos y archivos de paquete según sea necesario. La desventaja es que se descarga más de lo estrictamente requerido (por ejemplo, en el caso de una esquina cuando solo hay un solo paquete, se descargará completo incluso cuando se obtienen solo unas pocas revisiones), y que puede requerir muchas conexiones para finalizar.

Ampliación: capacidad de escritura frente a extensiones (complementos)

Mercurial se implementa en Python , con un código central escrito en C para el rendimiento. Proporciona API para escribir extensiones (complementos) como una forma de agregar funciones adicionales. Parte de la funcionalidad, como "sucursales de marcadores" o revisiones de firma, se proporciona en extensiones distribuidas con Mercurial y requiere activarla.

Git se implementa en C , Perl y scripts de shell . Git proporciona muchos comandos de bajo nivel ( plomería ) adecuados para usar en scripts. La forma habitual de introducir una nueva característica es escribirla como Perl o script de shell, y cuando la interfaz de usuario se estabilice, vuelva a escribirla en C para obtener rendimiento, portabilidad y, en el caso de script de shell, evitar los casos de esquina (este procedimiento se llama builtinificación ).

Git se basa y se basa en formatos [repositorios] y protocolos [de red]. En lugar de enlaces de lenguaje, hay reimplementaciones (parciales o completas) de Git en otros idiomas (algunos de ellos son parcialmente reimplementaciones y parcialmente envolturas alrededor de comandos git): JGit (Java, usado por EGit, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #).


TL; DR

Jakub Narębski
fuente
32
Lo que se podría agregar es que hg se esfuerza mucho para desalentar la reescritura de la historia (solo se puede hacer con extensiones: mq, histedit, rebase), mientras que git lo hace fuera de la caja (y parece parte de la comunidad incluso lo alienta).
tonfa
80
Creo que "reescribir la historia" suena innecesariamente negativo. Lo que animo en git es que las personas consideren la historia que publican. Otras personas necesitan consumir esa historia. Nadie (ni siquiera usted) está interesado en todas sus confirmaciones de "Ups, olvidé un archivo". A nadie le importa la serie de fusiones entrantes que atravesó mientras estaba rastreando una rama ascendente mientras trabajaba en una nueva función. Ese tipo de cosas hace que la historia (y las herramientas relacionadas) sean mucho más difíciles de entender y no aporta ningún valor.
Dustin
55
@Jakub: las ramas con nombre son algo que no existe en git. Es simplemente un campo en la descripción del cset (y eso es parte del historial, por lo que es inmutable a menos que cambie hashes, etc.). Algo así como las ramas de git son marcadores ("cabezas con nombre") pero actualmente no son transferibles de forma remota (no importa los marcadores remotos al extraer). stevelosh.com/blog/entry/2009/8/30/… lo explica muy bien.
tonfa
28
"Mercurial originalmente admitía solo una rama por flujo de trabajo del repositorio, y se nota". UH no. Mercurial no admitía ramas con nombre originalmente, pero siempre ha podido tener tantas ramas anónimas como su corazón desea en un solo repositorio. Compare eso con git, que hace que la ramificación anónima sea un gran dolor. Más o menos, tiene que pensar en un nombre para cada pequeña rama si quiere hacer nada (y evitar que su trabajo de basura recolectada).
Steve Losh
17
@SteveLosh: parece pensar que tener muchas sucursales anónimas en Mercurial es algo bueno, pero a mí me parece horrible. ¿Cómo los distingue a todos? Y parece pensar que nombrar ramas en Git es una dificultad enorme, pero si tiene un propósito para crear la rama, entonces tiene un nombre listo. Si no tiene ningún propósito, no se ramifique. No veo cómo Mercurial ofrece algún beneficio aquí. Solo veo dolor y confusión.
iconoclasta
57

Creo que puedes tener una idea de en qué se parecen o difieren esos sistemas al ver esos dos videos:

Linus Torvalds en Git ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Bryan O'Sullivan en Mercurial ( http://www.youtube.com/watch?v=JExtkqzEoHY )

Ambos son muy similares en diseño pero muy diferentes en implementaciones.

Yo uso Mercurial. Por lo que yo entiendo Git, una cosa importante que Git es diferente es que rastrea el contenido de los archivos en lugar de los archivos en sí. Linus dice que si mueve una función de un archivo a otro, Git le contará el historial de esa única función a través del movimiento.

También dicen que git es más lento que HTTP pero tiene su propio protocolo de red y servidor.

Git funciona mejor como un cliente grueso SVN que Mercurial. Puede tirar y empujar contra un servidor SVN. Esta funcionalidad aún está en desarrollo en Mercurial

Tanto Mercurial como Git tienen soluciones de alojamiento web muy buenas disponibles (BitBucket y GitHub), pero Google Code solo admite Mercurial. Por cierto, tienen una comparación muy detallada de Mercurial y Git que hicieron para decidir cuál admitir ( http://code.google.com/p/support/wiki/DVCSAnalysis ). Tiene mucha buena información.

artemb
fuente
8
Recomiendo leer todos los comentarios en esa página de códigos de google. La información se siente un tanto sesgada y no coincide con mi experiencia. Me gusta hg, y lo usé ampliamente durante un año más o menos. Yo uso git casi exclusivamente ahora. Hay cosas que necesito lograr que git hace fácil y hg hace casi imposible (aunque a algunos les gusta llamarlo por "complicación"). Git básico es tan fácil como la base hg.
Dustin
11
Dustin, ¿quizás enumeres algunos de esos casos de "git easy, hg no tanto"?
Gregg Lind el
1
@knittl no, no lo hace. Principalmente porque sería un problema para ellos implementarlo ya que git carece de un protocolo http inteligente (la mayoría de los front-end de Google están basados ​​en http).
tonfa
2
@tonfa: el protocolo HTTP inteligente para Git se está desarrollando actualmente (como en: hay parches en la lista de correo de git, y están en 'pu' = rama de actualizaciones propuestas en el repositorio de git.git).
Jakub Narębski
44
A partir de ahora, Google Code también es compatible con Git.
Andrej Kirejeŭ
30

Escribí una entrada de blog sobre los modelos de ramificación de Mercurial hace un tiempo, e incluí comparaciones con el modelo de ramificación de git. Quizás lo encuentres interesante: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/

Steve Losh
fuente
@Steve Losh: quería comentar sobre esta entrada del blog (sobre la rama sin nombre, también conocida como HEAD separada, y sobre git-fetch para buscar todas las ramas, no una), pero obtuve un error de 500 servidores.
Jakub Narębski
1
@Jakub Narębski Apuesto a que el problema es el carácter no ASCII a tu nombre Estoy bastante seguro de que me encontré con el mismo problema en otro sitio y resultó que el enlace Python Askimet se ahoga en Unicode. Le daré un vistazo.
Steve Losh
@ Steve Losh: Gracias por una información, después de "descodificar" mi nombre pude publicar un comentario. Muy buena descripción de la ramificación en Mercurial (pero sigo pensando que es inferior ;-))
Jakub Narębski
@SteveLosh Le animo a ampliar esta respuesta a una revisión más completa de mercurial. En este momento, la respuesta principal es, desafortunadamente, en gran medida un anuncio para git porque su autor no ha usado mercurial ampliamente y no entiende cómo usarlo de manera efectiva. Sería bueno que otra respuesta proporcione el punto de vista mercurial, por así decirlo.
Warren Dew
25

Yo uso ambos con bastante regularidad. La principal diferencia funcional está en la forma en que Git y Mercurial se ramifican dentro de los repositorios. Con Mercurial, los nombres de las ramas se clonan y se extraen junto con sus conjuntos de cambios. Cuando agrega cambios a una nueva rama en Mercurial y lo transfiere a otro repositorio, el nombre de la rama se transfiere al mismo tiempo. Por lo tanto, los nombres de las sucursales son más o menos globales en Mercurial, y debe usar la extensión Bookmark para tener nombres ligeros solo locales (si lo desea; Mercurial, de forma predeterminada, utiliza líneas de código ligeras anónimas, que en su terminología son llamado "cabezas"). En Git, los nombres de las sucursales y su asignación inyectiva a las sucursales remotas se almacenan localmente y debe administrarlos explícitamente, lo que significa saber cómo hacerlo.

Como otros notarán aquí, hay muchísimas diferencias menores. Lo que pasa con las ramas es el gran diferenciador.

james woodyatt
fuente
2
Vea también esta publicación para una buena explicación sobre los cuatro tipos de sucursales en Mercurial: stevelosh.com/blog/entry/2009/8/30/…
Martin Geisler
19

Eche un vistazo a Git vs. Mercurial: Por favor, relájese en la publicación de blog de Patrick Thomson, donde escribe:
Git es MacGyver , Mercurial es James Bond

Tenga en cuenta que esta publicación de blog es del 7 de agosto de 2008, y tanto SCM mejoró mucho desde entonces.

Jakub Narębski
fuente
11

Mercurial está casi completamente escrito en python. El núcleo de Git está escrito en C (y debería ser más rápido que el de Mercurial) y las herramientas escritas en sh, perl, tcl y utiliza utilidades GNU estándar. Por lo tanto, necesita llevar todas estas utilidades e intérpretes al sistema que no las contiene (por ejemplo, Windows).

Ambos soportes funcionan con SVN, aunque el soporte de AFAIK svn está roto para git en Windows (puede ser que solo tenga mala suerte / cojo, quién sabe). También hay extensiones que permiten interoperar entre git y Mercurial.

Mercurial tiene una buena integración de Visual Studio . La última vez que lo comprobé, el complemento para Git funcionaba pero era extremadamente lento.

Los conjuntos de comandos básicos son muy similares (init, clone, add, status, commit, push, pull, etc.). Entonces, el flujo de trabajo básico será el mismo. Además, hay un cliente similar a TortoiseSVN para ambos.

Las extensiones para Mercurial se pueden escribir en python (¡no es de extrañar!) Y para git se pueden escribir en cualquier forma ejecutable (binario ejecutable, script de shell, etc.). Algunas extensiones son locamente poderosas, como git bisect.

elder_george
fuente
99
El núcleo Mercurial está escrito en C también para su información (pero probablemente sea un núcleo más pequeño que git).
tonfa
1
Yo uso git-svn en Windows sin ningún problema. Eso es usar Cygwin (la única forma correcta de usar git en Windows si me preguntas). No puedo hablar por msysgit.
Dan Molding el
@Dan Molding: Sí, he tenido problemas con msysgit. Tal vez necesite probar el puerto cygwin (tenía poca experiencia en el uso de cygwin antes, así que lo evité). ¡Gracias por el consejo!
elder_george
Personalmente, no me gusta la intrusión de Cygwin en el registro para almacenar datos de usuarios. Es un PITA hacer que se ejecute fuera de la memoria USB y mantener una copia local de la unidad c: \ sincronizada para cuando quiero ejecutar más rápido de lo que puede ir mi memoria USB. : - /
Chris K
1
Utilizo el complemento Git para Visual Studio mencionado anteriormente, y el rendimiento de la versión actual es bueno. Se aplica a las herramientas de línea de comandos para hacer el trabajo, por lo que no creo que pierda significativamente el rendimiento en grandes proyectos.
Stuart Ellis el
11

Si necesita un buen soporte de Windows, puede preferir Mercurial. TortoiseHg (complemento del explorador de Windows) se las arregla para ofrecer una interfaz gráfica fácil de usar a una herramienta bastante compleja. Como se indica aquí, también tendrá un complemento de Visual Studio . Sin embargo, la última vez que lo intenté, la interfaz SVN no funcionó tan bien en Windows.

Si no te importa la interfaz de línea de comandos, recomendaría Git. No por razones técnicas, sino por razones estratégicas. La tasa de adopción de git es mucho mayor. Solo vea cuántos proyectos famosos de código abierto están cambiando de cvs / svn a Mercurial y cuántos están cambiando a Git. Vea cuántos proveedores de alojamiento de código / proyecto puede encontrar con soporte git en comparación con el alojamiento Mercurial.

Eric Darchis
fuente
También hay TortoiseGit, si no te gusta usar la línea de comando. (Pero requiere que se instale msysgit).
Ben James
2
Nuestra empresa terminó eligiendo git debido a su gran soporte en Windows: consulte Extensiones de Git . Soy parcial porque ahora soy un colaborador, pero no lo era cuando comenzamos a usarlo.
Jacob Stanley
11

Después de leer todo eso, Mercurial es más fácil (lo que todavía creo que es, después de que toda la comunidad de Internet es de la opinión), cuando comencé a trabajar con Git y Mercurial sentí que Git es relativamente más fácil de adaptar (comencé con Mercurial con TortoiseHg) cuando se trabaja desde la línea de comandos, principalmente porque los comandos git fueron nombrados apropiadamente de acuerdo a mí y son menos numerosos. Mercurial tiene diferentes nombres para cada comando que realiza un trabajo distinto, mientras que los comandos Git pueden ser multipropósito según la situación (por ejemplo,checkout) Si bien Git era más difícil en aquel entonces, ahora la diferencia es apenas sustancial. YMMV .. Con un buen cliente GUI como TortoiseHg, es cierto que fue mucho más fácil trabajar con Mercurial y no tuve que recordar los comandos ligeramente confusos. No voy a entrar en detalles sobre cómo variaba cada comando para la misma acción, pero aquí hay dos listas completas: 1 del sitio de Mercurial y la segunda de wikivs .

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           Git               ║                Mercurial                                                                       ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull                    ║ hg pull -u                                                                                     ║
║ git fetch                   ║ hg pull                                                                                        ║
║ git reset --hard            ║ hg up -C                                                                                       ║
║ git revert <commit>         ║ hg backout <cset>                                                                              ║
║ git add <new_file>          ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.)                            ║
║ git add <file>              ║ Not necessary in Mercurial.                                                                    ║
║ git add -i                  ║ hg record                                                                                      ║
║ git commit -a               ║ hg commit                                                                                      ║
║ git commit --amend          ║ hg commit --amend                                                                              ║
║ git blame                   ║ hg blame or hg annotate                                                                        ║
║ git blame -C                ║ (closest equivalent): hg grep --all                                                            ║
║ git bisect                  ║ hg bisect                                                                                      ║
║ git rebase --interactive    ║ hg histedit <base cset> (Requires the HisteditExtension.)                                      ║
║ git stash                   ║ hg shelve (Requires the ShelveExtension or the AtticExtension.)                                ║
║ git merge                   ║ hg merge                                                                                       ║
║ git cherry-pick <commit>    ║ hg graft <cset>                                                                                ║
║ git rebase <upstream>       ║ hg rebase -d <cset> (Requires the RebaseExtension.)                                            ║
║ git format-patch <commits>  ║ hg email -r <csets> (Requires the PatchbombExtension.)                                         ║
║   and git send-mail         ║                                                                                                ║
║ git am <mbox>               ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)  ║
║ git checkout HEAD           ║ hg update                                                                                      ║
║ git log -n                  ║ hg log --limit n                                                                               ║
║ git push                    ║ hg push                                                                                        ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝

Git guarda un registro de cada versión de archivos comprometidos internamente, mientras que Hg guarda solo los conjuntos de cambios que pueden tener una huella más pequeña. Git hace que sea más fácil cambiar la historia en comparación con Hg, pero de nuevo es una función de odiar o amar. Me gusta Hg para el primero y Git para el segundo.

Lo que extraño en Hg es la función de submódulo de Git. Hg tiene subrepos pero eso no es exactamente el submódulo Git.

El ecosistema alrededor de los dos también puede influir en la elección de uno: Git tiene que ser más popular (pero eso es trivial), Git tiene GitHub mientras que Mercurial tiene BitBucket , Mercurial tiene TortoiseHg para el cual no he visto un equivalente tan bueno para Git.

Cada uno tiene sus ventajas y desventajas, con cualquiera de ellos no vas a perder.

nawfal
fuente
8

Echa un vistazo a la publicación de Scott Chacon desde hace un tiempo.

Creo que git tiene la reputación de ser "más complicado", aunque en mi experiencia no es más complicado de lo que debería ser. En mi opinión, el modelo git es mucho más fácil de entender (las etiquetas contienen confirmaciones (y los punteros a cero o más confirmaciones principales) contienen árboles contienen blobs y otros árboles ... hecho).

No es solo mi experiencia que git no es más confuso que mercurial. Recomiendo nuevamente leer esta publicación de blog de Scott Chacon sobre el tema.

Dustin
fuente
1
El modelo Mercurial es en realidad casi idéntico: los puntos de registro de cambios al punto de manifiesto a las revisiones de archivos / blob ... hecho. Si estaba comparando el formato en disco, probablemente no tuvo en cuenta el archivo de paquetes, que es más difícil de explicar que el simple formato de revlog de hg.
tonfa
Bueno, ese modelo simplificado ignora el etiquetado que es considerablemente más complicado en la práctica en hg (aunque sí sostengo que git tag es un poco confuso porque no crea un objeto de etiqueta por defecto). El formato en disco fue particularmente costoso para ambos proyectos que tenían un historial de muchos nombres de archivo.
Dustin
1
No creo que el modelo ignore el etiquetado: el etiquetado es trivial en Mercurial; como saben, es solo un archivo que da nombres a los hash SHA-1. No hay conjeturas sobre cómo fluyen las etiquetas en el sistema: se mueven junto con empujes y tirones. Y si hay un conflicto de etiquetas, entonces también es trivial resolverlo: lo resuelve como cualquier otro conflicto. Después de todo, es solo una línea en un archivo de texto. Creo que la simplicidad de este modelo es una característica muy agradable.
Martin Geisler
Dustin: Sí, los usuarios a menudo están confundidos por el hecho de que no puedes ver la etiqueta 1.0 .hgtagscuando has revisado la revisión 1.0. Sin embargo, no necesita mirar dentro .hgtagsy encontrará que hg tagstodavía enumera todas las etiquetas. Además, este comportamiento es una consecuencia simple del almacenamiento de etiquetas en un archivo controlado por versión; nuevamente, el modelo es fácil de entender y muy predecible .
Martin Geisler
1
Martin Geisler Yo diría que las reglas para las etiquetas en Mercurial, requeridas porque usa un archivo controlado por la versión para el transporte, con capas en reglas especiales para hacer que las etiquetas no estén versionadas, es cualquier cosa menos fácil de entender.
Jakub Narębski
5

Utilicé Git durante poco más de un año en mi trabajo actual, y antes de eso, utilicé Mercurial durante un poco más de un año en mi trabajo anterior. Voy a proporcionar una evaluación desde la perspectiva de un usuario.

Primero, ambos son sistemas de control de versiones distribuidos. Los sistemas de control de versiones distribuidos requieren un cambio de mentalidad de los sistemas de control de versiones tradicionales, pero en realidad funcionan mucho mejor de muchas maneras una vez que uno los comprende. Por esta razón, considero que Git y Mercurial son muy superiores a Subversion, Perforce, etc. La diferencia entre los sistemas de control de versiones distribuidos y los sistemas de control de versiones tradicionales es mucho mayor que la diferencia entre Git y Mercurial.

Sin embargo, también hay diferencias significativas entre Git y Mercurial que hacen que cada uno se adapte mejor a su propio subconjunto de casos de uso.

Mercurial es más simple de aprender. Llegué al punto en que rara vez tuve que referirme a la documentación o notas después de unas semanas de usar Mercurial; Todavía tengo que consultar mis notas regularmente con Git, incluso después de usarlo durante un año. Git es considerablemente más complicado.

Esto se debe en parte a que Mercurial es simplemente más limpio. Raramente tiene que bifurcarse manualmente en Mercurial; Mercurial creará una sucursal anónima automáticamente para usted si lo necesita. La nomenclatura mercurial es más intuitiva; no tiene que preocuparse por la diferencia entre "buscar" y "extraer" como lo hace con Git. Mercurial es un poco menos buggy. Hay problemas de mayúsculas y minúsculas en los nombres de archivos que solían causar problemas al impulsar proyectos a través de plataformas con Git y Mercurial; Esto se solucionó en Mercurial hace algún tiempo, mientras que no se habían solucionado en Git la última vez que lo revisé. Puede decirle a Mercurial sobre el cambio de nombre de los archivos; con Git, si no detecta el cambio de nombre automáticamente, una propuesta muy acertada o errónea en mi experiencia, el cambio de nombre no se puede rastrear en absoluto.

Sin embargo, la otra razón de la complicación adicional de Git es que se necesita mucho para admitir funciones y potencia adicionales. Sí, es más complicado manejar la ramificación en Git, pero por otro lado, una vez que tienes las ramas, no es demasiado difícil hacer cosas con esas ramas que son prácticamente imposibles en Mercurial. Rebasar ramas es una de estas cosas: puede mover su rama de modo que su base, en lugar de ser el estado del tronco cuando se ramificó, sea el estado del tronco ahora; esto simplifica enormemente el historial de versiones cuando hay muchas personas trabajando en la misma base de código, ya que cada uno de los empujes al tronco puede aparecer de forma secuencial, en lugar de entrelazarse. Del mismo modo, es mucho más fácil contraer varias confirmaciones en su rama en una sola confirmación,

En última instancia, creo que la elección entre Mercurial y Git debería depender de qué tan grandes sean sus proyectos de control de versiones, medidos en términos de la cantidad de personas que trabajan en ellos simultáneamente. Si tiene un grupo de una docena o más trabajando en una sola aplicación web monolítica, por ejemplo, las herramientas de administración de sucursales más potentes de Git lo harán mucho mejor para su proyecto. Por otro lado, si su equipo está desarrollando un sistema distribuido heterogéneo, con solo uno o dos desarrolladores trabajando en cualquier componente al mismo tiempo, el uso de un repositorio Mercurial para cada uno de los proyectos de componentes permitirá que el desarrollo avance más suavemente con menos gestión del repositorio de gastos generales.

En pocas palabras: si tiene un gran equipo desarrollando una sola aplicación enorme, use Git; Si sus aplicaciones individuales son pequeñas, y cualquier escala proviene del número en lugar del tamaño de dichas aplicaciones, use Mercurial.

Warren Dew
fuente
4

Una diferencia totalmente ajena a los DVCS mismos:

Git parece ser muy popular entre los desarrolladores de C. Git es el repositorio de facto para el kernel de Linux y esta puede ser la razón por la que es tan popular entre los desarrolladores de C. Esto es especialmente cierto para aquellos que tienen el lujo de trabajar solo en el mundo Linux / Unix.

Los desarrolladores de Java parecen favorecer a Mercurial sobre Git. Posiblemente hay dos razones para eso: una es que varios proyectos Java muy grandes están alojados en Mercurial, incluido el JDK mismo. Otra es que la estructura y la documentación limpia de Mercurial atrae a las personas que vienen del campamento de Java, mientras que esas personas encuentran que el comando wrt inconsistente de Git nombra y carece de documentación. No digo que eso sea realmente cierto, digo que las personas se han acostumbrado a algo de su hábitat habitual y luego tienden a elegir DVCS de eso.

Los desarrolladores de Python favorecen casi exclusivamente a Mercurial, supongo. En realidad, no hay una razón racional para eso aparte del hecho de que Mercurial se basa en Python. (También uso Mercurial y realmente no entiendo por qué la gente hace tanto escándalo por el lenguaje de implementación del DVCS. No entiendo una palabra de Python y si no fuera por el hecho de que aparece en alguna parte que se basa en Python, entonces no lo habría sabido).

No creo que pueda decir que un DVCS se adapta mejor a un idioma que otro, por lo que no debe elegir entre eso. Pero, en realidad, las personas eligen (en parte) según el DVCS al que están más expuestos como parte de su comunidad.

(no, no tengo estadísticas de uso para respaldar mis afirmaciones anteriores ... todo se basa en mi propia subjetividad)

Peter
fuente