Pros y contras de diferentes models de ramificación en DVCS

Los tres grandes del control de versión distribuida (Git, Bazaar y Mercurial) tratan cada uno ramificación de manera bastante diferente. En Bazar, por ejemplo, las sucursales son repos separados (en realidad, copys divergentes del repository principal); en su sistema de files, diferentes twigs viven en diferentes directorys. En Git, por otro lado, puede tener múltiples twigs existentes en el mismo repository (y, por lo tanto, en el mismo directory en su sistema de files). Mercurial admite ambos comportamientos , el último con twigs nombradas .

¿Cuáles son los pros y los contras asociados con estos diferentes models de ramificación? En mi opinión, el enfoque de Bazar de una twig, un repository hace que la ramificación sea más dolorosa que el enfoque de Git (por ejemplo, para usar una twig en Bazar, primero tengo que crear la twig, luego sacar mi copy de trabajo actual, luego verificar la nueva twig, como lo haría en SVN).

Bazar no requiere que trabajes de la manera que describes. De hecho, escribí una publicación en el blog sobre esto hace dos días. Puede trabajar prácticamente con un único tree de trabajo, cambiando entre varias twigs y creando nuevas twigs sin abandonar el tree de trabajo. Los commands útiles para esto son: checkout , switch , branch --switch . Consulte la documentation del flujo de trabajo para Bazar, verá que puede configurarlo de la forma que desee.

No sé mucho sobre los models de ramificación en VCS distintos de Git. Diría que en cualquier DVCS puede implementar ramificación mediante clonación (crea una twig haciendo un clon). Las llamadas "twigs nombradas" de Mercurial son (de acuerdo con lo que yo entiendo) de hecho, las tags de compromiso solo se interpretan como una sucursal, a veces requieren la numeración local de las revisiones para resolver la ambigüedad. Mercurial "marcadores" ar, creo, bastante similar a las twigs de Git. Los dos DVCS que tienen un concepto muy diferente de ramificación son Monotone y Darcs . Creo que la "ramificación mediante copy" que utiliza Subversion, donde la separación entre el nombre del proyecto y el nombre de la sucursal es por convención , es una idea equivocada.


En las revisiones de Git, se forma un gráfico acíclico dirigido (DAG) de commits. Está dirigido, porque los commits tienen padres. Esa es una cuestión muy importante: los bordes en el DAG de confirmaciones son de compromiso con su padre (o, en el caso de fusión, dos o más de sus padres). El gráfico de confirmaciones es acíclico, lo que significa que no hay cadena (ninguna ruta) que comienza y termina con el mismo object.

El glosario de Git define "twig" como una línea de desarrollo activa . Esta idea está detrás de una implementación de sucursales en Git.

La confirmación más reciente en una twig se conoce como la punta de esa twig. La punta de la twig es referenceda por un encabezado de twig , que es solo un nombre simbólico para esta confirmación. En su forma "suelta" tal ramificación (por ejemplo para una twig llamada 'maestra') es simplemente un file en algún lugar del directory refs/heads/ dentro del repository git (dentro de .git dir), que contiene reference al consejo actual de una twig: su identificador de compromiso SHA-1 (como cadena hexadecimal).

Cuando creas una nueva confirmación en Git, la twig de la twig actualmente desprotegida se mueve hacia adelante. En otras palabras, la nueva confirmación se crea en la parte superior de la twig de la sucursal actual, y la cabeza de la bifurcación avanza a la nueva confirmación (algo similar a cómo podría avanzar el puntero a la parte superior de la stack).

Un solo repository de git puede rastrear un número arbitrario de twigs, pero su tree de trabajo (si tiene alguno) está asociado con solo uno de ellos (la twig "actual" o "desprotegida"). La twig actual viene dada por el puntero HEAD. HEAD es (usualmente) un puntero a la twig actualmente desprotegida (a un nombre de la cabeza de una twig), al igual que las cabezas de las twigs son pointers a las puntas de las twigs.

Por ejemplo, si la twig actualmente desprotegida es 'master', entonces el file .git/HEAD (que representa HEAD) contendría una sola línea terminada en LF con ref: refs/heads/master (una reference simbólica a refs/heads/master ), y .git/refs/heads/master (cabeza de la twig 'master') contendría, por ejemplo, la línea terminada en LF 0b127cb8ab975e43398a2b449563ccb78c437255 , que es el identificador SHA-1 a la punta de la twig 'master' (esto es, si la twig actual no está "empacada") tienes que echarle un vistazo a .git/packed-refs ).

Algunos commands en Git, como "git commit" o "git reset" manipulan / cambian el encabezado de la twig; otros como "git checkout" manipula / cambia HEAD (reference simbólica a la twig actual).

El command " git log branch " muestra todos los commits accesibles desde la sugerencia de la twig, lo que significa que la punta de la twig, su padre, padre (o padres) de ese padre se comprometen, etc. Muestra una parte de un DAG de confirmaciones.

En Git, eliminar una twig significa simplemente eliminar una twig. Eso podría significar que algunos commits se vuelven "invisibles", los freom refs inalcanzables (twigs y tags), lo que significa que en algún momento esos commits podrían ser recogidos y eliminados del repository. Pero si puede eliminar la twig con "git branch -d <branchname>", eso significa que no se perderán las confirmaciones; puede forzar la eliminación de la sucursal con "git branch -D <branchname>". Cambiar el nombre de una twig es simplemente una cuestión de cambiar el nombre de la cabeza de la twig, una reference simbólica (nombre simbólico) de la punta de la twig; los nombres de las twigs no se guardan en ningún lugar del object de confirmación.


Git también tiene un concepto de reflogs , que es una historia local de donde señala la punta de la twig (y cuándo). Por ejemplo, si modifica una confirmación con "git commit –amend", la sugerencia de bifurcación se replaceía con commit modificado, y HEAD ^ sería padre de la confirmación antes y después de la modificación, mientras que habría una input en reflog para la versión antes de modificar y después de enmendar Si rebobinas el historial usando "git reset", el reflog contendría información de la anterior sugerencia de bifurcación antes de rebobinar.

En resumen, el reflog brinda security adicional y una recuperación fácil a los commands de git.