El Mergiraf 0.4 proyecto lanzamiento ha sido publicadopresentando un controlador para Git para implementar la fusión de tres vías. Mergiraf admite la resolución de varios tipos de conflictos de fusión y se puede utilizar con diferentes lenguajes de programación y formatos de archivo. Se puede invocar de forma independiente para manejar conflictos que surgen con Git estándar o reemplazar el controlador de combinación predeterminado de Git para mejorar comandos como merge
, revert
, rebase
y cherry-pick
. El código se distribuye bajo el licencia GPLv3. La nueva versión agrega soporte para Python, TOML, Scala y TypeScript, así como optimizaciones de rendimiento.
Problemas resueltos por Mergiraf
El desarrollo de software program ejemplifica un sistema increíblemente complejo. Los sistemas complejos comparten una característica: son intrínsecamente difíciles de gestionar y su comportamiento deseado no surge por casualidad. Más bien, estos sistemas evolucionan con el tiempo, paso a paso, y cada cambio se prueba cuidadosamente. Lograr esto requiere una estructura bien definida y herramientas adecuadas.
La evolución de cualquier sistema complejo se puede visualizar como un árbol dirigido, donde la raíz representa un conjunto vacío de características y cada nodo (excepto la raíz) representa el resultado de aplicar una mutación a su padre.
En el contexto de los productos de software program, cada nodo se denomina versiónque representa un conjunto specific de características y anticaracterísticas. Cualquier cambio en este conjunto se considera un mutaciónformando un borde en el gráfico acíclico dirigido. Estas características son inherentemente abstractas; no reflejan los sistemas físicos sino la utilidad que los agentes inteligentes perciben en estos sistemas. Para convertir estas concepts en realidad, los desarrolladores deben trabajar con detalles de bajo nivel expresados en lenguajes de programación.
Instantáneas y conjuntos de cambios
Para refinar gradualmente el código fuente hasta un estado que muestre el comportamiento deseado y documentar cómo se logra esto, los programadores utilizan instantáneas y conjuntos de cambios.
- A instantánea Representa un estado específico del producto, capturando todos los detalles de bajo nivel.
- A conjunto de cambios Representa la transición entre instantáneas.
Normalmente, las instantáneas se derivan de conjuntos de cambios únicos, por lo que estos términos suelen usarse indistintamente. Sin embargo, existen excepciones, como fusionar confirmacionesque resultan de múltiples transiciones. Estos son notoriamente difíciles de manejar y generalmente se evitan.
Los sistemas de management de versiones modernos, como Git, brindan capacidades básicas para administrar los flujos de trabajo de desarrollo. Los desarrolladores pueden organizar instantáneas como gráficos acíclicos dirigidos, anotarlas con comentarios y reorganizar su orden según sea necesario. Esta funcionalidad ayuda a los desarrolladores a escribir historiales de proyectos semánticamente significativos, que son fundamentales para depurar y responder preguntas como:
- “¿Por qué se introdujo este detalle de bajo nivel (por ejemplo, una variable)?
- “¿Cuál es mi contribución a este proyecto?”
- “¿Quién implementó esta función y cuándo?”
- “¿Qué cambio causó este error, aunque no debería haber ocurrido?”
Ramificación y colaboración
Los sistemas de management de versiones también admiten sucursalesque representan piezas continuas de la historia del proyecto. Los desarrolladores utilizan ramas para:
- Implementar características específicas.
- Pruebe múltiples implementaciones candidatas.
- Mix resultados de varios contribuyentes sin fusionar todo manualmente cada vez.
Un flujo de trabajo típico implica una rama principal que representa el producto oficial, con ramas laterales para cada característica. Los desarrolladores sincronizan las ramas laterales con la rama principal regularmente (idealmente después de cada confirmación) para:
- Trabaje con la última versión del producto.
- Detecte tempranamente los problemas causados por otros desarrolladores.
Desafíos de la fusión
Combinar cambios de diferentes instantáneas (un proceso que implica encontrar un ancestro común y aplicar cambios secuencialmente) puede generar conflictos. Las herramientas VCS modernas se basan en algoritmos de fusión línea por líneaque tratan los archivos como secuencias de líneas y aplican algoritmos de estilo bioinformático para fusionarlos. Si bien es easy y common, este enfoque tiene limitaciones importantes:
- Independiente del contenido: Los algoritmos línea por línea ignoran la semántica del código fuente.
- Inconsistencias: A menudo producen fusiones incorrectas, lo que requiere que los desarrolladores resuelvan los conflictos manualmente.
- Escaso apoyo a los grandes cambios: Los cambios grandes o triviales (por ejemplo, reformatear el código) pueden romper estos algoritmos.
Los desarrolladores deben estudiar cuidadosamente ambas versiones del código, resolver inconsistencias y, a veces, incluso volver a examinar todo el proyecto. Estos problemas se exacerban cuando el algoritmo no logra detectar conflictos o produce código que no funciona; por ejemplo, cuando un desarrollador cambia el nombre de una variable mientras otro la usa en un código nuevo.
Un mejor enfoque
La solución supreme implica utilizar un modelo semántico del código en lugar de una heurística línea por línea. Si bien la investigación en esta área ha estado en curso durante décadas, las implementaciones prácticas de código abierto recién comenzaron a surgir a principios de la década de 2010, centrándose principalmente en Java.
- Árbol de goma: Una herramienta basada en Java que genera representaciones abstractas de cambios en el código fuente pero que no admite la combinación de cambios de forma inmediata.
- Difícil: Una herramienta basada en Rust para visualizar diferencias en la consola, pero carece de funcionalidad para fusionar o aplicar parches.
Aquí es donde interviene Mergiraf.
Lo que Mergiraf aporta a la mesa
Mergiraf es una herramienta basada en Rust que aprovecha la cuidador de árboles analizador para análisis gramatical libre de contexto. A diferencia de sus predecesores, Mergiraf se centra en resolución automática de conflictos de fusión en lugar de simplemente visualizar diferencias.
Características clave
-
Resolución automática de conflictos de fusión:
- Utiliza el algoritmo de GumTree para la generación de parches.
- Adapta el algoritmo de Spork para aplicar cambios.
-
Soporte para múltiples idiomas:
- Python, TOML, Scala, TypeScript y más.
- Compacto y eficiente:
-
Visualización de conflictos:
- Ayuda a los desarrolladores a comprender y resolver problemas no resueltos.
Limitaciones
-
Serialización de parches:
- Mergiraf aún no admite la serialización de parches para su aplicación posterior, aunque esto podría implementarse a través de los registros de eventos de GumTree.
-
Conciencia de estilo world:
- Carece de soporte para estilos globales (p. ej.,
.editorconfig
), lo que lo hace menos efectivo para manejar grandes cambios de formato.
- Carece de soporte para estilos globales (p. ej.,
Ejemplo
Dados los siguientes archivos:
Archivo base (base.py
)
tab_indentation = True
foo = 1
def principal():
print(foo + 2 + 3)
Archivo modificado A (a.py
)
from icecream import ic
foo = 1
def principal():
ic(foo + 2 + 3)
class Baz:
def __init__(self):
"""Baz class"""
Archivo modificado B (b.py
)
bar = 1
def principal():
print(bar + 2 + 3)
Ejecución
./mergiraf merge ./base.py ./a.py ./b.py -x a.py -y b.py -s base.py -o ./res.py
Resultado
from icecream import ic
bar = 1
def principal():
ic(bar + 2 + 3)
class Baz:
def __init__(self):
"""Baz class"""
Este resultado resuelve los conflictos de fusión, manteniendo los cambios de ambas ramas y preservando al mismo tiempo la semántica del código. Sin embargo, la combinación de pestañas y espacios en la sangría revela un área de mejora: Mergiraf debería integrarse mejor con .editorconfig
o herramientas similares para imponer estilos globales.
Conclusión
Mergiraf representa un importante paso adelante en la fusión de herramientas para Git. Al aprovechar los árboles de sintaxis abstracta (AST), proporciona a los desarrolladores una forma más confiable de resolver conflictos, admitiendo una amplia gama de lenguajes y flujos de trabajo. Si bien existen áreas de mejora, las innovaciones de Mergiraf lo convierten en una opción convincente para los flujos de trabajo de desarrollo de software program modernos.
En caso de que haya encontrado un error en el texto, envíe un mensaje al autor seleccionando el error y presionando Ctrl-Enter.