2009-10-31 13 views
11

Los tres grandes del control de versión distribuida (Git, Bazaar y Mercurial) tratan cada uno ramificación de forma bastante diferente. En Bazar, por ejemplo, las sucursales son repos separados (en realidad, copias divergentes del repositorio principal); en su sistema de archivos, diferentes ramas viven en diferentes directorios. En Git, por otro lado, puede tener múltiples ramas existentes en el mismo repositorio (y, por lo tanto, en el mismo directorio en su sistema de archivos). Mercurial admite both behaviors, este último con named branches.Pros y contras de diferentes modelos de ramificación en DVCS

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

+4

sucursales con nombre es bastante diferente de las sucursales de git, consulte aquí para más detalles: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/ – tonfa

+0

Vea también mi respuesta en "Git y Mercurial - Compare and Contrast", que también abarca las sucursales: http://stackoverflow.com/questions/1598759/git-and-mercurial-compare-and-contrast/1599930#1599930 –

+0

Hombre, tonfa siempre ¡logra publicar mi entrada de blog antes que yo! :) –

Respuesta

9

Bazaar no requiere que trabajes de la manera que describes. De hecho, he escrito a blog post sobre eso hace dos días. Puede trabajar prácticamente con un único árbol de trabajo, cambiando entre varias ramas y creando nuevas ramas sin abandonar el árbol de trabajo. Los comandos útiles para esto son: checkout, switch, branch --switch. Consulte la documentación de workflow para Bazar, verá que puede configurarlo de la forma que desee.

+0

Es bueno saber que Bazar es más flexible de lo que pensaba. En realidad, me preguntaba si la creación de un directorio "branches" dentro de su repos podría resolver el problema que mencioné en mi pregunta. Gracias por la visión. – ThisSuitIsBlackNot

6

No sé mucho sobre los modelos de bifurcación en VCS distintos de Git. Yo diría que en cualquier DVCS puedes implementar la ramificación clonando (creas una rama haciendo un clon). Mercurial llamadas "ramas nombradas" son (de acuerdo con lo que yo entiendo) de hecho cometer etiquetas solo se interpreta como una rama, que a veces requiere la numeración local de las revisiones para resolver la ambigüedad. Mercurial "marcadores" ar, creo, bastante similar a las ramas de Git. Los dos DVCS que tienen muy concepto diferente de ramificación son Monotone y Darcs. Creo que la "ramificación mediante copia" 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 revisiones Git forman un gráfico acíclico dirigido (DAG) de confirmaciones. Está dirigido, porque los commits tienen padres. Esa es una cuestión muy importante: los bordes en el DAG de confirmaciones son de compromiso a 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 objeto.

Git glossary define "rama" 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 rama se conoce como tip de esa rama. La punta de la bifurcación está referenciada por un ramal , que es solo un nombre simbólico para este compromiso. En su forma "suelta" tal ramificación (por ejemplo para una rama llamada 'maestra') es simplemente un archivo en algún lugar del directorio refs/heads/ dentro del repositorio git (dentro de .git dir), que contiene referencia al consejo actual de una rama: su SHA-1 identificador de commit (como cadena hexadecimal).

Cuando crea una nueva confirmación en Git, la rama de la rama actualmente desprotegida se mueve hacia adelante. En otras palabras, la nueva confirmación se crea en la parte superior de la rama 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 pila).

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

Por ejemplo si se activa actualmente fuera rama es 'maestro', entonces .git/HEAD archivo (cabeza que representa) contendría sola LF línea con ref: refs/heads/master (una referencia simbólica a refs/heads/master), y .git/refs/heads/master (cabeza de la rama de 'maestro') terminado sería Contiene, por ejemplo, la línea terminada en LF 0b127cb8ab975e43398a2b449563ccb78c437255, que es el identificador SHA-1 a la punta de la rama 'principal' (es decir, si la rama actual no está "empaquetada": entonces hay que echar un vistazo a .git/packed-refs).

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

El comando "git log branch" muestra todos los commits accesibles desde la sugerencia de la rama, lo que significa que la rama de sucursal, sus padres, padres (o padres) comprometen etc. Muestra una parte de un DAG de confirmaciones.

En Git, eliminar una rama significa simplemente quitar una rama. Eso podría significar que algunos commits se vuelven "invisibles", los freom refs inalcanzables (ramas y etiquetas), lo que significa que en algún momento esos commits podrían ser recogidos y eliminados del repositorio. Pero si puede eliminar la sucursal con "git branch -d <branchname>", 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 rama es simplemente una cuestión de cambiar el nombre de la cabeza de la rama, una referencia simbólica (nombre simbólico) de la punta de la rama; los nombres de las ramas no se guardan en ningún lugar del objeto de confirmación.


Git tiene también el concepto de reflogs, que es una historia local de donde señaló punta de la rama (y cuándo). Por ejemplo, si modifica una confirmación con "git commit --amend", la sugerencia de bifurcación se reemplazarí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 entrada 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 breve, el reflog brinda seguridad adicional y una recuperación fácil a los comandos de git.

Cuestiones relacionadas