Como comparar dois arquivos YAML sem sofrer com a indentação

A forma mais rápida de comparar dois arquivos YAML é colar ambos em uma ferramenta de diff lado a lado, normalizar a indentação e ler as linhas que ela destaca. A comparação é a parte fácil. Com YAML, o ruído é mais traiçoeiro do que o normal: uma tabulação perdida, uma chave reordenada ou um valor que alguém envolveu em aspas podem fazer dois arquivos que carregam os mesmos dados parecerem não ter nada em comum.

Este guia explica como obter um diff de YAML limpo e confiável. Vamos ver por que dois arquivos equivalentes se distanciam no papel, quais métodos vale a pena conhecer e um exemplo prático que você pode seguir. Se você só quer a ferramenta, nossa página de comparação YAML faz tudo isso no navegador.

Por que arquivos YAML são enganosamente difíceis de comparar

YAML é um formato sensível a espaços em branco (veja a especificação YAML 1.2.2), e é exatamente isso que torna os diffs complicados. A indentação carrega significado, mas a quantidade de indentação não, desde que seja consistente. Assim, um arquivo indentado com dois espaços e outro com quatro podem carregar a estrutura idêntica enquanto cada linha parece diferente para um diff de texto.

Aqui está o fato-chave a guardar: um mapping YAML é um conjunto de pares chave/valor e, como os objetos JSON, a ordem dessas chaves não muda os dados. Então isto:

name: Ada Lovelace
role: editor

e isto:

role: editor
name: Ada Lovelace

carregam o mesmo mapping, mesmo que um diff de linhas os pinte de vermelho e verde. Os itens de uma sequência, por outro lado, são ordenados, então reordenar uma lista é uma mudança real.

Parece uma mudança, mas quase nunca é
O que você vê no diffÉ uma mudança real?O que fazer
Indentação de 2 vs 4 espaçosNão, só a consistência importaReformate ambos para a mesma largura
Chaves de mapping em ordem diferenteNão, mappings não têm ordemOrdene as chaves dos dois lados
true vs "true"Sim, boolean vs stringInvestigue, isso é real
name: Ada vs name: "Ada"Não, mesmo valor de stringNormalize as aspas
Estilo flow [a, b] vs lista em blocoNão, mesma sequênciaEscolha um estilo para ambos
Itens de sequência em ordem diferenteSim, sequências são ordenadasInvestigue, isso é real

Duas linhas ali são armadilhas genuínas. true sem aspas é um boolean; com aspas é a string "true", e essa distinção já causou quedas reais. Mas name: Ada e name: "Ada" são a mesma string. Se você quer o detalhe técnico de como um parser resolve isso, a seção da especificação sobre o core schema é a referência.

Quatro formas de comparar YAML e quando usar cada uma

Não existe um único método melhor. Depende de onde estão os arquivos e o que você quer descobrir. Veja como as opções comuns se comparam.

MétodoMelhor paraEsforçoEntende YAML?
Conferência visualArquivos minúsculos, uma ou duas chavesBaixoNão, você é o parser
Ferramenta de diff onlineVerificações rápidas, colar de qualquer lugarBaixoCom reformatação, sim
Linha de comando (yq)Arquivos em disco, scripting, ordenar chavesMédioSim, quando você ordena primeiro
IDE ou git diffArquivos já em um repositórioBaixo se commitadoBaseado em linhas por padrão

Para a maioria das pessoas, uma ferramenta de navegador ganha na velocidade: nada para instalar, e você pode colar um fragmento direto de um manifesto Kubernetes ou uma config de CI. O problema é o ruído de formatação, que tratamos a seguir. Se você vive no terminal, yq é a ferramenta a aprender, e ela pode ordenar chaves do mesmo jeito que o jq faz para JSON.

A comparação limpa mais rápida, passo a passo

Esta é a rotina que uso quando alguém me entrega dois manifestos e pergunta "o que está diferente?" Leva cerca de quinze segundos.

  1. Abra a ferramenta de comparação YAML.
  2. Cole o original à esquerda e a nova versão à direita.
  3. Clique em Formatar nos dois lados para que compartilhem a mesma indentação.
  4. Ative ordenar chaves para que as chaves de mapping reordenadas parem de aparecer como mudanças.
  5. Leia o resultado. Verde é adicionado, vermelho é removido, e um valor alterado aparece como um de cada cor.

Os passos três e quatro são todo o truque. Quando ambos os arquivos usam a mesma indentação e suas chaves estão ordenadas, a única coisa que resta para destacar é o que de fato mudou. Nosso motor de diff é construído sobre o diff-match-patch do Google, que compara linha por linha primeiro para se manter rápido mesmo em arquivos longos.

Um exemplo prático

Digamos que você esteja revisando uma mudança em um registro de usuário. Aqui está o antes:

name: Ada Lovelace
role: editor
active: true
seats: 3

E aqui está o depois, como um colega de equipe entregou a você:

active: true
name: Ada Lovelace
role: admin
seats: 5
team: platform

Coloque esses em um diff de linhas cru e parece que quase toda linha se moveu, porque as chaves estão em ordem diferente. Reformate e ordene ambos, e a história real é curta:

O que realmente mudou
ChaveAntesDepoisMudança
roleeditoradminModificado
seats35Modificado
teamplatformAdicionado
nameAda LovelaceAda LovelaceSem mudança
activetruetrueSem mudança (só moveu)

Três edições reais: uma promoção de papel, uma contagem de assentos e uma nova chave de equipe. A reordenação era ruído. Essa promoção de editor para admin é exatamente o tipo de coisa que você quer pegar na revisão, e é fácil de passar despercebida quando está enterrada sob falsos positivos.

Eliminando o ruído de formatação na linha de comando

Se seus arquivos já estão em disco, a mesma ideia de "reformatar e ordenar" funciona com dois comandos curtos. yq pode ordenar chaves e reemitir uma forma canônica, então um diff simples depois é honesto:

yq -P 'sort_keys(..)' old.yaml > old.sorted.yaml
yq -P 'sort_keys(..)' new.yaml > new.sorted.yaml
diff old.sorted.yaml new.sorted.yaml

Agora o diff só relata valores que realmente mudaram, porque ambos os arquivos têm a mesma indentação e a mesma ordem de chaves. Este é o equivalente no terminal de clicar em Formatar e ordenar chaves no navegador.

As armadilhas exclusivas do YAML

Alguns recursos do YAML causam diffs que surpreendem as pessoas. Anchors e aliases (&name e *name) permitem que um arquivo repita um valor por referência enquanto outro o escreve por completo; ambos carregam os mesmos dados, mas se leem de forma totalmente diferente. O infame "problema da Noruega" é outro: no, off e yes sem aspas podem ser parseados como booleans em parsers antigos de YAML 1.1, então country: NO pode virar false. O YAML 1.2 corrigiu o schema, mas muitas ferramentas ainda trazem o comportamento de 1.1. Quando um valor parece ter mudado de tipo, é a primeira coisa a verificar.

Pegadinhas comuns para ficar de olho

PegadinhaPor que mordeCorreção
Tabulações para indentaçãoYAML proíbe tabulações para indentação; o arquivo pode nem ser parseadoConverta tabulações em espaços primeiro
Escalares com ou sem aspas"true" é uma string, true é um booleanPode ser uma mudança real, não descarte
Anchors e aliasesUm arquivo coloca o valor inline, o outro o referenciaResolva os anchors e então compare a forma expandida
O problema da Noruegano pode ser parseado como false em YAML 1.1Coloque aspas em strings ambíguas; verifique a versão do seu parser
Espaço em branco no fim da linhaEspaços invisíveis após um valor aparecem como mudançaRemova o espaço em branco final antes de comparar

YAML e JSON são mais próximos do que parecem

Todo documento JSON é YAML válido, porque YAML 1.2 é um superconjunto de JSON. Isso é útil para comparar: se a indentação ou os anchors estão te atrapalhando, converta ambos os arquivos para JSON, formate-os do mesmo jeito e faça o diff disso. Muitos parsers, incluindo o PyYAML, fazem round-trip do YAML para uma estrutura de dados simples que você pode reemitir como JSON, o que remove as diferenças de estilo e deixa só os dados.

Ferramentas relacionadas

YAML raramente viaja sozinho. Se você está comparando a forma JSON dos mesmos dados, comparar JSON aplica a mesma ideia. Configurações de ambiente e arquivos .env se alinham bem na página de comparação de configuração, e revisar mudanças entre duas chamadas de API é para o que o diff de respostas de API foi feito.

Perguntas frequentes

Comparar arquivos YAML online os envia para algum lugar?
No comparetext.org o diff roda no seu navegador. Os dois arquivos YAML são comparados por JavaScript na sua própria máquina, então nada é enviado a um servidor a menos que você clique explicitamente em Salvar ou Compartilhar. Isso o torna seguro para manifestos Kubernetes, configs de CI e outros dados que você não gostaria de colar em um site que envia tudo a cada tecla.
Por que meus dois arquivos YAML mostram cada linha como diferente?
Quase sempre é formatação, não mudanças reais. Um arquivo está indentado com dois espaços, o outro com quatro, ou as chaves do mapping estão em ordem diferente, ou um usa aspas e o outro não. Reformate ambos os lados para a mesma indentação e ordene as chaves para que a ordem pare de importar. Depois disso, o diff geralmente encolhe para o punhado de valores que realmente mudaram.
A largura da indentação importa ao comparar YAML?
Não para o significado, só para a consistência. YAML usa indentação para mostrar a estrutura, mas não se importa se você usa dois ou quatro espaços, desde que cada nível seja consistente dentro do arquivo. Assim, um arquivo de dois espaços e um de quatro podem conter dados idênticos enquanto parecem totalmente diferentes para um diff de texto. Reformatar ambos para a mesma largura remove essa diferença falsa. Tabulações, porém, não são permitidas para indentação de jeito nenhum.
Como comparo YAML ignorando a ordem das chaves?
As chaves de mapping YAML não têm ordem, então dois arquivos com as mesmas chaves em ordem diferente contêm os mesmos dados. Para que um diff de texto concorde, ordene as chaves dos dois lados antes de comparar. No navegador, use a opção de ordenar chaves (canonicalizar). Na linha de comando, o yq faz isso com sort_keys. Quando ambos os arquivos têm as chaves na mesma ordem ordenada, só aparecem mudanças de valores reais. Itens de sequência mantêm a ordem, então não os ordene.
O que é o problema da Noruega em YAML?
É uma pegadinha clássica do YAML em que o valor sem aspas NO é parseado como o boolean false em vez da string "NO", então um código de país para a Noruega vira false. Acontece em parsers de YAML 1.1, que tratam yes, no, on e off como booleans. O YAML 1.2 estreitou as regras, mas muitas ferramentas ainda trazem o comportamento de 1.1. Se um valor parece ter mudado de uma palavra para true ou false no seu diff, uma string parecida com boolean sem aspas é a causa provável. Colocar aspas no valor resolve.
Posso comparar arquivos YAML grandes sem a página travar?
Sim, até certo ponto. Um diff em modo de linhas se mantém rápido em arquivos com milhares de linhas porque compara linhas inteiras primeiro em vez de cada caractere. Arquivos muito grandes (vários megabytes) são melhor tratados com uma ferramenta de linha de comando como yq ou git diff, que faz streaming dos dados. Para qualquer coisa que você consiga rolar confortavelmente em um navegador, um diff online é a opção mais rápida.

Pronto para experimentar? Cole seus arquivos na ferramenta de comparação YAML e veja o que mudou.