Confrontatore di testo (Diff)

Confronta due testi e trova le differenze all'istante.

I tuoi dati non lasciano il tuo dispositivo

Informazioni sul confronto di testi

Questo strumento di diff usa l'algoritmo della più lunga sottosequenza comune (LCS) per confrontare due testi riga per riga. Le aggiunte sono evidenziate in verde e le eliminazioni in rosso. Scegli la vista «In linea» per vedere tutte le modifiche su una singola colonna, o «Fianco a fianco» per confrontare i testi originale e modificato in parallelo.

Usi comuni

Domande frequenti

Confronta carattere per carattere?

Questo strumento confronta riga per riga. Se una riga ha la minima modifica (anche un singolo carattere), l'intera riga viene marcata come modificata. È lo stesso approccio usato da Git e dalla maggior parte degli strumenti di diff.

C'è un limite di dimensione?

Non c'è un limite rigido, ma testi molto grandi (più di 10.000 righe) possono richiedere un momento per essere elaborati, perché il confronto viene eseguito interamente nel tuo browser.

Cosa significa davvero «diff»

Un diff descrive come trasformare un testo in un altro usando il più piccolo insieme di inserimenti e cancellazioni. Ci sono infiniti modi per farlo, quello banale è «cancella ogni carattere di A e poi inserisci ogni carattere di B.» Un diff utile è lo script di modifica più corto, che è il duale del problema della più lunga sottosequenza comune: trovare la più lunga sequenza di righe che appare (nell'ordine) in entrambi i testi, e tutto il resto è un'aggiunta o una cancellazione. La maggior parte degli algoritmi di diff sono algoritmi LCS travestiti.

Un punto sottile: la più lunga sottosequenza comune non è la più lunga sottostringa comune. Una sottosequenza preserva l'ordine ma non l'adiacenza, quindi «ABCDE» e «AXBYCZD» condividono la sottosequenza «ABCD» anche se nessuna sequenza contigua di tre caratteri appare in entrambe.

Una breve storia degli algoritmi di diff

Il primo programma di confronto file ampiamente usato fu il diff di Unix scritto da Douglas McIlroy ai Bell Labs, con l'algoritmo sottostante pubblicato da James W. Hunt e McIlroy come Bell Labs Computing Science Technical Report #41 nel giugno 1976. McIlroy stesso descrisse i quattro mesi di sviluppo come «uno sforzo disperato.» L'approccio Hunt-McIlroy calcolava l'hash di ogni riga del file B, indicizzava dove compariva ogni riga unica, e cercava la più lunga catena di corrispondenze monotonicamente crescente. Fu distribuito in Version 6 Unix e rimase essenzialmente lo stesso algoritmo in /usr/bin/diff sulla maggior parte dei sistemi Unix per decenni.

Eugene W. Myers pubblicò lo standard industriale moderno nel 1986, «An O(ND) Difference Algorithm and Its Variations» in Algorithmica Vol. 1, No. 2. Myers riformulò LCS come un problema di cammino minimo attraverso un grafo di modifica: disponi A lungo l'asse superiore e B lungo il lato, traccia una diagonale ogni volta che due righe corrispondono, e cerca il cammino dall'angolo in alto a sinistra a quello in basso a destra con il minor numero di archi non diagonali. Ogni arco non diagonale è un inserimento o una cancellazione; ogni diagonale è gratuita. Fondamentale, l'algoritmo viene eseguito in tempo O((N+M)·D) dove D è la dimensione dello script di modifica, ovvero, diventa più veloce quanto più simili sono i file. Per i tipici diff del controllo di versione D è minuscolo rispetto a N+M, quindi Myers è enormemente più veloce del caso peggiore O(N·M) nella pratica. Il suo articolo include anche un perfezionamento a spazio lineare che usa un trucco divide-et-impera del «middle snake». L'algoritmo di Myers è quello predefinito alla base di GNU diff, git diff, Mercurial, Subversion, jsdiff, il difflib di Python, e la maggior parte dei visualizzatori di diff con interfaccia grafica.

Bram Cohen (poi più noto come l'inventore di BitTorrent) progettò il patience diff per il sistema di controllo di versione Bazaar intorno al 2002. Il problema motivante: il diff di Myers allinea qualsiasi riga corrispondente, comprese quelle molto comuni, quindi spostare una funzione in C può produrre un diff rumoroso in cui la parentesi graffa di chiusura della funzione spostata si allinea con la parentesi graffa di chiusura di una funzione non correlata. Il patience diff àncora il diff sulle righe che compaiono esattamente una volta in ciascun file (tipicamente firme di funzione, intestazioni di commento, messaggi di log distintivi), calcola l'LCS di solo quelle àncore usando il patience sort, e ricorre sugli spazi vuoti. Il risultato si allinea su righe significative e si legge meglio per il codice sorgente. Git lo supporta tramite git diff --patience. L'histogram diff è un perfezionamento aggiunto a git intorno al 2010 che costruisce un istogramma delle occorrenze delle righe e preferisce àncore a bassa frequenza anziché quelle strettamente uniche; da git 2.45 in poi è quello predefinito per molte configurazioni.

Levenshtein contro LCS

Un concetto correlato che vale la pena distinguere. La distanza di Levenshtein (Vladimir Levenshtein, 1965) conta il numero minimo di inserimenti, cancellazioni e sostituzioni di singoli caratteri per trasformare una stringa in un'altra. Il diff basato su LCS è strettamente correlato ma leggermente diverso: il diff classico tratta una «modifica» come una coppia cancella-poi-inserisci anziché una singola sostituzione, perché ciò si adatta meglio ai file orientati alle righe. Levenshtein risponde a «quanto sono diverse queste stringhe?» e ti dà un numero; LCS risponde a «cosa è cambiato di preciso?» e ti dà un effettivo script di modifica. I correttori ortografici e le funzioni «forse cercavi?» vogliono il primo; gli strumenti di diff vogliono il secondo. La variante Damerau-Levenshtein (1964) estende Levenshtein con un operatore di trasposizione per il rilevamento di errori di battitura.

Granularità: riga, parola e carattere

Il diff può essere calcolato a diverse granularità, ciascuna con i suoi compromessi:

Uno schema comune nelle moderne interfacce di diff è calcolare prima il diff a livello di riga, poi per ogni coppia di «vicini rimossi/aggiunti» eseguire un diff secondario a livello di parola su solo quelle due righe ed evidenziare le modifiche all'interno della riga. È esattamente così che funzionano sia la vista PR di GitHub sia la libreria diff-match-patch.

Tre modalità di visualizzazione del diff che vedrai

Varianti utili di git diff

Quando ricorreresti a un diff nel browser

Limitazioni oneste

Altre domande

Perché questa pagina non mostra evidenziazioni a livello di carattere all'interno delle righe modificate?

Perché il passaggio a livello di riga è sufficiente per la maggior parte dei casi d'uso e viene eseguito molto più velocemente su input lunghi. Per l'evidenziazione parola per parola all'interno della riga, il perfezionamento in due passaggi è prassi standard ma aggiunge latenza. Se l'intera differenza di riga è importante per te (revisione legale, correzione di bozze di prosa), uno strumento dedicato a livello di parola (incluso git diff --word-diff da riga di comando) è più adatto.

Qual è la differenza tra unified diff e affiancato?

Unified diff è il formato compatto e leggibile dalla macchina che ogni file .patch usa, tre righe di contesto, blocchi contrassegnati con @@. L'affiancato mostra le due versioni in colonne parallele, il che è più riposante per l'occhio nella revisione visiva ma occupa più spazio orizzontale. Unified è ciò che invieresti via e-mail o committeresti; l'affiancato è ciò che leggeresti su un monitor largo.

Esistono algoritmi migliori di Myers per il codice sorgente?

Per il codice sorgente con funzioni spostate o grandi riarrangiamenti, sì, il patience diff (Bram Cohen, 2002) e l'histogram diff (git, intorno al 2010) sono progettati per allinearsi su righe uniche significative anziché su quelle comuni, producendo un output più leggibile. Entrambi sono disponibili tramite git diff --patience e git diff --histogram. Gli strumenti consapevoli dell'AST come difftastic vanno oltre e analizzano l'effettiva struttura del linguaggio.

È sicuro incollare testo riservato qui?

Sì, il diff viene eseguito interamente nel tuo browser usando un'implementazione LCS in JavaScript. Nulla viene caricato, nessuna analisi sull'input, nessun log lato server del testo. Questa è l'unica categoria di strumento di diff sicura per gli NDA, il codice sorgente interno o le clausole contrattuali non rilasciate; i servizi di diff basati su cloud vedono qualunque cosa incolli.

Strumenti correlati