Unisci (controllo versione) - Merge (version control)

Image
Esempio di grafico cronologico di un progetto controllato dalla versione, con unioni come frecce rosse

Nel controllo della versione , l' unione (detta anche integrazione) è un'operazione fondamentale che riconcilia più modifiche apportate a una raccolta di file controllata dalla versione. Molto spesso, è necessario quando un file viene modificato su due rami indipendenti e successivamente unito. Il risultato è una singola raccolta di file che contiene entrambi i set di modifiche.

In alcuni casi, l'unione può essere eseguita automaticamente, poiché sono disponibili informazioni cronologiche sufficienti per ricostruire le modifiche e le modifiche non sono in conflitto . In altri casi, una persona deve decidere esattamente cosa dovrebbero contenere i file risultanti. Molti strumenti software per il controllo delle revisioni includono funzionalità di unione.

Tipi di fusioni

Esistono due tipi di unione: automatica e manuale.

Unione automatica

La fusione automatica è ciò che fa il software di controllo della versione quando riconcilia le modifiche che sono avvenute simultaneamente (in senso logico). Inoltre, altri software implementano la fusione automatica se consentono di modificare lo stesso contenuto contemporaneamente. Ad esempio, Wikipedia consente a due persone di modificare lo stesso articolo contemporaneamente; quando l'ultimo collaboratore salva, le sue modifiche vengono unite nell'articolo invece di sovrascrivere la serie di modifiche precedente.

Unione manuale

La fusione manuale è ciò a cui le persone devono ricorrere (eventualmente assistite da strumenti di fusione) quando devono riconciliare file che differiscono. Per esempio, se due sistemi hanno versioni leggermente differenti di un file di configurazione e un utente vuole avere le cose buone in entrambi, questo di solito può essere ottenuto unendo i file di configurazione a mano, selezionando le modifiche desiderate da entrambe le fonti (questo è anche chiamata fusione a due vie). L'unione manuale è necessaria anche quando l'unione automatica si verifica in un conflitto di modifiche; ad esempio, pochissimi strumenti di unione automatica possono unire due modifiche alla stessa riga di codice (ad esempio, una che cambia il nome di una funzione e un'altra che aggiunge un commento). In questi casi, i sistemi di controllo di revisione ricorrono all'utente per specificare il risultato di fusione previsto.

Unisci algoritmi

Esistono molti approcci diversi alla fusione automatica, con sottili differenze. Gli algoritmi di unione più importanti includono l'unione a tre vie, l'unione a tre vie ricorsiva, l'applicazione di patch fuzzy, l'unione di trame e la commutazione di patch.

Unione a tre vie

Schema di una fusione a tre vie
C è l'origine, A e B sono le derivate di C e D è la nuova versione di output

Un'unione a tre vie viene eseguita dopo un'analisi automatica delle differenze tra un file "A" e un file "B", considerando anche l'origine, o l'antenato comune, di entrambi i file "C". È un metodo di fusione approssimativo, ma ampiamente applicabile poiché richiede solo un antenato comune per ricostruire i cambiamenti che devono essere uniti.

L'unione a tre vie cerca le sezioni che sono le stesse solo in due dei tre file. In questo caso, ci sono due versioni della sezione, e la versione che si trova nell'antenato comune "C" viene scartata, mentre la versione che differisce viene conservata nell'output. Se "A" e "B" sono d'accordo, questo è ciò che appare nell'output. Una sezione uguale in "A" e "C" emette la versione modificata in "B", e allo stesso modo una sezione uguale in "B" e "C" emette la versione in "A".

Le sezioni che sono diverse in tutti e tre i file sono contrassegnate come una situazione di conflitto e lasciate all'utente per la risoluzione.

La fusione a tre vie è implementata dall'onnipresente programma diff3 ed è stata l'innovazione centrale che ha permesso il passaggio dai sistemi di controllo delle revisioni basati sul blocco dei file ai sistemi di controllo delle revisioni basati sull'unione . È ampiamente utilizzato dal Concurrent Versions System (CVS).

Unione ricorsiva a tre vie

Gli strumenti di controllo delle revisioni basati sull'unione a tre vie sono molto diffusi, ma la tecnica dipende fondamentalmente dalla ricerca di un antenato comune delle versioni da unire.

Ci sono casi imbarazzanti, in particolare la "unione incrociata", in cui non esiste un unico ultimo antenato comune delle versioni modificate.

Image
Il problema "Criss-cross-merge" nel controllo della versione del software. Nella metà sinistra si stanno modificando 2 aree, e . e sono versioni successivamente modificate. La soluzione è mostrata nella metà destra: viene creato un antenato virtuale (il cerchio tratteggiato).

Fortunatamente, in questo caso si può dimostrare che ci sono al massimo due possibili antenati candidati, e l'unione ricorsiva a tre vie costruisce un antenato virtuale fondendo prima gli antenati non univoci. Questa unione può soffrire dello stesso problema, quindi l'algoritmo le unisce in modo ricorsivo . Poiché esiste un numero finito di versioni nella cronologia, è garantito che il processo terminerà alla fine. Questa tecnica viene utilizzata dallo strumento di controllo delle revisioni di Git .

(L'implementazione di unione ricorsiva di Git gestisce anche altri casi imbarazzanti, come un file che viene modificato in una versione e rinominato nell'altra, ma quelle sono estensioni della sua implementazione di unione a tre vie; non fa parte della tecnica per trovare tre versioni da unire.)

L'unione ricorsiva a tre vie può essere utilizzata solo in situazioni in cui lo strumento ha conoscenza del grafo aciclico diretto di ascendenza totale (DAG) dei derivati ​​da unire. Di conseguenza, non può essere utilizzato in situazioni in cui i derivati ​​o le fusioni non specifichino completamente la/le loro controllante/i.

Applicazione patch sfocata

Una patch è un file che contiene una descrizione delle modifiche a un file. Nel mondo Unix, c'è stata una tradizione nel diffondere le modifiche ai file di testo come patch nel formato prodotto da " diff -u". Questo formato può quindi essere utilizzato dal programma di patch per riapplicare (o rimuovere) le modifiche in (o da) un file di testo o una struttura di directory contenente file di testo.

Tuttavia, il programma di patch dispone anche di alcune funzionalità per applicare la patch in un file che non è esattamente simile al file di origine utilizzato per produrre la patch. Questo processo è chiamato applicazione di patch fuzzy e si traduce in una sorta di fusione asimmetrica a tre vie, in cui le modifiche nella patch vengono scartate se il programma di patch non riesce a trovare un punto in cui applicarle.

Come CVS è iniziato come un insieme di script su diff3 , GNU arch è iniziato come un insieme di script su patch. Tuttavia, l'applicazione di patch fuzzy è un metodo relativamente inaffidabile, a volte applica erroneamente patch che hanno troppo poco contesto (specialmente quelle che creano un nuovo file), a volte rifiuta di applicare le eliminazioni eseguite da entrambi i derivati.

Commutazione patch

La commutazione delle patch viene utilizzata in Darcs per unire le modifiche ed è implementata anche in git (ma chiamata "rebasing"). L'unione di commutazione di patch significa cambiare l'ordine delle patch (cioè le descrizioni delle modifiche) in modo che formino una storia lineare. In effetti, quando due patch vengono realizzate nel contesto di una situazione comune, al momento della fusione, una di esse viene riscritta in modo che appaia eseguita nel contesto dell'altra.

La commutazione delle patch richiede che le modifiche esatte che hanno apportato file derivati ​​siano archiviate o possano essere ricostruite. Da questi esatti cambiamenti è possibile calcolare come uno di essi dovrebbe essere modificato per rifondarlo sull'altro. Ad esempio, se la patch A aggiunge la riga "X" dopo la riga 7 del file F e la patch B aggiunge la riga "Y" dopo la riga 310 del file F, B deve essere riscritto se viene ribasato su A: la riga deve essere aggiunta su riga 311 del file F, perché la riga aggiunta in A sposta i numeri di riga di uno.

La commutazione delle patch è stata studiata molto formalmente, ma gli algoritmi per affrontare i conflitti di unione nella commutazione delle patch rimangono ancora questioni di ricerca aperte. Tuttavia, è possibile dimostrare che la commutazione delle patch produce risultati di unione "corretti" in cui altre strategie di unione sono principalmente euristiche che cercano di produrre ciò che gli utenti vogliono vedere.

Il programma Unix flipdiff del pacchetto "patchutils" implementa la commutazione delle patch per le patch tradizionali prodotte da diff -u.

Intreccio unione

Weave merge è un algoritmo che non fa uso di un antenato comune per due file. Invece, tiene traccia di come le singole righe vengono aggiunte ed eliminate nelle versioni derivate dei file e produce il file unito su queste informazioni.

Per ogni riga nei file derivati, weave merge raccoglie le seguenti informazioni: quali righe la precedono, quali la seguono e se è stata cancellata in qualche fase della storia di entrambe le derivate. Se in uno dei due derivati ​​è stata eliminata la riga a un certo punto, non deve essere presente nella versione unita. Per le altre righe, devono essere presenti nella versione unita.

Le righe sono ordinate in un ordine in cui ogni riga è dopo tutte le righe che l'hanno preceduta in un determinato momento della storia e prima di tutte le righe che l'hanno seguita in un determinato momento della storia. Se questi vincoli non forniscono un ordinamento totale per tutte le righe, le righe che non hanno un ordinamento l'una rispetto all'altra sono aggiunte in conflitto.

L'unione trame è stata apparentemente utilizzata dallo strumento commerciale di controllo delle revisioni BitKeeper e può gestire alcuni dei casi problematici in cui un'unione a tre vie produce risultati errati o errati. È anche una delle opzioni di unione dello strumento di controllo delle revisioni di GNU Bazaar ed è utilizzato in Codeville .

Guarda anche

Riferimenti