2010-11-17 12 views
8

He estado usando Mercurial por un tiempo, y hay un "hecho" que se da muchas veces.Increíble fusión de Mercurial: ¿qué me estoy perdiendo?

De hecho, me sorprendió al ver un video realizado por Fogcreek ayer, this video: Fog Creek Kiln: Unlock the power of DVCS for your company que parece que hay algo que no funciona para mí aquí.

Aproximadamente a la 1:39 en ese video y en adelante hace un punto de decir que mientras otros sistemas de control de versión rastrean revisiones (es decir, instantáneas), DVCS como los conjuntos de cambios de pista Mercurial (es decir, lo que sucedió entre las instantáneas).

Esto les da una ventaja en la fusión de escenarios, y luego muestra un ejemplo. Si mueve una función en una rama y cambia la misma función en otra rama, Mercurial puede fusionar eso.

Y he visto esto mencionado en otra parte, aunque ahora no encuentro enlaces directos.

Esto no parece funcionar para mí.


Editar: Este es un problema con el valor por defecto "beyondcompare3" configuración de la herramienta de mezcla para TortoiseHg. Agregué la configuración a continuación a mi archivo Mercurial.ini, y ahora funciona como se esperaba. Claro, que va batea a la herramienta de interfaz gráfica de usuario si no puede AutoMerge, pero ahora la fusión descrita en esta pregunta aquí se ejecuta sin ningún mensaje y simplemente hace lo correcto fuera de la caja

[ui] 
merge = bc3 

[merge-tools] 
bc3.executable = C:\Program Files (x86)\Beyond Compare 3\bcomp.exe 
bc3.args = $local $other $base $output /automerge /reviewconflicts /closescript 
bc3.priority = 1 
bc3.premerge = True 
bc3.gui = True 

para probar esto, he cometido este archivo a un repositorio:

void Main() 
{ 
    Function1(); 
    Function2(); 
} 

public void Function1() 
{ 
    Debug.WriteLine("Function 1"); 
    for (int index = 0; index < 10; index++) 
     Debug.WriteLine("f1: " + index); 
} 

public void Function2() 
{ 
    Debug.WriteLine("Function 1"); 
} 

Luego, en dos conjuntos de cambios paralelos diferentes ramificación hacia fuera de éste, hice los dos cambios siguientes:

  1. I trasladó la función Función1 a la parte inferior del archivo
  2. he cambiado el mensaje dentro Función1

Luego trató de fusionar y Mercurial me da una ventana de conflicto de combinación, tratando de averiguar lo que hizo.

Básicamente, intenta cambiar el texto en la Función 2, que ahora está en la posición que tenía la Función 1 antes de que se moviera.

¡Esto no se suponía que sucediera!


He aquí los archivos de origen para la reproducción de mi ejemplo:

de archivos por lotes para la producción de repositorio:

@echo off 

setlocal 

if exist repo rd /s /q repo 
hg init repo 
cd repo 

copy ..\example1.linq example.linq 
hg commit -m "initial commit" --addremove --user "Bob" --date "2010-01-01 18:00:00" 

copy ..\example2.linq example.linq 
hg commit -m "moved function" --user "Bob" --date "2010-01-01 19:00:00" 

hg update 0 
copy ..\example3.linq example.linq 
hg commit -m "moved function" --user "Alice" --date "2010-01-01 20:00:00" 

Las 3 versiones del archivo, example1.linq, example2.linq y example3 .linq:

Ejemplo1.LINQ:

<Query Kind="Program" /> 

void Main() 
{ 
    Function1(); 
    Function2(); 
} 

public void Function1() 
{ 
    Debug.WriteLine("Function 1"); 
    for (int index = 0; index < 10; index++) 
     Debug.WriteLine("f1: " + index); 
} 

public void Function2() 
{ 
    Debug.WriteLine("Function 1"); 
} 

Example2.linq:

<Query Kind="Program" /> 

void Main() 
{ 
    Function1(); 
    Function2(); 
} 

public void Function2() 
{ 
    Debug.WriteLine("Function 1"); 
} 

public void Function1() 
{ 
    Debug.WriteLine("Function 1"); 
    for (int index = 0; index < 10; index++) 
     Debug.WriteLine("f1: " + index); 
} 

Example3.linq:

<Query Kind="Program" /> 

void Main() 
{ 
    Function1(); 
    Function2(); 
} 

public void Function1() 
{ 
    Debug.WriteLine("Function 1b"); 
    for (int index = 0; index < 10; index++) 
     Debug.WriteLine("f1: " + index); 
} 

public void Function2() 
{ 
    Debug.WriteLine("Function 1"); 
} 

Respuesta

7

Bueno, actualmente está alcanzando a uno de la limitación de, básicamente, cualquier VCS actual (DVCS o no, no importa).

El hecho es que los VCS son actualmente independientes del idioma, la base de su algoritmo de combinación es una diferencia textual. Significa que están buscando qué cambio y cuál es el contexto relacionado .
La parte importante aquí es el contexto. No es nada más que algunas líneas antes y después de los cambios que ha realizado.

Esto significa que son realmente malos para tratar con la reorganización del código dentro de un mismo archivo, porque básicamente estás atornillando todo el contexto en el que pueden confiar.
Normalmente, en su ejemplo, al cambiar las dos funciones, no solo invirtió completamente el contexto entre los dos conjuntos de cambios, sino que al no tener líneas adicionales después de la última función, redujo implícitamente el contexto del último cambio, disminuyendo las posibilidades de que un algoritmo de fusión haya podido descifrar lo que realmente hizo.

Actualmente, solo conozco una herramienta diff, de msft, para XML, que está tratando de ocuparse del semántico de su cambio y no solo de su representación textual.
También sé que los chicos de PlasticSCM están tratando de implementar dicha función para algunos lenguajes convencionales, pero es realmente un lugar donde hay margen de mejora.

+1

En realidad, es un problema de configuración. Estoy usando Beyond Compare como mi herramienta diff/merge, y aparentemente, a menos que configure TortoiseHg/Mercurial para usar Beyond Compare * yo mismo *, no automatiza los conflictos que puede manejar. Después de que agregué la configuración necesaria, todo funciona como se esperaba. Actualizaré mi pregunta. –

+0

Me doy cuenta del problema con la falta de contexto, tengo un conocimiento profundo sobre cómo funcionan los algoritmos de diferencias, habiendo implementado bastantes datos de texto y binarios, pero se ha dicho que este escenario específico funciona una y otra vez con DVCS así que Solo me preguntaba por qué no lo hizo. –

+0

Bueno, de hecho, el ejemplo no se trata de que un chico modifique una función y otra que lo mueva hacia abajo, sino el mismo tipo que realiza las dos operaciones (en dos pasos). Lo que significa que, en teoría, debería haber sido capaz de trabajar en Fonction2 mientras que el otro haría las otras dos operaciones, y luego la fusión funcionaría bien. – gizmo

Cuestiones relacionadas