Comparar Textos

Nada do que você digita aqui é armazenado, registrado ou compartilhado.

Cole dois textos para ver exatamente o que mudou, linha a linha e palavra a palavra. Tudo roda no seu navegador, então nenhuma das versões é enviada.

Como usar

  1. Cole o original à esquerda e a nova versão à direita.
  2. As diferenças aparecem abaixo, lado a lado ou unificadas.
  3. Use as opções de ignorar se espaços ou maiúsculas não devem contar.

Como a comparação é calculada

Os dois textos são divididos em linhas, e as linhas em comum são encontradas como a maior subsequência comum - a mesma ideia em que o comando diff do Unix se baseia. Tudo o que está nessa subsequência mantém o lugar; o que sobra é informado como removido à esquerda ou adicionado à direita. Quando uma remoção e uma adição ficam lado a lado, elas são pareadas e mostradas como modificação, e não como dois eventos sem relação.

Cada par modificado passa então por uma segunda comparação por palavra, então uma linha longa com um único número alterado destaca esse número em vez de pintar a linha inteira de vermelho. Essa é a diferença entre um diff que se lê e um diff que exige apertar os olhos, e é por isso que ferramentas só por linha parecem pouco úteis para texto corrido e arquivos de configuração.

Antes de tudo isso, as linhas idênticas do início e do fim são cortadas. Dois arquivos de mil linhas que diferem num único ponto são, portanto, comparados como um punhado de linhas, o que é mais rápido e mais claro.

Quando duas linhas que parecem iguais são marcadas como diferentes

Essa é a surpresa mais comum, e a causa é sempre um caractere que você não vê. Espaços no fim da linha são o culpado mais frequente, e é por isso que ignorá-los vem ativado por padrão. Depois vêm as quebras de linha: um arquivo escrito no Windows termina as linhas com retorno de carro e avanço de linha, um escrito no macOS ou Linux só com avanço de linha, e um diff que compara os bytes brutos vai considerar todas as linhas alteradas.

Em seguida vêm tabs contra sequências de espaços, que a opção de ignorar espaços unifica; o espaço não separável que editores de texto e algumas páginas web inserem no lugar de um espaço normal; aspas curvas e travessões trocados pela autocorreção; e um BOM invisível no início da primeira linha. Qualquer um deles faz duas linhas idênticas na tela serem de fato diferentes no arquivo.

O limite de tamanho

A maior subsequência comum é quadrática: comparar m linhas com n linhas preenche uma tabela de m por n. Com algumas centenas de linhas isso é trivial; com dez mil contra dez mil são cem milhões de células, e a página pararia de responder enquanto as preenchesse.

Por isso a comparação tem um orçamento de quatro milhões de células depois de cortados o prefixo e o sufixo comuns, e uma comparação que passaria disso é recusada com uma mensagem em vez de ser tentada. Na prática, arquivos de milhares de linhas são comparados na hora desde que sejam razoavelmente parecidos, e só dois documentos grandes realmente sem relação atingem o limite. Quando isso acontece, a ferramenta certa é um diff de linha de comando que processe em fluxo.

Lado a lado ou unificado

A visão lado a lado mantém as duas versões em colunas próprias e é melhor para texto corrido, traduções e tudo em que você quer ler os dois textos como textos. A visão unificada as intercala com marcadores, que é o formato usado em patches e revisão de código, e é mais fácil de acompanhar quando as mudanças são pequenas e espalhadas por um arquivo longo.

Nenhuma das duas muda o que foi calculado; são duas apresentações do mesmo resultado.

Os algoritmos por trás de um diff

A abordagem clássica, publicada por Eugene Myers em 1986, encontra o menor script de edição entre duas sequências - o menor conjunto de inserções e remoções que transforma uma na outra. É o que o comando diff do Unix e a implementação padrão do Git usam, e é ótimo no sentido de produzir o menor número de mudanças.

Menos mudanças nem sempre é mais legível. O algoritmo de Myers pode alinhar linhas sem relação alguma que por acaso coincidem - uma chave de fechamento aqui, uma linha em branco ali - produzindo um diff que intercala duas funções em vez de mostrar uma removida e outra adicionada. O algoritmo patience do Git resolve isso ancorando-se em linhas que aparecem exatamente uma vez nas duas versões e recorrendo entre essas âncoras, o que normalmente coincide com aquilo que o leitor considera a correspondência real.

O algoritmo histogram, hoje a alternativa recomendada pelo Git, estende o patience com uma heurística de frequência e é mais rápido em arquivos grandes. Se um diff de code review parecer sem sentido, definir diff.algorithm como histogram frequentemente produz um resultado mais claro a partir exatamente dos mesmos dois arquivos.

Diferenças entre dois lados e merges de três vias

Comparar dois arquivos responde o que mudou. Um merge precisa de uma terceira entrada - o ancestral comum - porque sem ela não há como saber qual lado alterou uma linha e qual simplesmente manteve o original. É por isso que o controle de versão guarda uma base de merge e por isso que ferramentas de merge de três vias mostram três painéis.

Um conflito surge quando os dois lados alteram a mesma região em relação a esse ancestral. Todo o resto é mesclado automaticamente, inclusive alterações adjacentes que não se sobrepõem, e é por isso que duas pessoas podem editar o mesmo arquivo o dia inteiro sem conflito e então colidir em uma única linha.

Entender isso muda a forma como você resolve conflitos. Os marcadores em um arquivo conflitado mostram a sua versão e a do outro, mas a pergunta útil é o que cada lado estava tentando fazer em relação à base - e git checkout --conflict=diff3 acrescenta a base aos marcadores, o que normalmente torna a resolução óbvia em vez de um chute entre duas alternativas.

Comparando coisas que não são linhas de texto

A comparação por linhas pressupõe que os limites das linhas têm significado. JavaScript minificado, um payload JSON em uma única linha e um parágrafo longo de prosa quebram essa premissa: uma alteração de um caractere faz com que a linha inteira seja reportada como diferente. Formatar os dois lados antes restaura a estrutura de que o diff precisa e, no caso do JSON, uma forma canônica - chaves ordenadas, indentação consistente - torna a comparação significativa em vez de acidental.

O CSV tem o problema oposto: o diff por linhas funciona, mas reporta uma reordenação de colunas como alteração em todas as linhas. Ordenar antes por uma coluna-chave, ou usar uma ferramenta que entende CSV, separa a mudança que importa do ruído.

Formatos binários e quase binários precisam de conversores próprios. Um .docx é um zip de XML, um notebook é JSON com a saída embutida e um PDF é praticamente opaco. O Git oferece filtros textconv, que convertem um arquivo em texto antes da comparação, e é assim que as equipes conseguem diffs legíveis de documentos e notebooks sem guardar uma segunda cópia.

Lendo um diff escrito por outra pessoa

Um diff revisável depende sobretudo do que não está nele. Ruído de formatação - um formatador rodado sobre o arquivo, finais de linha alterados, um organizador de imports aplicado - enterra as três linhas que importam sob trezentas que não importam, e o remédio de sempre é separar o commit mecânico do commit substantivo, para que cada um possa ser lido no seu próprio ritmo.

Quando mesmo assim você recebe um diff misturado, a comparação que ignora espaços em branco é o caminho mais rápido: git diff -w, ou as opções de ignorar disponíveis aqui. Volte a ativá-los antes de aprovar, porque em alguns arquivos o espaço em branco é conteúdo - a indentação do Python, a estrutura do YAML, as tabulações do Makefile e qualquer teste que verifique a saída exata.

Renomeações grandes são o outro caso que vale tratar de propósito. Um arquivo movido e editado aparece como uma remoção mais uma adição, a menos que a ferramenta detecte a renomeação, e a flag -M do Git ou uma interface de revisão que reconhece renomeações transforma um diff de mil linhas de volta nas dez linhas que realmente mudaram.

Comparar textos como tarefa editorial

Nem todo diff é de código. Comparar duas versões de um contrato, duas traduções, ou um documento antes e depois de uma edição é um uso comum, e a visão lado a lado existe para isso: você quer ler os dois textos como textos, não como um patch.

Para prosa, o destaque no nível de palavra carrega quase todo o valor, porque uma frase reescrita aparece como uma frase reescrita, e não como uma linha removida e uma adicionada. As ferramentas que fazem isso bem dentro de uma linha são as que as pessoas consideram utilizáveis para trabalho editorial, e é por isso que a comparação aqui roda uma segunda passagem no nível de palavra dentro de cada par alterado.

Duas observações práticas para documentos. Texto colado de um processador de texto costuma trazer aspas curvas, travessões curtos e espaços não separáveis que a outra cópia não tem, então aparecem diferenças onde o texto parece idêntico. E um documento exportado duas vezes da mesma origem pode diferir apenas nas quebras de linha, razão pela qual normalizar os finais de linha antes de comparar poupa muita confusão.

Perguntas frequentes

Como as diferenças são calculadas?
Encontrando a maior subsequência comum de linhas, a mesma ideia por trás do comando diff. Linhas presentes nos dois lados mantêm seu lugar; o resto aparece como adicionado, removido, ou emparelhado como modificação quando uma remoção e uma adição ficam juntas.
Por que palavras individuais são destacadas dentro de uma linha alterada?
Saber que uma linha mudou raramente basta. Uma segunda passagem compara as palavras dentro de cada par modificado, então um único valor alterado em uma linha longa fica óbvio em vez de enterrado.
O que as opções de ignorar fazem?
Ignorar maiúsculas trata maiúsculas e minúsculas como iguais. Ignorar espaços colapsa sequências de espaços e tabulações, útil quando a indentação mudou mas o conteúdo não. Ignorar espaços no fim da linha vem ativado, já que espaço invisível no fim de linha quase nunca é uma diferença real.
Existe limite de tamanho?
A comparação é quadrática no número de linhas diferentes, então trechos idênticos no começo e no fim são pulados primeiro e comparações muito grandes são recusadas em vez de travar a página. Na prática, arquivos de alguns milhares de linhas comparam instantaneamente.
Meu texto é enviado para algum lugar?
Não. As duas versões ficam no seu navegador, o que torna isso seguro para contratos, logs e código não publicado.

Última atualização:

Relatar um problema

Inclua os passos, o resultado esperado e o resultado real. Remova segredos e dados pessoais.

Ferramentas relacionadas