Confronta due file

Illimitato file. Confronti in tempo reale. Gratuitamente, per sempre.
Originale
Modificato

Privato e sicuro

Tutto accade nel tuo browser. I tuoi file non toccano mai i nostri server.

Velocissimo

Nessun caricamento, nessuna attesa. Converti nel momento in cui rilasci un file.

Realmente gratuito

Nessun account richiesto. Nessun costo nascosto. Nessun trucco sulle dimensioni dei file.

I "Diff" sono la lingua franca del cambiamento. Sono le narrazioni compatte che ti dicono cosa si è spostato tra due versioni di una cosa — codice sorgente, prosa, un set di dati — senza costringerti a rileggere tutto. Dietro quei pochi simboli (+, -, @@) si nasconde una profonda pila di algoritmi, euristiche e formati che bilanciano ottimalità, velocità e comprensione umana. Questo articolo è un tour pratico, dagli algoritmi ai flussi di lavoro, dei diff: come vengono calcolati, come vengono formattati, come li usano gli strumenti di unione e come regolarli per revisioni migliori. Lungo il percorso, fonderemo le affermazioni su fonti primarie e documenti ufficiali — perché i piccoli dettagli (come se gli spazi bianchi contano) contano davvero.

Cos'è in realtà un "diff"

Formalmente, un diff descrive uno script di modifica più breve (SES) per trasformare una sequenza "vecchia" in una "nuova" usando inserimenti e cancellazioni (e talvolta sostituzioni, che possono essere modellate come cancella+inserisci). In pratica, la maggior parte dei diff rivolti ai programmatori sonoorientati alla riga e poi opzionalmente raffinati in parole o caratteri per la leggibilità. Gli output canonici sono i formati contesto e unificato ; quest'ultimo — quello che di solito vedi nella revisione del codice — comprime l'output con un'intestazione concisa e "hunk", ognuno dei quali mostra un intorno di contesto attorno alle modifiche. Il formato unificato è selezionato tramite -u/--unified ed è lo standard de facto per l'applicazione di patch; patch generalmente beneficia delle linee di contesto per applicare le modifiche in modo robusto.

Il manuale di GNU diff elenca gli interruttori a cui ti rivolgi quando vuoi meno rumore e più segnale — ignorando gli spazi, espandendo le tabulazioni per l'allineamento, o chiedendo uno script di modifica "minimo" anche se è più lento (riferimento opzioni). Queste opzioni non cambiano cosa significa che due file differiscano; cambiano quanto aggressivamente l'algoritmo cerca script più piccoli e come il risultato vienepresentato agli esseri umani.

Da LCS a Myers: come vengono calcolati i diff

La maggior parte dei diff di testo si basa sull'astrazione della Sottosequenza Comune Più Lunga (LCS) . La programmazione dinamica classica risolve LCS in tempo e spazio O(mn), ma è troppo lenta e avida di memoria per file di grandi dimensioni. L'algoritmo di Hirschberg ha mostrato come calcolare allineamenti ottimali in spazio lineare (ancora tempo O(mn)) usando divide et impera, una tecnica fondamentale per risparmiare spazio che ha influenzato le implementazioni pratiche di diff.

Per velocità e qualità, la svolta è stata l'algoritmo di Eugene W. Myers del 1986, che trova un SES in tempo O(ND) (N ≈ linee totali, D ≈ distanza di modifica) e spazio quasi lineare. Myers modella le modifiche in un "grafo di modifica" e avanza lungo le frontiere più estese, producendo risultati che sono sia veloci che vicini al minimo nell'impostazione del diff di riga. Ecco perché "Myers" rimane il predefinito in molti strumenti.

C'è anche la famiglia Hunt–Szymanski , che accelera LCS quando poche posizioni corrispondono (pre-indicizzando le corrispondenze e inseguendo sottosequenze crescenti), ed è storicamente legata alle prime varianti di diff. Questi algoritmi illuminano i compromessi: in input con corrispondenze sparse, possono essere eseguiti in modo sub-quadratico. Per una panoramica pratica che colma teoria e implementazione, vedi le note di Neil Fraser.

Quando "ottimale" non è leggibile: strategie di pazienza e istogramma

Myers mira a script di modifica minimi, ma "minimo" ≠ "più leggibile". Grandi blocchi riordinati o duplicati possono ingannare un algoritmo SES puro in allineamenti scomodi. Entra patience diff, attribuito a Bram Cohen: si ancora a linee uniche e a bassa frequenza per stabilizzare gli allineamenti, producendo spesso diff che gli esseri umani trovano più puliti — specialmente nel codice con funzioni spostate o blocchi riorganizzati. Molti strumenti espongono questo tramite un'opzione "pazienza" (ad es.,diff.algorithm).

Histogram diff estende la pazienza con un istogramma di frequenza per gestire meglio gli elementi a bassa occorrenza pur rimanendo veloce (reso popolare in JGit). Se hai mai scoperto che --histogram produce hunk più chiari per file rumorosi, è per design. Su Git moderno, puoi scegliere l'algoritmo a livello globale o per invocazione:git config diff.algorithm myers|patience|histogram o git diff --patience.

Chiarezza a livello di parola, controllo degli spazi bianchi e evidenziazione del codice spostato

I diff di riga sono concisi ma possono oscurare piccole modifiche. I diff a livello di parola (--word-diff) colorano le modifiche all'interno della riga senza inondare la revisione con inserimenti/cancellazioni di intere righe — ottimo per la prosa, le stringhe lunghe o le righe singole.

Gli spazi bianchi possono inondare i diff dopo la riformattazione. Sia Git che GNU diff ti permettono di ignorare le modifiche agli spazi in diversi gradi e le opzioni per gli spazi bianchi di GNU diff (-b, -w, -B) aiutano quando viene eseguito un formattatore; vedrai modifiche logiche invece di rumore di allineamento.

Quando il codice si sposta in blocco, Git può evidenziare i blocchi spostati con --color-moved, separando visivamente "spostato" da "modificato", il che aiuta i revisori a verificare che uno spostamento non abbia nascosto modifiche non intenzionali. Rendilo persistente tramite diff.colorMoved.

Diff al servizio delle unioni: a due vie vs. a tre vie e diff3

Un diff a due vie confronta esattamente due versioni; non può dire se entrambe le parti hanno modificato la stessa riga di base, quindi spesso crea troppi conflitti. L'unione a tre vie (usata dai VCS moderni) calcola i diff da un antenato comunea ciascuna parte e poi riconcilia i due insiemi di modifiche. Questo riduce drasticamente i conflitti spuri e fornisce un contesto migliore. Il nucleo algoritmico classico qui è diff3, che unisce le modifiche da "O" (base) a "A" e "B" e contrassegna i conflitti dove necessario.

Il lavoro accademico e industriale continua a formalizzare e migliorare la correttezza dell'unione; per esempio, le unioni a tre vie verificate propongono nozioni semantiche di assenza di conflitti. Nel quotidiano di Git, la moderna strategia di unione ort si basa sul diffing e sul rilevamento delle rinomine per produrre unioni con meno sorprese. Per gli utenti, i consigli chiave sono: mostrare le righe di base nei conflitti con merge.conflictStyle=diff3, e integrare frequentemente in modo che i diff rimangano piccoli.

Rilevamento delle rinomine e le sue soglie

I diff tradizionali non possono "vedere" le rinomine perché l'indirizzamento del contenuto tratta i file come blob; vedono solo una cancellazione e un'aggiunta. Le euristiche di rilevamento delle rinomine colmano questa lacuna confrontando la somiglianza tra le coppie aggiunte/rimosse. In Git, abilita o regola tramite -M/--find-renames[=<n>] (il default è ~50% di somiglianza). Abbassalo per spostamenti più rumorosi. Puoi limitare i confronti dei candidati con diff.renameLimit (e merge.renameLimit durante le unioni). Per seguire la cronologia attraverso le rinomine, usa git log --follow -- <path>. Git recente esegue anche il rilevamento delle rinomine di directory per propagare gli spostamenti di cartelle durante le unioni.

Diff binari e delta: rsync, VCDIFF/xdelta, bsdiff

Il testo non è l'unica cosa che cambia. Per i binari, di solito vuoi la codifica delta — emettere istruzioni di copia/aggiunta per ricostruire un target da una fonte. L' algoritmo rsync ha aperto la strada alla differenziazione remota efficiente usando checksum a rotazione per allineare i blocchi attraverso una rete, minimizzando la larghezza di banda.

L'IETF ha standardizzato un formato delta generico, VCDIFF (RFC 3284), che descrive un bytecode di ADD, COPY e RUN, con implementazioni come xdelta3 che lo usano per l'applicazione di patch binarie. Per patch compatte su eseguibili, bsdiff produce spesso delta molto piccoli tramite array di suffissi e compressione; sceglilo quando la dimensione della patch domina e la generazione può avvenire offline.

Diff di testo oltre il codice sorgente: corrispondenza fuzzy e applicazione di patch

Quando hai bisogno di un'applicazione di patch robusta di fronte a modifiche concorrenti o contesti leggermente disallineati — pensa a editor o sistemi collaborativi — considera diff-match-patch. Sposa la differenziazione in stile Myers con Bitap corrispondenza fuzzy per trovare corrispondenze vicine e applicare patch "al meglio", più accelerazioni pre-diff e pulizie post-diff che scambiano un po' di minimalismo per un output umano più gradevole. Per come combinare diff e patch fuzzy in cicli di sincronizzazione continui, vedi la Sincronizzazione Differenzialedi Fraser.

Diff di dati strutturati: tabelle e alberi

I diff di riga su CSV/TSV sono fragili perché una modifica di una singola cella può sembrare una modifica di un'intera riga. Gli strumenti di diff consapevoli delle tabelle (daff) trattano i dati come righe/colonne, emettendo patch che mirano a celle specifiche e rendendo visualizzazioni che rendono evidenti aggiunte, cancellazioni e modifiche (vedi la vignetta R). Per controlli rapidi, i differenziatori CSV specializzati possono evidenziare le modifiche cella per cella e i cambiamenti di tipo; non sono algoritmicamente esotici, ma aumentano il segnale di revisioneconfrontando la struttura a cui tieni effettivamente.

Regolazione pratica di Git diff: una lista di controllo per il revisore

Come le unioni consumano effettivamente i diff (e cosa fare quando non lo fanno)

Un'unione calcola due diff (BASE→OURS, BASE→THEIRS) e cerca di applicarli entrambi a BASE. Strategie come ort orchestrano questo su larga scala, includendo il rilevamento delle rinomine (inclusi gli spostamenti su scala di directory) e euristiche per minimizzare i conflitti. Quando si verificano conflitti, --conflict=diff3 arricchisce i marcatori con il contesto di base, che è inestimabile per comprendere l'intento. Il capitolo di Pro Git su Unione Avanzata illustra i modelli di risoluzione, e i documenti di Git elencano manopole come -X ours e -X theirs. Per risparmiare tempo su conflitti ricorrenti, abilita rerere per registrare e riprodurre le tue risoluzioni.

Oltre i file: scenari remoti e incrementali

Se stai sincronizzando grandi risorse su una rete, sei più vicino al rsync mondo che al diff locale. Rsync calcola checksum a rotazione per scoprire blocchi corrispondenti in remoto, quindi trasferisce solo ciò che è necessario. Per i delta impacchettati, VCDIFF/xdelta ti dà un bytecode standard e strumenti maturi; sceglilo quando controlli sia l'encoder che il decoder. E se la dimensione della patch è fondamentale (ad es., firmware over-the-air), bsdiff scambia CPU/memoria al momento della compilazione per patch molto piccole.

Una parola veloce su "fuzzy" e "amichevole"

Librerie come diff-match-patch accettano che, nel mondo reale, il file che stai patchando potrebbe essere cambiato. Combinando un diff solido (spesso Myers) con la corrispondenza fuzzy (Bitap) e regole di pulizia configurabili, possono trovare il posto giusto per applicare una patch e rendere il diff più leggibile — fondamentale per la modifica collaborativa e la sincronizzazione.

Le "puntate minime" che dovresti interiorizzare

  1. Conosci i tuoi formati. I diff unificati (-u/-U<n>) sono compatti e adatti alle patch; sono ciò che si aspettano la revisione del codice e la CI (riferimento).
  2. Conosci i tuoi algoritmi. Myers per modifiche minime veloci (articolo); pazienza/istogramma per la leggibilità su riordini o blocchi rumorosi (pazienza, istogramma); Hirschberg per il trucco dello spazio lineare (articolo); Hunt–Szymanski per l'accelerazione delle corrispondenze sparse (articolo).
  3. Conosci i tuoi interruttori. Controlli degli spazi bianchi, word-diff e color-moved sono moltiplicatori di revisione (documenti di git diff; opzioni per gli spazi bianchi di GNU).
  4. Conosci le tue unioni. A tre vie con diff3 -style è meno confuso; ort più il rilevamento delle rinomine riduce il churn; rerere risparmia tempo.
  5. Scegli lo strumento giusto per i dati. Per CSV/tabelle, usa daff; per i binari, usa VCDIFF/xdelta o bsdiff.

Appendice: piccolo ricettario di comandi

Perché la memoria muscolare conta:

# Mostra un diff unificato standard con contesto extra
  git diff -U5
  diff -u -U5 a b
  
  # Ottieni chiarezza a livello di parola per righe lunghe o prosa
  git diff --word-diff
  
  # Ignora il rumore degli spazi bianchi dopo la riformattazione
  git diff -b -w --ignore-blank-lines
  diff -b -w -B a b
  
  # Evidenzia il codice spostato durante la revisione
  git diff --color-moved
  git config --global diff.colorMoved default
  
  # Doma i refactoring con il rilevamento delle rinomine e segui la cronologia attraverso le rinomine
  git diff -M
  git log --follow -- <file>
  
  # Preferisci l'algoritmo per la leggibilità
  git diff --patience
  git diff --histogram
  git config --global diff.algorithm patience
  
  # Vedi le righe di base nei marcatori di conflitto
  git config --global merge.conflictStyle diff3

Pensiero finale

I grandi diff riguardano meno la dimostrazione della minimalità e più la massimizzazione della comprensione del revisore con un costo cognitivo minimo. Ecco perché l' ecosistema ha sviluppato più algoritmi (Myers, pazienza, istogramma), più presentazioni (unificato, word-diff, color-moved) e strumenti consapevoli del dominio (daff per tabelle, xdelta/bsdiff per binari). Impara i compromessi, regola le manopole e passerai più tempo a ragionare sull'intento e meno tempo a riassemblare il contesto da righe rosse e verdi.


Riferimenti selezionati e letture aggiuntive

Domande Frequenti

Cos'è un diff?

Un diff è uno strumento o una funzionalità utilizzata nei sistemi di controllo versione per evidenziare le differenze tra due versioni o istanze di un file. È tipicamente usato per tracciare le modifiche o gli aggiornamenti fatti al file nel tempo.

Come un diff confronta due file?

Un diff confronta due file riga per riga. Scansiona e associa ogni riga nel primo file con la sua corrispondente nel secondo file, notando tutte le differenze significative come aggiunte, cancellazioni o modifiche.

Cos'è una patch nel contesto dei diff?

Una patch è un file che contiene le differenze tra due file, come prodotto dallo strumento diff. Può essere applicata a una versione di un file con il comando 'patch' per aggiornarlo a una versione più recente.

Cosa sono i diff unificati?

I diff unificati sono un tipo di formato di file diff che presenta le modifiche in un formato di file adatto per i file di testo. Mostra le cancellazioni dal file originale precedute da un '-', e le aggiunte al file originale sono precedute da un '+'.

Perché i diff sono cruciali nei sistemi di controllo della versione?

I diff sono cruciali nei sistemi di controllo della versione perché consentono ai team di tracciare le modifiche apportate a un file nel tempo. Questo tracciamento facilita il mantenimento della coerenza, previene il duplicazione del lavoro, individua errori o discrepanze, e gestisce in modo efficiente più versioni di file.

Cos'è l'algoritmo LCS nei diff strumenti?

L'algoritmo Longest Common Subsequence(LCS) è un metodo comune usato nei diff strumenti per trovare la sequenza più lunga di caratteri che appaiono da sinistra a destra in entrambi i file originali e modificati.Questo algoritmo aiuta a identificare le principali somiglianze e differenze tra due file.

Gli strumenti diff possono confrontare i file binari?

La maggior parte degli strumenti diff di base può confrontare solo file di testo. Tuttavia, strumenti diff specializzati sono progettati per confrontare file binari, mostrando le differenze in un formato leggibile.

Quali sono alcuni diff strumenti comunemente utilizzati oggi?

Alcuni dei più popolari diff strumenti includono GNU diff, DiffMerge, KDiff3, WinMerge (Windows), e FileMerge (Mac). Molte Integrated Development Environments (IDE) includono anche utilità diff incorporate.

Come posso creare un diff in Git?

In Git, puoi creare un diff utilizzando il comando `git diff` seguito dalle due versioni dei file che vuoi confrontare. L'output mostrerà le differenze tra i due file.

Posso utilizzare gli strumenti diff con le directory, non solo con i file?

Sì, molti strumenti diff hanno la capacità di confrontare directory oltre ai file individuali. Questa caratteristica può essere particolarmente utile quando si confrontano versioni di un grande progetto con molti file.