¿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 C
y la otra rama tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 979c049974485125e1f9357f6bbe9c1b548a64c3 D
Cada 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 D
Conflictos reales: hay una rama que tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 12e0fdbc57a0be78f0e817fd1d170a3615cd35da C
y la otra rama tiene
f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B 979c049974485125e1f9357f6bbe9c1b548a64c3 C
Aquí hay un conflicto real: la
hg tag C
se 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
A
se elimina en X, entonces Mercurial normalmente puede darse cuenta de queA
se elimina en general. Esto se basa en una línea000...0 A
en el archivo.hgtags
en X. Sin embargo, si.hgtags
X e Y para obtener W, entonces el enfoque sugerido no contendrá ninguna línea000...0 A
La definición deA
de Z ahora tendrá efecto repentinamente y reintroduciráA
Conflictos 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 tags
en.hgtags
, y el comportamiento de lashg tags
con varias cabezas se explica en la wiki . Dado quehg tags
incondicionalmente lee y combina silenciosamente el archivo.hgtags
de 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.hgtags
y 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