Compare dois textos linha a linha. Destaca linhas adicionadas, removidas e inalteradas — como o git diff.
Diff (abreviação de difference) é o processo de comparar duas versões de um texto e identificar exatamente o que mudou entre elas — quais linhas foram adicionadas, quais foram removidas e quais permaneceram iguais. É uma das ferramentas mais fundamentais do desenvolvimento de software e da gestão de documentos.
O formato de saída padrão do diff usa convenções visuais simples:
linhas com + foram adicionadas na versão nova,
linhas com − foram removidas da versão original,
e linhas sem prefixo (ou com espaço) permaneceram iguais. Essa notação foi padronizada
pelo utilitário Unix diff nos anos 1970 e é usada até hoje
em Git, GitHub, code reviews e editores de código.
--- arquivo_original.txt +++ arquivo_modificado.txt @@ -1,5 +1,5 @@ Linha que não mudou -Linha que foi REMOVIDA +Linha que foi ADICIONADA Outra linha igual -Texto antigo aqui +Texto novo aqui
diff é criado nos Bell Labs por Douglas McIlroy
e implementado por James Hunt e McIlroy com base no algoritmo LCS (Longest Common Subsequence —
Maior Subsequência Comum). Publicado no Unix V5, o diff torna-se imediatamente essencial para
programadores que precisam rastrear mudanças em código-fonte. O paper original de Hunt e McIlroy
("An Algorithm for Differential File Comparison") continua sendo referência até hoje.
diff -u) — o formato com
---, +++ e cabeçalhos @@ que usamos até hoje.
O utilitário complementar patch permite aplicar
um arquivo diff a qualquer sistema, tornando possível distribuir apenas as mudanças
entre versões de software, não o arquivo completo.
svn diff ou cvs diff,
o programador vê exatamente o que mudou desde o último commit. O diff deixa de ser uma ferramenta
de linha de comando isolada e vira o núcleo do fluxo de trabalho de desenvolvimento colaborativo.
git diff torna-se a operação mais usada por desenvolvedores
do mundo — mostrando diferenças entre commits, branches e arquivos. O Git introduz o conceito
de diff de blobs (objetos binários), tornando possível rastrear mudanças em qualquer tipo de arquivo,
não apenas texto.
Por baixo de qualquer ferramenta de diff está um algoritmo que precisa responder: qual é a menor quantidade de mudanças necessária para transformar o texto A no texto B? Isso é chamado de edit distance (distância de edição) ou LCS problem.
LCS — Longest Common Subsequence (Maior Subsequência Comum): O algoritmo clássico encontra a maior sequência de linhas que aparecem em ambos os textos na mesma ordem, sem precisar ser contíguas. Tudo que está no A mas não no LCS foi removido; tudo que está no B mas não no LCS foi adicionado. Complexidade: O(n×m) onde n e m são o número de linhas.
| Algoritmo | Usado em | Complexidade | Característica |
|---|---|---|---|
| Hunt-McIlroy (LCS) | diff Unix original | O(n·d) onde d=diferenças | Clássico, ótimo para textos com poucas mudanças |
| Myers diff | Git, GNU diff moderno | O(n + d²) | Mais rápido que LCS, produz diffs mais legíveis |
| Patience diff | Git (opção), Bazaar | O(n log n) | Produz diffs mais intuitivos em refatorações pesadas |
| Histogram diff | Git (padrão atual) | O(n log n) | Evolução do Patience, melhor para código com blocos repetidos |
| Levenshtein | Diff de palavras/chars | O(n·m) | Opera caractere a caractere, não linha a linha |
# Ver mudanças não staged (working tree vs index) git diff # Ver mudanças staged (index vs último commit) git diff --staged # Comparar dois commits específicos git diff abc1234 def5678 # Comparar duas branches git diff main..feature/minha-feature # Diff de um arquivo específico git diff HEAD~1 -- src/arquivo.js # Diff com estatísticas (quantas linhas mudaram por arquivo) git diff --stat # Diff ignorando espaços em branco git diff -w # Diff usando algoritmo Patience (mais legível em refatorações) git diff --diff-algorithm=patience # Gerar arquivo .patch para enviar por email git diff > minhas-mudancas.patch # Aplicar um arquivo .patch git apply minhas-mudancas.patch
# Diff básico entre dois arquivos diff arquivo_a.txt arquivo_b.txt # Formato unified (mais legível, padrão moderno) diff -u arquivo_a.txt arquivo_b.txt # Ignorar maiúsculas/minúsculas diff -i arquivo_a.txt arquivo_b.txt # Ignorar linhas em branco diff -B arquivo_a.txt arquivo_b.txt # Ignorar espaços extras diff -b arquivo_a.txt arquivo_b.txt # Diff de diretórios (recursivo) diff -r pasta_antiga/ pasta_nova/ # Diff side-by-side (lado a lado) diff -y arquivo_a.txt arquivo_b.txt # Salvar o diff como patch diff -u original.txt modificado.txt > mudancas.patch
// Usando a biblioteca 'diff' (npm install diff) import * as Diff from 'diff'; const textoA = `linha 1\nlinha 2\nlinha 3`; const textoB = `linha 1\nlinha dois modificada\nlinha 3\nlinha 4 nova`; // Diff linha a linha const resultado = Diff.diffLines(textoA, textoB); resultado.forEach(parte => { const cor = parte.added ? '\x1b[32m' // verde : parte.removed ? '\x1b[31m' // vermelho : '\x1b[37m'; // branco process.stdout.write(cor + parte.value + '\x1b[0m'); }); // Diff de palavras (word-level) const diffPalavras = Diff.diffWords('hello world', 'hello novo mundo'); // Diff de caracteres const diffChars = Diff.diffChars('abcdef', 'abXYef');
# difflib — biblioteca nativa do Python import difflib textoA = """linha 1 linha 2 linha 3""".splitlines(keepends=True) textoB = """linha 1 linha dois modificada linha 3 linha 4 nova""".splitlines(keepends=True) # Unified diff (formato git/patch) diff = difflib.unified_diff(textoA, textoB, fromfile='original.txt', tofile='modificado.txt') print(''.join(diff)) # HTML diff visual (abre no navegador) differ = difflib.HtmlDiff() html = differ.make_file(textoA, textoB) with open('diff.html', 'w') as f: f.write(html) # Similarity ratio entre dois textos (0.0 a 1.0) ratio = difflib.SequenceMatcher(None, 'texto a', 'texto b').ratio() print(f"Similaridade: {ratio:.1%}")
A granularidade do diff determina a menor unidade de comparação:
git diff.Para código, diff de linha é o padrão. Para revisar textos em linguagem natural, diff de palavra é mais informativo.
O cabeçalho @@ é chamado de hunk header e indica em que parte do arquivo está o bloco de mudanças:
-1,5 → no arquivo original, o bloco começa na linha 1 e tem 5 linhas de contexto+1,6 → no arquivo modificado, o bloco começa na linha 1 e tem 6 linhas (uma a mais, porque uma linha foi adicionada)O formato completo é @@ -L,S +L,S @@ onde L=linha inicial e S=quantidade de linhas no hunk.
JSON não está formatado de forma consistente entre fontes diferentes. Antes de comparar, normalize os dois JSONs:
jq . arquivo.json no terminaljq --sort-keys . arquivo.jsonPara diff de JSONs diretamente: diff <(jq --sort-keys . a.json) <(jq --sort-keys . b.json). Isso elimina falsos positivos causados por ordenação diferente de chaves ou formatação inconsistente.
O diff padrão não funciona bem com binários (PDFs, imagens, executáveis). Alternativas:
diff arquivo1.bin arquivo2.bin retorna exit code 0 se iguais, 1 se diferentes — útil em scriptspdftotext e compare os textos resultantesconvert imagem1.png imagem2.png -metric AE -compare diff.pngpython-docx ou converta para formato de texto antes de compararSão operações complementares no controle de versão:
No Git, o fluxo típico é: git diff para ver o que mudou → git merge para incorporar as mudanças → resolver conflitos manualmente se houver → git diff --staged para verificar o resultado antes de commitar.
Linha com + → adicionada na versão nova (B). Cor verde.
Linha com − → removida da versão original (A). Cor vermelha.
Algoritmo padrão: Myers diff (Git). Para refatorações grandes, use --diff-algorithm=patience para resultado mais legível.
Para JSON/configs: normalize o formato antes de comparar. jq --sort-keys . elimina falsos positivos por ordenação de chaves diferente.
Veja também