2010-11-17 7 views
8

Utilizzo Mercurial da un po 'e c'è un "fatto" che viene dato molte volte.Mercurial unire awesomeness - cosa mi manca?

In effetti, mi ha colpito mentre guardavo un video fatto da Fogcreek ieri, this video: Fog Creek Kiln: Unlock the power of DVCS for your company che sembra esserci qualcosa che non funziona per me qui.

A circa 1:39 in questo video e in avanti si dice che mentre altri sistemi di controllo versione rilevano le revisioni (ad esempio le istantanee), i changeset di traccia Mercurial di DVCS (ad esempio quello che è successo tra le istantanee).

Questo dà loro un vantaggio nell'unione di scenari e quindi mostra un esempio. Se si sposta una funzione in un ramo e si cambia la stessa funzione in un altro ramo, Mercurial è in grado di unirlo.

E ho visto questo accennato altrove, anche se ora non riesco a trovare alcun collegamento diretto.

Questo non sembra funzionare per me.


Edit: Questo è un problema con il default "beyondcompare3" Configurazione strumento di unione per TortoiseHg. Ho aggiunto la configurazione di seguito al mio file Mercurial.ini e ora funziona come previsto. Certo, sarà Punt allo strumento GUI se non può automerge, ma ora l'unione descritta in questa domanda qui viene eseguito senza alcuna richiesta e appena fa la cosa giusta, fuori dalla scatola

[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 

per verificare ciò, ho commesso questo file in un repository:

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"); 
} 

Poi in due diversi gruppi di modifiche parallele si dirama da questo, ho fatto le seguenti due modifiche:

  1. ho spostato la funzione Function1 alla fine del file
  2. ho cambiato il messaggio all'interno Funzione1

Allora ho provato a fondere, e Mercurial mi dà una finestra di conflitto di unione, cercando di capire quello che ho fatto.

Fondamentalmente, tenta di modificare il testo in Function2, che ora si trova nella posizione in cui Function1 era prima che venisse spostato.

Questo non dovrebbe accadere!


Ecco i file di origine per la riproduzione il mio esempio:

di file batch per la produzione di repository:

@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" 

Le 3 versioni del file, example1.linq, example2.linq e Example3 .linq:

Esempio1.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"); 
} 

risposta

7

Bene, si sta attualmente colpendo uno della limitazione della, in fondo, QUALSIASI VCS corrente (DVCS o no, non importa).

Il fatto è che VCS al momento è indipendente dal linguaggio, la base del loro algoritmo di fusione è una differenza testuale. Significa che stanno cercando il cambiamento e il relativo contesto .
La parte importante qui è il contesto. Non è altro che alcune linee prima e dopo le modifiche apportate.

Ciò significa che sono davvero pessimi nel gestire la riorganizzazione del codice all'interno di uno stesso file, perché in pratica si sta rovinando tutto il contesto su cui possono fare affidamento.
In genere, nel tuo esempio, passando le due funzioni, non solo hai invertito completamente il contesto tra i due changeset, ma peggio, non avendo più righe dopo l'ultima funzione, hai ridotto implicitamente il contesto dell'ultimo cambiamento, diminuendo le possibilità che un algoritmo di fusione sia riuscito a capire cosa hai veramente fatto.

Attualmente conosco solo uno strumento diff, da msft, per XML, che sta cercando di gestire la semantica della modifica e non solo la sua rappresentazione testuale.
So anche che i ragazzi di PlasticSCM stanno cercando di implementare tale funzionalità per alcune lingue tradizionali, ma è davvero un posto dove c'è spazio per miglioramenti.

+1

In realtà, si tratta di un problema di configurazione. Sto usando Beyond Compare come il mio strumento diff/merge, e apparentemente, a meno che non configuri TortoiseHg/Mercurial per usare Beyond Compare * me *, non risolve i conflitti che può gestire. Dopo aver aggiunto la configurazione necessaria, tutto viene eseguito come previsto. Aggiornerò la mia domanda –

+0

Mi rendo conto del problema con la mancanza di contesto, ho una conoscenza approfondita di come funzionano gli algoritmi diff, avendo implementato un bel po 'di dati sia di testo che di binari, ma questo specifico scenario è stato detto funzionare di volta in volta con DVCS' quindi io mi stavo chiedendo perché non fosse così. –

+0

Beh, in effetti, l'esempio non riguarda un ragazzo che modifica una funzione, e un'altra che la sposta verso il basso, ma lo stesso ragazzo che fa le due operazioni (in due passaggi). Ciò significa che, in teoria, avresti dovuto essere in grado di lavorare su Fonction2 mentre qualcun altro avrebbe fatto le altre due operazioni, e quindi l'unione si sarebbe comportata bene. – gizmo