La mayor diferencia es cómo se registran los nombres de las sucursales en el historial. Con las ramas con nombre, el nombre de la rama se incrusta en cada conjunto de cambios y, por lo tanto, se convertirá en una parte inmutable de la historia. Con los clones no habrá un registro permanente de dónde vino un conjunto de cambios en particular.
Esto significa que los clones son excelentes para experimentos rápidos en los que no desea registrar el nombre de una rama, y las ramas con nombre son buenas para las ramas a largo plazo ("1.x", "2.x" y similares).
Tenga en cuenta también que un único repositorio puede acomodar fácilmente múltiples ramas livianas en Mercurial. Tales ramas en el repositorio pueden marcarse para que pueda encontrarlas fácilmente nuevamente. Digamos que ha clonado el repositorio de la compañía cuando se veía así:
[a] --- [b]
Hackeas y haces [x]
y [y]
:
[a] --- [b] --- [x] --- [y]
Es decir, mientras alguien pone [c]
y [d]
entra en el repositorio, así que cuando tire obtendrá un gráfico de historia como este:
[x] --- [y]
/ /
[a B C D]
Aquí hay dos cabezas en un solo repositorio. Su copia de trabajo siempre reflejará un único conjunto de cambios, la llamada copia de trabajo del conjunto de cambios principal. Comprueba esto con:
% hg parents
Digamos que informa [y]
. Puedes ver las cabezas con
% hg heads
y esto informará [y]
y [d]
. Si desea actualizar su repositorio a un pago limpio de [d]
, simplemente haga (sustituya [d]
con el número de revisión [d]
):
% hg update --clean [d]
Luego verá ese hg parents
informe [d]
. Esto significa que su próximo commit tendrá [d]
como padre. Por lo tanto, puede corregir un error que haya notado en la rama principal y crear un conjunto de cambios [e]
:
[x] --- [y]
/ /
[a B C D e]
Para empujar [e]
solo el conjunto de cambios , debe hacer
% hg push -r [e]
¿Dónde [e]
está el hash changeset? Por defecto hg push
, simplemente comparar los repositorios y ver que [x]
, [y]
y [e]
están desaparecidos, pero es posible que no quieren compartir [x]
y [y]
todavía.
Si la corrección de errores también le afecta, desea fusionarla con su rama de características:
% hg update [y]
% hg merge
Eso dejará su gráfico de repositorio con el siguiente aspecto:
[x] --- [y] ----------- [z]
/ /
[a B C D e]
donde [z]
es la fusión entre [y]
y [e]
. También podrías haber optado por tirar la rama:
% hg strip [x]
Mi punto principal de esta historia es esta: un solo clon puede representar fácilmente varias pistas de desarrollo. Esto siempre ha sido cierto para "hg simple" sin usar ninguna extensión. Sin embargo, la extensión de marcadores es de gran ayuda. Le permitirá asignar nombres (marcadores) a conjuntos de cambios. En el caso anterior, querrá un marcador en su cabeza de desarrollo y uno en la cabeza ascendente. Los marcadores se pueden empujar y extraer con Mercurial 1.6 y se han convertido en una característica incorporada en Mercurial 1.8.
Si hubiera optado por hacer dos clones, su clon de desarrollo se habría visto así después de hacer [x]
y [y]
:
[a] --- [b] --- [x] --- [y]
Y su clon aguas arriba contendrá:
[a] --- [b] --- [c] --- [d]
Ahora notas el error y lo arreglas. Aquí no tiene que hacerlo, hg update
ya que el clon ascendente está listo para usar. Usted se compromete y crea [e]
:
[a] --- [b] --- [c] --- [d] --- [e]
Para incluir la corrección de errores en su clon de desarrollo, tire de ella allí:
[a] --- [b] --- [x] --- [y]
\
[c] --- [d] --- [e]
y fusionar:
[a] --- [b] --- [x] --- [y] --- [z]
\ /
[c] --- [d] --- [e]
El gráfico puede verse diferente, pero tiene la misma estructura y el resultado final es el mismo. Usando los clones, tenías que hacer un poco menos de contabilidad mental.
Las ramas con nombre realmente no entraron en escena aquí porque son bastante opcionales. Mercurial se desarrolló utilizando dos clones durante años antes de cambiar a ramas con nombre. Mantenemos una rama llamada 'estable' además de la rama 'predeterminada' y hacemos nuestros lanzamientos basados en la rama 'estable'. Consulte la página de ramificación estándar en la wiki para obtener una descripción del flujo de trabajo recomendado.
Creo que quieres toda la historia en un repositorio. Engendrar un repositorio a corto plazo es para experimentos a corto plazo, no para eventos importantes como lanzamientos.
Una de las decepciones de Mercurial es que no parece haber una manera fácil de crear una rama de corta duración, jugar con ella, abandonarla y recoger la basura. Las ramas son para siempre. Simpatizo con nunca querer abandonar la historia, pero las ramas súper baratas y desechables son una
git
característica que realmente me gustaría verhg
.fuente
hg strip
es lo que quiero. ¿Por qué no se pueden eliminar las sucursales de reclamos de documentación en línea?hg ci --close-branch
.Deberías hacer las dos cosas .
Comience con la respuesta aceptada de @Norman: use un repositorio con una rama con nombre por versión.
Luego, tenga un clon por rama de lanzamiento para compilar y probar.
Una nota clave es que incluso si usa múltiples repositorios, debe evitar usar
transplant
para mover conjuntos de cambios entre ellos porque 1) cambia el hash y 2) puede introducir errores que son muy difíciles de detectar cuando hay cambios conflictivos entre el conjunto de cambios que trasplante y la rama objetivo. En su lugar, desea hacer la fusión habitual (y sin premezcla: siempre inspeccione visualmente la fusión), lo que dará como resultado lo que @mg dijo al final de su respuesta:De manera más detallada, si usa múltiples repositorios, el repositorio "troncal" (o predeterminado, principal, desarrollo, lo que sea) contiene TODOS los conjuntos de cambios en TODOS los repositorios. Cada repositorio de versión / rama es simplemente una rama en el tronco, todas fusionadas de una manera u otra de nuevo al tronco, hasta que desee dejar una versión anterior. Por lo tanto, la única diferencia real entre ese repositorio principal y el repositorio único en el esquema de rama con nombre es simplemente si las ramas se nombran o no.
Eso debería hacer obvio por qué dije "comenzar con un repositorio". Ese único repositorio es el único lugar que necesitarás buscar cualquier conjunto de cambios en cualquier lanzamiento . Puede etiquetar más conjuntos de cambios en las ramas de lanzamiento para el control de versiones. Es conceptualmente claro y simple, y simplifica la administración del sistema, ya que es lo único que tiene que estar disponible y recuperarse todo el tiempo.
Pero aún necesita mantener un clon por rama / lanzamiento que necesita construir y probar. Es lo más trivial posible
hg clone <main repo>#<branch> <branch repo>
, y luegohg pull
en el repositorio de rama solo se extraerán nuevos conjuntos de cambios en esa rama (más los conjuntos de cambios ancestrales en las ramas anteriores que se fusionaron).Esta configuración se adapta mejor al modelo de confirmación de kernel de Linux de un solo extractor (no se siente bien actuar como Lord Linus. En nuestra empresa llamamos al integrador de roles ), ya que el repositorio principal es lo único que los desarrolladores necesitan para clonar y el tirador necesita entrar. El mantenimiento de los repositorios de sucursales es puramente para la administración de versiones y puede ser completamente automatizado. Los desarrolladores nunca necesitan sacar / empujar a los repositorios de la rama.
Aquí está el ejemplo de @ mg presentado para esta configuración. Punto de partida:
Haga una rama con nombre para una versión de lanzamiento, diga "1.0", cuando llegue a la versión alfa. Comprometa correcciones de errores:
(1.0)
no es un conjunto de cambios real ya que la rama con nombre no existe hasta que se confirma. (Puede realizar una confirmación trivial, como agregar una etiqueta, para asegurarse de que las ramas con nombre se creen correctamente).La fusión
[m1]
es la clave de esta configuración. A diferencia de un repositorio de desarrolladores en el que puede haber un número ilimitado de cabezas, NO desea tener varias cabezas en su repositorio principal (excepto para la rama antigua de lanzamiento muerto como se mencionó anteriormente). Por lo tanto, siempre que tenga nuevos conjuntos de cambios en las ramas de lanzamiento, debe fusionarlos nuevamente con la rama predeterminada (o una rama de lanzamiento posterior) de inmediato. Esto garantiza que cualquier corrección de errores en una versión también se incluya en todas las versiones posteriores.Mientras tanto, el desarrollo en la rama predeterminada continúa hacia la próxima versión:
Y, como de costumbre, debe fusionar las dos cabezas en la rama predeterminada:
Y este es el clon de la rama 1.0:
Ahora es un ejercicio agregar la próxima rama de lanzamiento. Si es 2.0, definitivamente se ramificará por defecto. Si es 1.1, puede optar por bifurcar 1.0 o por defecto. En cualquier caso, cualquier nuevo conjunto de cambios en 1.0 debe fusionarse primero con la siguiente rama y luego, por defecto. Esto se puede hacer automáticamente si no hay conflicto, lo que resulta simplemente en una fusión vacía.
Espero que el ejemplo aclare mis puntos anteriores. En resumen, las ventajas de este enfoque son:
ACTUALIZACIÓN hg hace esto : el repositorio principal contiene las ramas predeterminadas y estables, y el repositorio estable es el clon de rama estable. Sin embargo, no usa una rama versionada, ya que las etiquetas de versión a lo largo de la rama estable son lo suficientemente buenas para sus propósitos de administración de versiones.
fuente
La mayor diferencia, hasta donde yo sé, es algo que ya has dicho: las ramificaciones nombradas están en un único repositorio. Las ramas con nombre tienen todo a mano en un solo lugar. Los repositorios separados son más pequeños y fáciles de mover. La razón por la que hay dos escuelas de pensamiento sobre esto es que no hay un ganador claro. Cualquiera de los argumentos del lado que tenga más sentido para usted es probablemente con el que debe ir, porque es probable que su entorno sea más similar al suyo.
fuente
Creo que es claramente una decisión pragmática dependiendo de la situación actual, por ejemplo, el tamaño de una función / rediseño. Creo que las bifurcaciones son realmente buenas para que los contribuyentes con roles aún no comprometidos se unan al equipo de desarrolladores al demostrar su aptitud con una sobrecarga técnica descuidada.
fuente
Realmente recomendaría no usar ramas con nombre para las versiones. Para eso son realmente las etiquetas. Las ramas con nombre están destinadas a diversiones duraderas, como un
stable
rama.Entonces, ¿por qué no solo usar etiquetas? Un ejemplo básico:
Eso creará una nueva cabeza sin nombre en la
default
rama, también conocido como. una rama anónima, que está perfectamente bien en hg. En cualquier momento, puede fusionar las confirmaciones de corrección de errores en la pista de desarrollo principal. No hay necesidad de ramas con nombre.fuente