¿Cómo fusionar automáticamente.hgtags en Mercurial?
merge dvcs (5)
Deberías probar la diffmerge , ¡es increíble!
Tengo un script que ejecuta algunos comandos de Mercurial en modo no interactivo en un servidor de compilación. Uno de los comandos combina dos ramas y siempre hay un conflicto en el archivo .hgtags durante la fusión debido a la forma en que se configuran los scripts de construcción.
¿Cómo puedo obligar a Mercurial a fusionar siempre el archivo .hgtags utilizando los cambios de ambos archivos, primero de uno y luego del otro?
Por ejemplo, si los archivos a fusionar fueran
A
B
C
y
A
B
D
Me gustaría que el resultado fuera
A
B
C
D
Supongo que necesitaré una herramienta de combinación personalizada. ¿Qué herramienta proporciona esta funcionalidad?
En realidad, no es necesario fusionar el archivo .hgtags. Puede ser diferente en diferentes ramas y Mercurial listará correctamente todas las etiquetas en todas las ramas.
Usamos la opción de configuración de merge-patterns para decirle a Mercurial que use la rama local cuando haga combinaciones de .hgtags. Agregue lo siguiente al archivo hgrc de su repositorio:
[merge-patterns]
.hgtags = internal:local
Cuando se realiza una combinación que involucra el archivo .hgtags, .hgtags se mostrará como modificado, pero no se cambiará.
Mercurial 3.1 (2014-08-01) introdujo interno: tagmerge . Está marcado como experimental, así que ten cuidado. Aquí está el preámbulo del changeset de changeset (puede encontrar más detalles sobre el algoritmo si sigue el enlace):
Agregue una nueva herramienta de combinación interna: tagmerge que implementa un algoritmo de fusión automática para los archivos de etiquetas de mercurial
El algoritmo de etiquetado es capaz de resolver la mayoría de los conflictos de combinación que actualmente desencadenan un conflicto de combinación .hgtags. El único caso que no (y no puede) manejar es que dos etiquetas apuntan a diferentes revisiones en cada padre de combinación y sus historiales de etiquetas correspondientes tienen el mismo rango (es decir, la misma longitud). En todos los demás casos, el algoritmo de fusión elegirá la revisión que pertenece al padre con el historial de etiquetas mejor calificado. El historial de etiquetas fusionadas es la combinación de ambos historiales de etiquetas (se tiene especial cuidado para tratar de combinar los historiales de etiquetas comunes cuando sea posible).
El algoritmo también maneja casos en los que las etiquetas se han eliminado manualmente del archivo .hgtags y otros casos de esquina similares.
Además de fusionar realmente las etiquetas de dos padres, teniendo en cuenta la base, el algoritmo también intenta minimizar la diferencia entre el archivo de etiquetas fusionadas y el archivo de etiquetas del primer padre (es decir, trata de hacer que el orden de las etiquetas fusionadas sea tan similar como posible para el primer archivo de etiqueta de los padres).
tagmerge solo funciona con archivos de etiquetas, por lo que para usarlo deberías establecer patrones de combinación . Para hacer esto en base a cada comando use la opción --config :
hg merge -r REV --config merge-patterns..hgtags=internal:tagmerge
O para hacer esto en base a cada repositorio, agregue a su configuración de repos .hg/hgrc esto:
[merge-patterns]
.hgtags=internal:tagmerge
Consulte la respuesta a continuación por Magras de La Mancha para una mejor solución con Mercurial 3.1. La siguiente es una solución más simple e ingenua para versiones anteriores de Mercurial.
Sí, debe configurar una herramienta de combinación personalizada para su archivo .hgtags . Mercurial no proporciona ninguna herramienta de combinación especial para .hgtags , se espera que la .hgtags manualmente utilizando su herramienta de combinación de tres vías normal.
Los conflictos en el archivo .hgtags pueden tener dos tipos:
Conflictos tontos: esta es la situación que tiene y realmente no hay conflicto aquí. Lo que pasa es que una rama tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 12e0fdbc57a0be78f0e817fd1d170a3615cd35da Cy la otra rama tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 979c049974485125e1f9357f6bbe9c1b548a64c3 DCada etiqueta se refiere exactamente a un conjunto de cambios, por lo que no hay conflicto aquí. La fusión debe ser, por supuesto, la unión de los dos archivos:
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 12e0fdbc57a0be78f0e817fd1d170a3615cd35da C 979c049974485125e1f9357f6bbe9c1b548a64c3 DConflictos reales: hay una rama que tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 12e0fdbc57a0be78f0e817fd1d170a3615cd35da Cy la otra rama tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 979c049974485125e1f9357f6bbe9c1b548a64c3 CAquí hay un conflicto real: la
hg tag Cse realizó en ambas ramas, pero las etiquetas se refieren a diferentes conjuntos de cambios. Resolver esto es una tarea manual.
Si puede garantizar que solo tendrá conflictos tontos y que solo tiene una etiqueta por conjunto de cambios, entonces puede usar
hg log -r "tagged()" --template "{node} {tags}/n" > .hgtags
para generar un nuevo archivo .hgtags . La idea clave es que Mercurial sabe cómo combinar etiquetas internamente. Hace esto todo el tiempo cuando tienes dos cabezas con diferentes archivos .hgtags . La plantilla anterior simplemente genera un nuevo archivo .hgtags basado en esta combinación interna.
Si puede tener más de una etiqueta por conjunto de cambios, entonces lo anterior no funcionará: todas las etiquetas se imprimen en una línea, por lo que obtiene una etiqueta foo bar lugar de dos etiquetas foo y bar . A continuación, puede utilizar este archivo de estilo en su lugar:
changeset = "{tags}"
tag = "{node} {tag}/n"
Da salida a una línea por etiqueta , no a un conjunto de cambios. Guarda este estilo en algún lugar y configura una herramienta de combinación:
[merge-tools]
hgtags.executable = hg
hgtags.args = log -r "tagged()" --style ~/tmp/tags-style > $output
hgtags.premerge = False
hgtags.priority = -1000
[merge-patterns]
.hgtags = hgtags
Ahora tiene combinaciones de etiquetas automáticas. Hay algunas advertencias:
Tres o más cabezas: la técnica solo funciona si tiene dos cabezas en el momento de la fusión. Si tiene tres cabezas o más, es posible que una etiqueta eliminada vuelva a aparecer. Si tiene los encabezados X, Y y Z, y la etiqueta
Ase elimina en X, entonces Mercurial normalmente puede darse cuenta de queAse elimina en general. Esto se basa en una línea000...0 Aen el archivo.hgtagsen X. Sin embargo, si.hgtagsX e Y para obtener W, entonces el enfoque sugerido no contendrá ninguna línea000...0 ALa definición deAde Z ahora tendrá efecto repentinamente y reintroduciráAConflictos reales: si tiene conflictos reales en
.hgtags, entonces el método anterior elegirá silenciosamente la etiqueta de la cabecera más reciente para usted. La herramienta de combinación básicamente guarda lashg tagsen.hgtags, y el comportamiento de lashg tagscon varias cabezas se explica en la wiki . Dado quehg tagsincondicionalmente lee y combina silenciosamente el archivo.hgtagsde todas las cabezas, no hay nada que podamos hacer al respecto con este enfoque simple. Tratar con esto requeriría un script más grande que lea los dos archivos.hgtagsy detecte el conflicto.
No puede resolver automáticamente los conflictos de combinación realizando una fusión desatendida. Sin la combinación (es decir, seleccionar "solo mi" o "solo otro") funcionará.
Me temo que tiene un flujo de trabajo mal planificado: el servidor de compilación no debe realizar ninguna acción que modifique las fuentes. Es tarea para la elección humana y humana.
Pero supongo que los datos exactos dentro de .hgtags tienen que ser valiosos para el servidor de compilación (usa su propio clon, no está poblado por nadie, ¡espero!), Por lo tanto, puede definir cualquier política de combinación en el comando y tener (mala, con datos). -loss) .hgtags fusionados
Por cierto, "primero de uno, luego de otro" en cualquier idioma, usando solo lógica formal, para pares
A
B
C
y
A
B
D
significa ABCABD resultado