Comparatore di Testi

Confronta due testi affiancati e evidenzia le differenze riga per riga

Prova un esempio

Testo A

Testo B

Esegue in locale · Sicuro per incollare segreti
Esegue in locale · Sicuro per incollare segreti

Cos'è il Text Diff?

Un text diff (abbreviazione di "difference", differenza) è il risultato del confronto di due blocchi di testo che identifica quali righe sono state aggiunte, rimosse o lasciate invariate. Il concetto nasce dall'utility Unix diff, rilasciata per la prima volta nel 1974 come parte di Version 5 Unix. Oggi il text diff è la base dei sistemi di controllo versione come Git, dove ogni commit memorizza un diff anziché una copia completa di ogni file.

Un algoritmo diff trova la Longest Common Subsequence (LCS) tra due sequenze di righe. Le righe presenti nell'LCS sono marcate come invariate. Le righe del testo originale non presenti nell'LCS sono marcate come rimosse. Le righe del testo modificato non presenti nell'LCS sono marcate come aggiunte. Il risultato è un insieme minimo di modifiche necessarie per trasformare un testo nell'altro.

L'output di un diff può avere diversi formati. Il unified diff (predefinito per git diff) prefissa le righe rimosse con un segno meno e quelle aggiunte con un segno più. Il diff affiancato dispone entrambi i testi in colonne parallele. Questo strumento usa il confronto riga per riga con output a colori: verde per le aggiunte, rosso per le rimozioni e neutro per le righe invariate. Le righe invariate sono mostrate senza prefisso per impostazione predefinita, ma possono essere nascoste per concentrarsi solo sulle modifiche.

Perché usare uno strumento di diff online?

Confrontare testi in un terminale richiede di installare utility diff e gestire le opzioni della riga di comando. Uno strumento diff basato su browser elimina completamente questa complessità.

Confronto istantaneo
Incolla due blocchi di testo e vedi le differenze evidenziate immediatamente. Nessuna creazione di file, nessun comando da ricordare, nessun output da interpretare.
🔒
Elaborazione privacy-first
Tutto il confronto avviene nel tuo browser tramite JavaScript. Il tuo testo non lascia mai il dispositivo, il che è importante quando si confrontano file di configurazione, credenziali o codice proprietario.
📋
Output pronto da copiare
L'output del diff usa i prefissi standard + / - che corrispondono al formato unified diff. Puoi copiare il risultato direttamente nei messaggi di commit, nei commenti di code review o nei report di bug.
🌐
Nessun login o installazione richiesti
Funziona su qualsiasi dispositivo con un browser. Nessuna creazione di account, nessuna estensione, nessuna app desktop. Apri la pagina e inizia a confrontare.

Casi d'uso del Text Diff

Sviluppo Frontend
Confronta l'output CSS o HTML minificato prima e dopo una fase di build per individuare modifiche indesiderate nel markup o negli stili generati.
Sviluppo Backend
Esegui il diff delle risposte API tra ambienti diversi (staging vs produzione) per verificare che un deploy non abbia introdotto cambiamenti imprevisti nei dati.
DevOps & Infrastruttura
Confronta manifest Kubernetes, piani Terraform o configurazioni Nginx prima di applicare modifiche a un cluster o a un server in produzione.
QA & Testing
Verifica che l'output dei test corrisponda ai baseline attesi confrontando il risultato effettivo con un file snapshot memorizzato.
Data Engineering
Confronta le intestazioni CSV o le definizioni di schema SQL tra migrazioni di database per confermare che le colonne siano state aggiunte o rinominate correttamente.
Studio & Formazione
Confronta la tua soluzione con un'implementazione di riferimento riga per riga per trovare dove la tua logica diverge dall'approccio atteso.

Formati di output diff a confronto

Gli strumenti diff producono output in diversi formati. La tabella seguente riassume i più comuni, cosa li genera e quando ciascuno è utile.

FormatoStrumento / SorgenteDescrizione
Unified diffdiff -u / git diffPrefixes lines with + / - / space; includes @@ hunk headers
Side-by-sidediff -y / sdiffTwo columns, changed lines aligned horizontally
Context diffdiff -cShows changed lines with surrounding context, marked with ! / + / -
HTML diffPython difflibColor-coded HTML table with inline change highlights
JSON PatchRFC 6902Array of add/remove/replace operations on a JSON document

Come funziona il diff per righe: l'algoritmo LCS

La maggior parte degli strumenti di diff per righe, incluso questo, usa l'algoritmo Longest Common Subsequence (LCS). LCS trova il maggior insieme di righe che compaiono in entrambi i testi nello stesso ordine relativo, senza richiedere che siano contigue. Le righe non presenti nell'LCS sono le differenze effettive.

L'algoritmo LCS standard usa la programmazione dinamica e ha complessità O(m x n), dove m e n sono il numero di righe dei due testi. Per file di grandi dimensioni, varianti ottimizzate come l'algoritmo diff di Myers (usato da Git) riducono questo a O(n + d^2) dove d è il numero di differenze, rendendolo veloce quando la maggior parte delle righe è condivisa.

1. Costruisci la tabella DP
Crea una matrice (m+1) x (n+1). Per ogni coppia di righe, memorizza la lunghezza della sottosequenza comune più lunga trovata finora. Le righe uguali estendono il valore diagonale di 1.
2. Backtrack
Percorri la matrice dall'angolo in basso a destra fino a (0,0). Le mosse diagonali su righe uguali producono voci "invariate". Le mosse orizzontali o verticali producono voci "aggiunte" o "rimosse".
3. Genera l'output
Mappa ogni voce su una riga visualizzata: le righe invariate non hanno prefisso, quelle aggiunte ottengono +, quelle rimosse ottengono -. Applica la codifica a colori per maggiore chiarezza visiva.

Esempi di codice

Implementazioni del confronto testuale riga per riga in JavaScript, Python, Go e da riga di comando. Ogni esempio produce output in stile unified diff.

JavaScript
// Line-by-line diff using the LCS algorithm
function diffLines(a, b) {
  const linesA = a.split('\n')
  const linesB = b.split('\n')

  // Build LCS table
  const m = linesA.length, n = linesB.length
  const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
  for (let i = 1; i <= m; i++)
    for (let j = 1; j <= n; j++)
      dp[i][j] = linesA[i-1] === linesB[j-1]
        ? dp[i-1][j-1] + 1
        : Math.max(dp[i-1][j], dp[i][j-1])

  // Backtrack to produce diff
  const result = []
  let i = m, j = n
  while (i > 0 || j > 0) {
    if (i > 0 && j > 0 && linesA[i-1] === linesB[j-1]) {
      result.unshift({ type: 'equal', text: linesA[i-1] }); i--; j--
    } else if (j > 0 && (i === 0 || dp[i][j-1] >= dp[i-1][j])) {
      result.unshift({ type: 'add', text: linesB[j-1] }); j--
    } else {
      result.unshift({ type: 'remove', text: linesA[i-1] }); i--
    }
  }
  return result
}

const diff = diffLines("alpha\nbeta\ngamma", "alpha\nbeta changed\ngamma\ndelta")
// → [
//   { type: 'equal',  text: 'alpha' },
//   { type: 'remove', text: 'beta' },
//   { type: 'add',    text: 'beta changed' },
//   { type: 'equal',  text: 'gamma' },
//   { type: 'add',    text: 'delta' }
// ]
Python
import difflib

text_a = """alpha
beta
gamma""".splitlines()

text_b = """alpha
beta changed
gamma
delta""".splitlines()

# Unified diff (same format as git diff)
for line in difflib.unified_diff(text_a, text_b, fromfile='a.txt', tofile='b.txt', lineterm=''):
    print(line)
# --- a.txt
# +++ b.txt
# @@ -1,3 +1,4 @@
#  alpha
# -beta
# +beta changed
#  gamma
# +delta

# HTML side-by-side diff
d = difflib.HtmlDiff()
html = d.make_file(text_a, text_b, fromdesc='Original', todesc='Modified')
Go
package main

import (
	"fmt"
	"strings"
)

// Minimal LCS-based line diff
func diffLines(a, b string) {
	la := strings.Split(a, "\n")
	lb := strings.Split(b, "\n")
	m, n := len(la), len(lb)

	dp := make([][]int, m+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}
	for i := 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if la[i-1] == lb[j-1] {
				dp[i][j] = dp[i-1][j-1] + 1
			} else if dp[i-1][j] >= dp[i][j-1] {
				dp[i][j] = dp[i-1][j]
			} else {
				dp[i][j] = dp[i][j-1]
			}
		}
	}

	var result []string
	i, j := m, n
	for i > 0 || j > 0 {
		if i > 0 && j > 0 && la[i-1] == lb[j-1] {
			result = append([]string{" " + la[i-1]}, result...)
			i--; j--
		} else if j > 0 && (i == 0 || dp[i][j-1] >= dp[i-1][j]) {
			result = append([]string{"+" + lb[j-1]}, result...)
			j--
		} else {
			result = append([]string{"-" + la[i-1]}, result...)
			i--
		}
	}

	for _, line := range result {
		fmt.Println(line)
	}
}

// Output:
//  alpha
// -beta
// +beta changed
//  gamma
// +delta
CLI (diff / git)
# Compare two files with unified diff (3 lines of context)
diff -u original.txt modified.txt

# Git diff between working tree and last commit
git diff HEAD -- file.txt

# Git diff between two branches
git diff main..feature -- src/

# Side-by-side diff in the terminal
diff -y --width=120 original.txt modified.txt

# Color-coded diff (requires colordiff)
diff -u original.txt modified.txt | colordiff

Domande frequenti

Qual è la differenza tra un diff per righe e un diff per caratteri?
Un diff per righe confronta il testo riga per riga: se qualsiasi carattere in una riga cambia, l'intera riga è marcata come rimossa e la nuova versione è marcata come aggiunta. Un diff per caratteri (o per parole) opera a una granularità più fine, marcando i caratteri o le parole specifici che sono cambiati all'interno di una riga. Il diff per righe è lo standard per la code review; il diff per caratteri è più utile per l'editing di testi in prosa.
Come funziona git diff internamente?
Git usa l'algoritmo diff di Myers per impostazione predefinita, che trova lo script di modifica più breve (il numero minimo di inserimenti e cancellazioni) tra due file. Git memorizza il risultato in formato unified diff con intestazioni di hunk @@ che indicano i numeri di riga. Quando esegui git diff, Git confronta il working tree con l'index (staging area), non con l'ultimo commit, a meno che non passi HEAD esplicitamente.
Posso confrontare file binari con uno strumento di diff testuale?
No. Gli strumenti di diff testuale dividono l'input sui caratteri di newline e confrontano stringhe. I file binari contengono sequenze di byte arbitrarie che producono suddivisioni in righe prive di senso. Per il confronto binario, usa uno strumento di hex diff o un confronto di checksum a livello di file (sha256sum su entrambi i file).
I miei dati vengono inviati a un server quando uso questo strumento?
No. Questo strumento funziona interamente nel tuo browser. Il calcolo del diff usa un'implementazione JavaScript dell'LCS che viene eseguita lato client. Nessuna richiesta di rete viene effettuata con il contenuto del tuo testo. Puoi verificarlo aprendo il tab Rete del tuo browser mentre usi lo strumento.
Cos'è il formato unified diff?
Unified diff è il formato di output usato da diff -u e git diff. Mostra le righe modificate con prefissi - (rimossa) e + (aggiunta), preceduti da intestazioni @@ che specificano gli intervalli di numeri di riga in entrambi i file. Le righe di contesto (invariate) hanno un prefisso spazio. Unified diff è il formato più comune per patch, pull request e strumenti di code review.
Come confronto file grandi con molte differenze?
Per file con migliaia di righe, uno strumento basato su browser funziona ma può rallentare perché l'algoritmo LCS scala in modo quadratico. Per diff molto grandi, gli strumenti da riga di comando come diff o git diff sono più veloci perché usano implementazioni C ottimizzate e possono trasmettere l'output in streaming. Puoi anche filtrare le righe invariate (disattiva "Mostra righe invariate" in questo strumento) per concentrarti solo sulle modifiche.
Cos'è un diff a tre vie (three-way merge diff)?
Un three-way merge confronta due versioni modificate di un file rispetto al loro antenato comune (la base). Git lo usa durante git merge e git rebase. Identifica le modifiche apportate in ciascun branch rispetto alla base e le combina. Quando entrambi i branch modificano la stessa riga, Git segnala un conflitto di merge. Il three-way merge richiede tre input, mentre un diff standard ne richiede solo due.