Comparador de texto (Diff)
Compare dois textos e encontre as diferenças instantaneamente.
Sobre a comparação de textos
Esta ferramenta de diff usa o algoritmo da maior subsequência comum (LCS) para comparar dois textos linha a linha. As adições são destacadas em verde e as exclusões em vermelho. Escolha a visualização « Em linha » para ver todas as mudanças em uma única coluna, ou « Lado a lado » para comparar os textos original e modificado em paralelo.
Usos comuns
- Comparar mudanças de código antes de fazer commit
- Revisar documentos ou contratos modificados
- Verificar as diferenças de tradução
- Validar mudanças em arquivos de configuração
- Comparar respostas de API
Perguntas frequentes
A comparação é feita caractere por caractere ?
Esta ferramenta compara linha a linha. Se uma linha tem a menor mudança (mesmo um único caractere), toda a linha é marcada como modificada. É a mesma abordagem usada pelo Git e pela maioria das ferramentas de diff.
Há limite de tamanho ?
Não há limite rígido, mas textos muito grandes (mais de 10 000 linhas) podem levar um instante para serem processados, pois a comparação é executada inteiramente no seu navegador.
O que «diff» realmente significa
Um diff descreve como transformar um texto em outro usando o menor conjunto de inserções e exclusões. Há infinitas maneiras de fazer isso; a trivial é «apagar cada caractere de A e depois inserir cada caractere de B». Um diff útil é o menor script de edição, que é o dual do problema da Maior Subsequência Comum: encontrar a sequência mais longa de linhas que aparece (na ordem) em ambos os textos, e todo o resto é uma adição ou uma exclusão. A maioria dos algoritmos de diff são algoritmos de LCS com um chapéu diferente.
Um ponto sutil: a maior subsequência comum não é a maior substring comum. Uma subsequência preserva a ordem, mas não a adjacência, então «ABCDE» e «AXBYCZD» compartilham a subsequência «ABCD», mesmo que nenhuma sequência contígua de três caracteres apareça em ambas.
Uma breve história dos algoritmos de diff
O primeiro programa de comparação de arquivos amplamente usado foi o diff do Unix, escrito por Douglas McIlroy no Bell Labs, com o algoritmo subjacente publicado por James W. Hunt e McIlroy como o Bell Labs Computing Science Technical Report #41, em junho de 1976. O próprio McIlroy descreveu os quatro meses de desenvolvimento como «um esforço desesperado». A abordagem de Hunt-McIlroy fazia hash de cada linha do arquivo B, indexava onde cada linha única ocorria e procurava a cadeia de correspondências monotonicamente crescente mais longa. Ele veio no Version 6 Unix e permaneceu essencialmente o mesmo algoritmo no /usr/bin/diff na maioria dos sistemas Unix por décadas.
Eugene W. Myers publicou o padrão moderno da indústria em 1986, «An O(ND) Difference Algorithm and Its Variations», na Algorithmica Vol. 1, No. 2. Myers reformulou o LCS como um problema de caminho mais curto através de um grafo de edição: coloque A no eixo de cima e B na lateral, desenhe uma diagonal sempre que duas linhas coincidirem e procure o caminho do canto superior esquerdo ao inferior direito com o menor número de arestas não diagonais. Cada aresta não diagonal é uma inserção ou exclusão; cada diagonal é gratuita. O ponto crucial: o algoritmo roda em tempo O((N+M)·D), em que D é o tamanho do script de edição, ou seja, ele fica mais rápido quanto mais parecidos os arquivos são. Para os diffs típicos de controle de versão, D é minúsculo comparado a N+M, então o Myers é, na prática, drasticamente mais rápido que o pior caso O(N·M). Seu artigo também inclui um refinamento de espaço linear usando um truque de dividir para conquistar chamado «middle snake». O algoritmo de Myers é o padrão por trás do GNU diff, do git diff, do Mercurial, do Subversion, do jsdiff, do difflib do Python e da maioria dos visualizadores gráficos de diff.
Bram Cohen (mais tarde mais conhecido como o inventor do BitTorrent) projetou o patience diff para o sistema de controle de versão Bazaar por volta de 2002. O problema motivador: o diff de Myers alinha qualquer linha correspondente, incluindo as muito comuns, então mover uma função em C pode produzir um diff ruidoso em que a chave de fechamento da função movida se alinha com a chave de fechamento de uma função sem relação. O patience diff ancora o diff em linhas que ocorrem exatamente uma vez em cada arquivo (normalmente assinaturas de função, cabeçalhos de comentário, mensagens de log distintivas), calcula o LCS apenas desses âncoras usando o patience sort e recursa nos intervalos. O resultado se alinha em linhas significativas e fica mais legível para código-fonte. O Git o suporta via git diff --patience. O histogram diff é um refinamento adicionado ao git por volta de 2010 que constrói um histograma de ocorrências de linha e prefere âncoras de baixa frequência em vez de estritamente únicas; do git 2.45 em diante, é o padrão para muitas configurações.
Levenshtein vs. LCS
Um conceito relacionado que vale a pena distinguir. A distância de Levenshtein (Vladimir Levenshtein, 1965) conta o número mínimo de inserções, exclusões e substituições de um único caractere para transformar uma string em outra. O diff baseado em LCS é intimamente relacionado, mas ligeiramente diferente: o diff clássico trata uma «mudança» como um par de exclusão-depois-inserção, em vez de uma única substituição, porque isso se mapeia melhor em arquivos orientados a linhas. O Levenshtein responde «quão diferentes são estas strings?» e te dá um número; o LCS responde «o que especificamente mudou?» e te dá um script de edição de verdade. Os corretores ortográficos e os recursos de «você quis dizer?» querem o primeiro; as ferramentas de diff querem o segundo. A variante Damerau-Levenshtein (1964) estende o Levenshtein com um operador de transposição para a detecção de erros de digitação.
Granularidade: linha, palavra e caractere
O diff pode ser calculado em diferentes granularidades, cada uma com seus compromissos:
- Nível de linha: cada linha é um token; duas linhas ou coincidem exatamente ou não. Rápido, mapeia-se de forma limpa em como os programadores editam código, produz patches concisos que o
patch(1)consegue aplicar. Custo: reformatar um caractere em uma linha de 200 caracteres marca a linha inteira como alterada. O padrão dodiff, do git, do SVN e desta ferramenta. - Nível de palavra: cada token delimitado por espaço em branco é uma unidade, então uma linha que mudou uma palavra mostra apenas aquela palavra destacada. Excelente para prosa, contratos, rascunhos de blog. Usado pelo
git diff --word-diff, pelo modo «Sugestão» do Google Docs, pelo «Controle de Alterações» do Microsoft Word e pelo modo de comparar palavras do Diffchecker. - Nível de caractere: cada ponto de código Unicode é uma unidade. Pega erros de digitação de um único caractere, ideal para a marcação de revisão jurídica, em que uma palavra pode inverter o sentido. Lento em entradas grandes e às vezes ilegível para edições longas.
Um padrão comum nas interfaces de diff modernas é calcular o diff primeiro no nível de linha e, então, para qualquer par de «vizinhos removida/adicionada», rodar um diff secundário no nível de palavra apenas naquelas duas linhas e destacar as mudanças dentro da linha. É exatamente assim que a visualização de PR do GitHub e a biblioteca diff-match-patch funcionam.
Três modos de exibição de diff que você verá
- Diff unificado (o formato de todo arquivo
.patch), com hunks introduzidos por@@ -oldStart,oldLen +newStart,newLen @@e três linhas de contexto acima e abaixo, por padrão. Surgiu com a flag-udo GNU diff, de Wayne Davison, por volta de 1990. Compacto e legível por máquina pelopatch(1), e é por isso que o git, os patches de e-mail no estilo do kernel e o SVN todos o usam. - Lado a lado: o original à esquerda, o modificado à direita, alinhados linha por linha. O
diff -yproduz uma versão ASCII primitiva; Beyond Compare, Meld, WinMerge e a visualização «Lado a lado» acima todos usam este formato. O melhor para revisão visual e revisão de prosa. - Em linha (empilhado): uma única coluna em que as linhas removidas e adicionadas ficam intercaladas. A visualização de PR do GitHub usa isso por padrão. O formato mais eficiente em espaço para telas estreitas e edições pequenas.
Variantes úteis do git diff
git diff: índice vs. árvore de trabalho.git diff --staged: HEAD vs. índice.git diff main..feature: as pontas dos branches.main...featurecompara em relação à base de merge, o que o PR vai incorporar.git diff --word-diffe--color-words: diff no nível de palavra amigável a marcação e tingido de cor.git diff --no-index a.txt b.txt: funciona em arquivos fora de qualquer repositório git. Prático como um diff autônomo de pobre, com os algoritmos patience ou histogram.git diff -w: ignora todos os espaços em branco (corresponde à caixa de seleção «Ignorar os espaços» acima).git diff --histogram: troca o algoritmo por comando.
Quando você recorreria a um diff no navegador
- Revisão de código. Cole duas versões de um arquivo, examine o que mudou, decida se a mudança faz sentido.
- Revisar código editado por IA. Compare seu original com a versão refatorada por um LLM para identificar desvios ou alucinações.
- Marcação de revisão de contratos jurídicos. Confirme que apenas as cláusulas acordadas mudaram entre a versão 3 e a versão 4.
- QA de tradução. Compare duas traduções francesas do mesmo parágrafo, ou faça o diff dos arquivos de localização anteriores e atualizados quando só um punhado de strings deveria ter mudado.
- Desvio de configuração. Compare o
nginx.confde produção com o de staging. - Comparação de schema SQL. Despeje as instruções
CREATE TABLEde dois bancos de dados e faça o diff delas para encontrar índices faltando ou desvio de tipo de coluna. - Desvio de especificação. Faça o diff de duas versões de um YAML OpenAPI / Swagger para verificar se as mudanças incompatíveis estão documentadas.
- Rascunhos de blog em Markdown. Identifique o que um coautor editou.
- Auditorias de conformidade. Faça o diff de uma política de privacidade mês a mês para os reguladores.
- Perícia de arquivos de lock. Faça o diff de
package-lock.jsonouyarn.lockpara entender uma atualização de dependência.
Limitações honestas
- O diff de texto simples não tem consciência semântica. Renomear
fooparabarem um arquivo parece, em custo, idêntico a uma reescrita totalmente sem relação. Ferramentas como o difftastic analisam a AST da linguagem e produzem diffs estruturais («função adicionada», «argumento reordenado»). Esta página não faz isso: é um diff de linha LCS simples. - Espaços em branco e fins de linha causam diffs espúrios. CRLF vs. LF, espaço em branco no final, tabulações vs. espaços. A alternância «Ignorar os espaços» acima corresponde ao
-wdo git. - Arquivos binários não se encaixam. Diff é um conceito de texto. Para diff binário, há ferramentas como
bsdiff,xdeltaou VBinDiff. - Sensibilidade à ordem. O diff de linha presume que os documentos foram editados linha por linha. Para CSVs não ordenados ou reordenações de chaves de objetos JSON, você vai querer ordenar ou canonicalizar primeiro.
- Detecção de movimento. O diff LCS clássico não reconhece que uma função foi movida dentro de um arquivo: ele mostra o movimento como uma exclusão mais uma inserção. Beyond Compare, Meld e difftastic tentam detectar movimentos; esta página não.
Mais perguntas
Por que esta página não mostra destaques no nível de caractere dentro das linhas alteradas?
Porque a passagem no nível de linha basta para a maioria dos casos de uso e roda muito mais rápido em entradas longas. Para destaque palavra por palavra dentro da linha, o refinamento em duas etapas é prática padrão, mas adiciona latência. Se a diferença da linha inteira importa para você (marcação de revisão jurídica, revisão de prosa), uma ferramenta dedicada no nível de palavra (incluindo o git diff --word-diff na linha de comando) é mais adequada.
Qual é a diferença entre o diff unificado e o lado a lado?
O diff unificado é o formato compacto e legível por máquina que todo arquivo .patch usa: três linhas de contexto, hunks marcados com @@. O lado a lado exibe as duas versões em colunas paralelas, o que é mais fácil para os olhos na revisão visual, mas ocupa mais espaço horizontal. O unificado é o que você enviaria por e-mail ou faria commit; o lado a lado é o que você leria em um monitor largo.
Existem algoritmos melhores que o Myers para código-fonte?
Para código-fonte com funções movidas ou grandes rearranjos, sim: o patience diff (Bram Cohen, 2002) e o histogram diff (git, por volta de 2010) são projetados para se alinhar em linhas únicas significativas, em vez de comuns, produzindo uma saída mais legível. Ambos estão disponíveis via git diff --patience e git diff --histogram. Ferramentas que conhecem a AST, como o difftastic, vão além e analisam a estrutura real da linguagem.
É seguro colar texto confidencial aqui?
Sim: o diff roda inteiramente no seu navegador, usando uma implementação de LCS em JavaScript. Nada é enviado, nenhuma análise sobre a entrada, nenhum log do texto no lado do servidor. Esta é a única categoria de ferramenta de diff que é segura para NDAs, código-fonte interno ou cláusulas de contrato não divulgadas; os serviços de diff baseados na nuvem veem tudo o que você cola.