İki YAML dosyasını girinti derdine düşmeden karşılaştırma

İki YAML dosyasını karşılaştırmanın en hızlı yolu, ikisini yan yana bir diff aracına yapıştırmak, girintiyi normalleştirmek ve vurguladığı satırları okumaktır. Karşılaştırma kolay kısımdır. YAML'de gürültü her zamankinden daha sinsidir: yanlış yere düşmüş bir sekme, yeniden sıralanmış bir anahtar veya birinin tırnak içine aldığı bir değer, aynı veriye yüklenen iki dosyayı hiç ortak yanları yokmuş gibi gösterebilir.

Bu rehber, temiz ve güvenilir bir YAML diff'i nasıl alacağınızı anlatır. İki eşdeğer dosyanın kâğıt üzerinde neden ayrıştığına, bilmeye değer yöntemlere ve takip edebileceğiniz çalışılmış bir örneğe bakacağız. Yalnızca aracı istiyorsanız, YAML karşılaştırma sayfamız bunların tümünü tarayıcıda yapar.

YAML dosyaları neden aldatıcı şekilde karşılaştırması zordur

YAML boşluğa duyarlı bir biçimdir (bkz. YAML 1.2.2 belirtimi), ve diff'leri çetrefilli yapan tam da budur. Girinti anlam taşır, ama girintinin miktarı taşımaz, yeterince tutarlı olduğu sürece. Yani iki boşlukla girintilenmiş bir dosya ile dört boşlukla girintilenmiş bir başkası aynı yapıya yüklenirken, bir metin diff'ine her satır farklı görünebilir.

Aklınızda tutmanız gereken anahtar gerçek şu: bir YAML mapping'i anahtar/değer çiftleri kümesidir ve JSON nesneleri gibi, o anahtarların sırası veriyi değiştirmez. Yani bu:

name: Ada Lovelace
role: editor

ve bu:

role: editor
name: Ada Lovelace

bir satır diff'i onları kırmızı ve yeşile boyasa da aynı mapping'e yüklenir. Bir sequence'in öğeleri ise sıralıdır, dolayısıyla bir listeyi yeniden sıralamak gerçek bir değişikliktir.

Değişiklik gibi görünür ama genellikle değildir
Diff'te gördüğünüzGerçek bir değişiklik mi?Ne yapmalı
2 boşluk vs 4 boşluk girintiHayır, yalnızca tutarlılık önemlidirİkisini de aynı genişliğe yeniden biçimlendirin
Mapping anahtarları farklı sıradaHayır, mapping'ler sırasızdırHer iki tarafta anahtarları sıralayın
true vs "true"Evet, boolean vs dizeAraştırın, bu gerçek
name: Ada vs name: "Ada"Hayır, aynı dize değeriTırnakları normalleştirin
Flow stili [a, b] vs blok listeHayır, aynı sequenceİkisi için tek bir stil seçin
Sequence öğeleri farklı sıradaEvet, sequence'ler sıralıdırAraştırın, bu gerçek

Oradaki iki satır gerçek tuzaktır. Tırnaksız true bir boolean'dır; tırnaklı haldeyse "true" dizesidir ve bu ayrım gerçek kesintilere yol açmıştır. Ama name: Ada ile name: "Ada" aynı dizedir. Bir ayrıştırıcının bunu nasıl çözdüğünün ince ayrıntısını isterseniz, belirtimin core schema bölümü başvuru kaynağıdır.

YAML'yi karşılaştırmanın dört yolu ve her birine ne zaman başvurulur

Tek bir en iyi yöntem yoktur. Dosyaların nerede olduğuna ve neyi öğrenmek istediğinize bağlıdır. Yaygın seçenekler şöyle kıyaslanır.

YöntemEn iyisiÇabaYAML'yi anlıyor mu?
Gözle kontrolÇok küçük dosyalar, bir veya iki anahtarDüşükHayır, ayrıştırıcı sizsiniz
Çevrimiçi diff aracıHızlı kontroller, her yerden yapıştırmaDüşükYeniden biçimlendirmeyle, evet
Komut satırı (yq)Diskteki dosyalar, betikleme, anahtar sıralamaOrtaEvet, önce sıralarsanız
IDE veya git diffZaten bir depoda olan dosyalarCommit edilmişse düşükVarsayılan olarak satır tabanlı

Çoğu kişi için bir tarayıcı aracı hızda kazanır: kurulacak hiçbir şey yoktur ve bir parçayı doğrudan bir Kubernetes manifestinden veya bir CI yapılandırmasından yapıştırabilirsiniz. Pürüz, biçimlendirme gürültüsüdür, onu sonra ele alacağız. Terminalde yaşıyorsanız, yq öğrenilecek araçtır ve jq'nun JSON için yaptığı gibi anahtarları sıralayabilir.

En hızlı temiz karşılaştırma, adım adım

Biri bana iki manifest uzatıp "ne farklı?" diye sorduğunda kullandığım rutin budur. Yaklaşık on beş saniye sürer.

  1. YAML karşılaştırma aracını açın.
  2. Orijinali sola, yeni sürümü sağa yapıştırın.
  3. Aynı girintiyi paylaşsınlar diye her iki tarafta Biçimlendir'e tıklayın.
  4. Yeniden sıralanmış mapping anahtarları değişiklik olarak görünmeyi bıraksın diye anahtarları sırala'yı açın.
  5. Sonucu okuyun. Yeşil eklenen, kırmızı kaldırılandır ve değişen bir değer her renkten biri olarak görünür.

Üç ve dördüncü adımlar işin tüm püf noktasıdır. Her iki dosya aynı girintiyi kullanıp anahtarları sıralandığında, vurgulanacak tek şey gerçekte ne değiştiğidir. Diff motorumuz Google'ın diff-match-patch üzerine kuruludur; önce satır satır karşılaştırır, böylece uzun dosyalarda bile hızlı kalır.

Çalışılmış bir örnek

Diyelim ki bir kullanıcı kaydındaki bir değişikliği inceliyorsunuz. İşte öncesi:

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

Ve işte bir takım arkadaşının size verdiği hâliyle sonrası:

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

Bunları ham bir satır diff'ine atın; anahtarlar farklı sırada olduğu için neredeyse her satır yer değiştirmiş gibi görünür. İkisini de yeniden biçimlendirip sıralayın, gerçek hikâye kısadır:

Gerçekte ne değişti
AnahtarÖnceSonraDeğişiklik
roleeditoradminDeğiştirildi
seats35Değiştirildi
teamplatformEklendi
nameAda LovelaceAda LovelaceDeğişiklik yok
activetruetrueDeğişiklik yok (yalnızca taşındı)

Üç gerçek düzenleme: bir rol yükseltmesi, bir koltuk sayısı ve yeni bir team anahtarı. Yeniden sıralama gürültüydü. editor'dan admin'e o terfi, incelemede yakalamak isteyeceğiniz türden bir şeydir ve yanlış pozitiflerin altına gömüldüğünde kaçırması kolaydır.

Komut satırında biçimlendirme gürültüsünü yok etmek

Dosyalarınız zaten diskteyse, aynı "yeniden biçimlendir ve sırala" fikri iki kısa komutla işler. yq anahtarları sıralayıp kanonik bir biçim yeniden üretebilir, böylece sonrasında düz bir diff dürüst olur:

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

Artık diff yalnızca gerçekten değişen değerleri raporlar, çünkü her iki dosya da aynı girintiye ve aynı anahtar sırasına sahiptir. Bu, tarayıcıda Biçimlendir'e ve anahtarları sırala'ya tıklamanın terminal karşılığıdır.

YAML'ye özgü tuzaklar

Birkaç YAML özelliği insanları şaşırtan diff'lere yol açar. Anchors ve aliases (&name ve *name) bir dosyanın bir değeri referansla tekrarlamasına izin verirken başka bir dosya onu tam olarak yazar; ikisi de aynı veriye yüklenir ama tamamen farklı okunur. Meşhur "Norveç sorunu" bir başkasıdır: tırnaksız no, off ve yes eski YAML 1.1 ayrıştırıcılarında boolean olarak çözümlenebilir, dolayısıyla country: NO false olabilir. YAML 1.2 şemayı düzeltti, ama birçok araç hâlâ 1.1 davranışını taşır. Bir değer tür değiştirmiş gibi göründüğünde, ilk kontrol edilecek şey budur.

Dikkat edilecek yaygın çukurlar

ÇukurNeden ısırırÇözüm
Girinti için sekmelerYAML girinti için sekmeleri yasaklar; dosya ayrıştırılmayabilir bileÖnce sekmeleri boşluğa dönüştürün
Tırnaklı vs tırnaksız skalerler"true" bir dizedir, true bir boolean'dırBu gerçek bir değişiklik olabilir, göz ardı etmeyin
Anchors ve aliasesBir dosya değeri satır içine koyar, diğeri ona referans verirAnchors'ı çözün, sonra genişletilmiş biçimi karşılaştırın
Norveç sorununo, YAML 1.1'de false olarak çözümlenebilirBelirsiz dizeleri tırnağa alın; ayrıştırıcı sürümünüzü kontrol edin
Satır sonu boşluğuBir değerden sonraki görünmez boşluklar değişiklik olarak görünürKarşılaştırmadan önce satır sonu boşluğunu kırpın

YAML ve JSON göründüklerinden daha yakındır

Her JSON belgesi geçerli YAML'dir, çünkü YAML 1.2 JSON'un bir üst kümesidir. Karşılaştırma için bu kullanışlıdır: girinti veya anchors size zorluk çıkarıyorsa, her iki dosyayı JSON'a dönüştürün, aynı şekilde biçimlendirin ve onun diff'ini alın. PyYAML dâhil birçok ayrıştırıcı, YAML'yi JSON olarak yeniden üretebileceğiniz düz bir veri yapısına gidip getirir; bu da biçemsel farkları soyup yalnızca veriyi bırakır.

İlgili araçlar

YAML nadiren tek başına gelir. Aynı verinin JSON biçimini karşılaştırıyorsanız, JSON karşılaştırma aynı fikri uygular. Ortam ayarları ve .env dosyaları yapılandırma karşılaştırma sayfasında güzel hizalanır ve iki API çağrısı arasındaki değişiklikleri incelemek API yanıt diff'inin yapıldığı şeydir.

Sık sorulan sorular

YAML dosyalarını çevrimiçi karşılaştırmak onları bir yere yükler mi?
comparetext.org'da diff tarayıcınızda çalışır. İki YAML dosyası kendi makinenizde JavaScript tarafından karşılaştırılır, dolayısıyla Kaydet veya Paylaş'a açıkça tıklamadığınız sürece bir sunucuya hiçbir şey gönderilmez. Bu, Kubernetes manifestleri, CI yapılandırmaları ve her tuş vuruşunda yükleyen bir siteye yapıştırmak istemeyeceğiniz diğer veriler için onu güvenli kılar.
İki YAML dosyam neden her satırı farklı gösteriyor?
Neredeyse her zaman biçimlendirmedir, gerçek değişiklik değil. Bir dosya iki boşlukla, diğeri dörtle girintilenmiştir, ya da mapping anahtarları farklı sıradadır, ya da biri tırnak kullanır diğeri kullanmaz. Her iki tarafı aynı girintiye yeniden biçimlendirin ve sıra önemini yitirsin diye anahtarları sıralayın. Bundan sonra diff genellikle gerçekten değişen birkaç değere küçülür.
YAML karşılaştırırken girinti genişliği önemli mi?
Anlam için değil, yalnızca tutarlılık için. YAML yapıyı göstermek için girinti kullanır, ama her seviye dosya içinde tutarlı olduğu sürece iki ya da dört boşluk kullanmanızı umursamaz. Yani iki boşluklu bir dosya ile dört boşluklu bir dosya aynı veriyi tutarken bir metin diff'ine tamamen farklı görünebilir. İkisini de aynı genişliğe yeniden biçimlendirmek o yanlış farkı kaldırır. Sekmeler ise girinti için hiç izinli değildir.
Anahtar sırasını yok sayarak YAML'yi nasıl karşılaştırırım?
YAML mapping anahtarları sırasızdır, dolayısıyla aynı anahtarları farklı sırada içeren iki dosya aynı veriyi tutar. Bir metin diff'inin de buna katılması için, karşılaştırmadan önce her iki tarafta anahtarları sıralayın. Tarayıcıda anahtarları sırala (kanonikleştir) seçeneğini kullanın. Komut satırında yq bunu sort_keys ile yapar. Her iki dosyanın anahtarları aynı sıralı düzene girdiğinde, yalnızca gerçek değer değişiklikleri görünür. Sequence öğeleri sıralı kalır, dolayısıyla onları sıralamayın.
YAML'de Norveç sorunu nedir?
Tırnaksız NO değerinin "NO" dizesi yerine boolean false olarak çözümlenip Norveç ülke kodunun false olduğu klasik bir YAML tuzağıdır. Bu, yes, no, on ve off'u boolean olarak ele alan YAML 1.1 ayrıştırıcılarında olur. YAML 1.2 kuralları daralttı, ama birçok araç hâlâ 1.1 davranışını taşır. Diff'inizde bir değer bir sözcükten true ya da false'a dönmüş gibi görünüyorsa, tırnaksız boolean benzeri bir dize olası nedendir. Değeri tırnağa almak sorunu giderir.
Sayfa donmadan büyük YAML dosyalarını karşılaştırabilir miyim?
Evet, belli bir noktaya kadar. Satır modu diff, her karakter yerine önce tüm satırları karşılaştırdığı için binlerce satırlık dosyalarda hızlı kalır. Çok büyük dosyalar (birkaç megabayt) veriyi akıtan yq veya git diff gibi bir komut satırı aracıyla daha iyi ele alınır. Bir tarayıcıda rahatça kaydırabileceğiniz her şey için çevrimiçi bir diff daha hızlı seçenektir.

Denemeye hazır mısınız? Dosyalarınızı YAML karşılaştırma aracına yapıştırın ve neyin değiştiğini görün.