Zwei YAML-Dateien vergleichen, ohne an der Einrückung zu scheitern
Der schnellste Weg, zwei YAML-Dateien zu vergleichen, besteht darin, beide in ein nebeneinander angeordnetes Diff-Tool einzufügen, die Einrückung zu normalisieren und die hervorgehobenen Zeilen zu lesen. Das Vergleichen ist der einfache Teil. Bei YAML ist das Rauschen tückischer als üblich: ein versehentlicher Tab, ein umgeordneter Schlüssel oder ein von jemandem in Anführungszeichen gesetzter Wert können dazu führen, dass zwei Dateien, die zu denselben Daten laden, aussehen, als hätten sie nichts gemeinsam.
Dieser Leitfaden zeigt, wie man einen sauberen, zuverlässigen YAML-Diff erhält. Wir schauen uns an, warum zwei gleichwertige Dateien auf dem Papier auseinanderdriften, welche Methoden es wert sind, gekannt zu werden, und ein ausgearbeitetes Beispiel, dem man folgen kann. Wer einfach nur das Tool möchte, kann auf unserer YAML-Vergleichsseite all das im Browser erledigen.
Warum YAML-Dateien trügerisch schwer zu vergleichen sind
YAML ist ein leerzeichensensitives Format (siehe die YAML-1.2.2-Spezifikation), und genau das macht Diffs knifflig. Einrückung trägt Bedeutung, aber die Menge der Einrückung nicht, solange sie konsistent ist. So können eine mit zwei Leerzeichen eingerückte Datei und eine andere mit vier zur identischen Struktur laden, während jede Zeile für einen Textdiff anders aussieht.
Hier ist die zentrale Tatsache, die man behalten sollte: Ein YAML-Mapping ist eine Menge von Schlüssel/Wert-Paaren, und wie bei JSON-Objekten ändert die Reihenfolge dieser Schlüssel die Daten nicht. Also dies:
name: Ada Lovelace
role: editor
und dies:
role: editor
name: Ada Lovelace
laden zum selben Mapping, auch wenn ein Zeilendiff sie rot und grün malt. Die Elemente einer Sequenz hingegen sind geordnet, also ist das Umordnen einer Liste eine echte Änderung.
| Was man im Diff sieht | Ist es eine echte Änderung? | Was zu tun ist |
|---|---|---|
| 2-Leerzeichen- vs. 4-Leerzeichen-Einrückung | Nein, nur die Konsistenz zählt | Beide auf die gleiche Breite umformatieren |
| Mapping-Schlüssel in anderer Reihenfolge | Nein, Mappings sind ungeordnet | Schlüssel auf beiden Seiten sortieren |
true vs. "true" | Ja, boolean vs. String | Untersuchen, das ist real |
name: Ada vs. name: "Ada" | Nein, gleicher String-Wert | Anführungszeichen normalisieren |
Flow-Stil [a, b] vs. Block-Liste | Nein, gleiche Sequenz | Einen Stil für beide wählen |
| Sequenz-Elemente in anderer Reihenfolge | Ja, Sequenzen sind geordnet | Untersuchen, das ist real |
Zwei Zeilen dort sind echte Fallen. true ohne Anführungszeichen ist
ein boolean; mit Anführungszeichen ist es der String "true", und diese
Unterscheidung hat echte Ausfälle verursacht. Aber name: Ada und
name: "Ada" sind derselbe String. Wer die technischen Details dazu
nachlesen möchte, wie ein Parser das auflöst, findet im Abschnitt der Spezifikation
über das core schema
die Referenz.
Vier Methoden zum Vergleichen von YAML und wann man zu welcher greift
Es gibt keine einzige beste Methode. Es hängt davon ab, wo die Dateien liegen und was man herausfinden möchte. So schneiden die gängigen Optionen ab.
| Methode | Am besten für | Aufwand | Versteht YAML? |
|---|---|---|---|
| Manuell durchlesen | Winzige Dateien, ein oder zwei Schlüssel | Gering | Nein, man ist der Parser |
| Online-Diff-Tool | Schnelle Prüfungen, Einfügen von überall | Gering | Mit Umformatierung ja |
Befehlszeile (yq) | Dateien auf der Festplatte, Scripting, Schlüssel sortieren | Mittel | Ja, wenn man zuerst sortiert |
IDE oder git diff | Dateien bereits in einem Repository | Gering bei Commits | Standardmäßig zeilenbasiert |
Für die meisten Menschen gewinnt ein Browser-Tool an Geschwindigkeit: nichts zu installieren, und man kann einen Ausschnitt direkt aus einem Kubernetes-Manifest oder einer CI-Konfiguration einfügen. Der Haken ist Formatierungsrauschen, das wir als Nächstes behandeln. Wer viel im Terminal arbeitet, sollte yq kennenlernen, das Schlüssel auf dieselbe Weise sortieren kann, wie es jq für JSON tut.
Der schnellste saubere Vergleich, Schritt für Schritt
Das ist die Vorgehensweise, die ich verwende, wenn mir jemand zwei Manifeste gibt und fragt: "Was ist anders?" Es dauert etwa fünfzehn Sekunden.
- Das YAML-Vergleichstool öffnen.
- Das Original links einfügen, die neue Version rechts.
- Auf beiden Seiten auf Formatieren klicken, damit sie die gleiche Einrückung verwenden.
- Schlüssel sortieren aktivieren, damit umgeordnete Mapping-Schlüssel nicht mehr als Änderungen erscheinen.
- Das Ergebnis lesen. Grün bedeutet hinzugefügt, rot bedeutet entfernt, und ein geänderter Wert erscheint als eines von beidem.
Schritt drei und vier sind der eigentliche Trick. Sobald beide Dateien die gleiche Einrückung verwenden und ihre Schlüssel sortiert sind, bleibt nur noch hervorgehoben, was sich tatsächlich geändert hat. Unser Diff-Engine basiert auf Googles diff-match-patch, das zuerst zeilenweise vergleicht und so auch bei langen Dateien schnell bleibt.
Ein ausgearbeitetes Beispiel
Angenommen, man prüft eine Änderung an einem Benutzerdatensatz. Hier ist der Vorher-Stand:
name: Ada Lovelace
role: editor
active: true
seats: 3
Und hier ist der Nachher-Stand, wie ein Teammitglied ihn übergeben hat:
active: true
name: Ada Lovelace
role: admin
seats: 5
team: platform
Wirft man diese in einen einfachen Zeilendiff, sieht es aus, als hätte sich fast jede Zeile verschoben, weil die Schlüssel in anderer Reihenfolge sind. Formatiert und sortiert man beide, ist die eigentliche Geschichte kurz:
| Schlüssel | Vorher | Nachher | Änderung |
|---|---|---|---|
role | editor | admin | Geändert |
seats | 3 | 5 | Geändert |
team | — | platform | Hinzugefügt |
name | Ada Lovelace | Ada Lovelace | Keine Änderung |
active | true | true | Keine Änderung (nur verschoben) |
Drei echte Bearbeitungen: eine Rollenerhöhung, eine Sitzanzahl und ein neuer
Team-Schlüssel. Die Umsortierung war Rauschen. Diese Beförderung von
editor zu admin ist genau die Art von Sache, die man im
Review erkennen möchte, und sie ist leicht zu übersehen, wenn sie unter falschen
Positivmeldungen vergraben ist.
Formatierungsrauschen in der Befehlszeile beseitigen
Wenn die Dateien bereits auf der Festplatte liegen, funktioniert die gleiche
"Umformatieren und Sortieren"-Idee mit zwei kurzen Befehlen. yq kann
Schlüssel sortieren und eine kanonische Form neu ausgeben, sodass ein einfacher
Diff danach ehrlich ist:
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
Jetzt meldet diff nur noch Werte, die sich wirklich geändert haben,
weil beide Dateien die gleiche Einrückung und die gleiche Schlüsselreihenfolge
haben. Das ist das Terminal-Äquivalent zu Formatieren und Schlüssel sortieren im
Browser.
Die Fallstricke, die nur YAML kennt
Einige YAML-Funktionen verursachen Diffs, die Leute überraschen. Anchors und
aliases (&name und *name) lassen eine Datei einen
Wert per Referenz wiederholen, während eine andere ihn vollständig ausschreibt;
beide laden zu denselben Daten, lesen sich aber völlig unterschiedlich. Das
berüchtigte "Norwegen-Problem" ist ein weiteres: no, off
und yes ohne Anführungszeichen können in älteren YAML-1.1-Parsern als
booleans interpretiert werden, sodass country: NO zu
false werden könnte. YAML 1.2 hat das Schema korrigiert, aber viele
Tools bringen weiterhin das 1.1-Verhalten mit. Wenn ein Wert aussieht, als hätte er
den Typ gewechselt, ist das das Erste, was man prüfen sollte.
Häufige Stolperfallen, auf die man achten sollte
| Stolperfalle | Warum sie zuschlägt | Lösung |
|---|---|---|
| Tabs für die Einrückung | YAML verbietet Tabs für die Einrückung; die Datei lässt sich womöglich nicht einmal parsen | Tabs zuerst in Leerzeichen umwandeln |
| Skalare mit oder ohne Anführungszeichen | "true" ist ein String, true ist ein boolean | Das kann eine echte Änderung sein, nicht abtun |
| Anchors und aliases | Eine Datei setzt den Wert inline, die andere referenziert ihn | Anchors auflösen, dann die expandierte Form vergleichen |
| Das Norwegen-Problem | no kann in YAML 1.1 als false geparst werden | Mehrdeutige Strings in Anführungszeichen setzen; Parser-Version prüfen |
| Nachgestellte Leerzeichen | Unsichtbare Leerzeichen nach einem Wert erscheinen als Änderung | Nachgestellte Leerzeichen vor dem Vergleich entfernen |
YAML und JSON sind enger verwandt, als sie aussehen
Jedes JSON-Dokument ist gültiges YAML, weil YAML 1.2 eine Obermenge von JSON ist. Das ist praktisch zum Vergleichen: Wenn die Einrückung oder die anchors einem zu schaffen machen, konvertiert man beide Dateien zu JSON, formatiert sie gleich und vergleicht das stattdessen. Viele Parser, darunter PyYAML, machen einen Round-Trip von YAML zu einer einfachen Datenstruktur, die man als JSON neu ausgeben kann, was die stilistischen Unterschiede entfernt und nur die Daten übrig lässt.
Verwandte Tools
YAML reist selten allein. Wenn man die JSON-Form derselben Daten vergleicht, wendet
JSON-Vergleich dieselbe Idee an.
Umgebungseinstellungen und .env-Dateien passen gut auf die
Konfigurations-Vergleichsseite, und Änderungen
zwischen zwei API-Aufrufen zu überprüfen ist genau das, wofür
das API-Antwort-Diff gebaut wurde.
Häufig gestellte Fragen
- Werden YAML-Dateien beim Online-Vergleich irgendwo hochgeladen?
- Auf comparetext.org läuft der Diff im Browser. Die beiden YAML-Dateien werden von JavaScript auf dem eigenen Computer verglichen, sodass nichts an einen Server gesendet wird, es sei denn, man klickt ausdrücklich auf Speichern oder Teilen. Das macht es sicher für Kubernetes-Manifeste, CI-Konfigurationen und andere Daten, die man nicht auf einer Website einfügen möchte, die bei jedem Tastendruck hochlädt.
- Warum zeigen meine zwei YAML-Dateien jede Zeile als unterschiedlich an?
- Fast immer ist es Formatierung, keine echten Änderungen. Eine Datei ist mit zwei Leerzeichen eingerückt, die andere mit vier, oder die Mapping-Schlüssel sind in anderer Reihenfolge, oder eine verwendet Anführungszeichen und die andere nicht. Beide Seiten auf die gleiche Einrückung umformatieren und die Schlüssel sortieren, damit die Reihenfolge keine Rolle mehr spielt. Danach schrumpft der Diff meist auf die wenigen Werte, die sich wirklich geändert haben.
- Spielt die Einrückungsbreite beim Vergleichen von YAML eine Rolle?
- Nicht für die Bedeutung, nur für die Konsistenz. YAML nutzt die Einrückung, um die Struktur zu zeigen, aber es ist egal, ob man zwei oder vier Leerzeichen verwendet, solange jede Ebene innerhalb der Datei konsistent ist. So können eine Zwei-Leerzeichen-Datei und eine Vier-Leerzeichen-Datei identische Daten enthalten und für einen Textdiff trotzdem völlig verschieden aussehen. Beide auf die gleiche Breite umzuformatieren entfernt diesen falschen Unterschied. Tabs sind für die Einrückung jedoch überhaupt nicht erlaubt.
- Wie vergleiche ich YAML und ignoriere dabei die Schlüsselreihenfolge?
- YAML-Mapping-Schlüssel sind ungeordnet, also enthalten zwei Dateien mit denselben Schlüsseln in anderer Reihenfolge dieselben Daten. Damit ein Textdiff zustimmt, sortiere man die Schlüssel vor dem Vergleich auf beiden Seiten. Im Browser die Option Schlüssel sortieren (kanonisieren) verwenden. In der Befehlszeile erledigt das yq mit sort_keys. Sobald beide Dateien Schlüssel in derselben sortierten Reihenfolge haben, erscheinen nur noch echte Wertänderungen. Sequenz-Elemente bleiben geordnet, also nicht sortieren.
- Was ist das Norwegen-Problem in YAML?
- Es ist ein klassischer YAML-Stolperstein, bei dem der Wert NO ohne Anführungszeichen als boolean false statt als String "NO" geparst wird, sodass ein Ländercode für Norwegen zu false wird. Es passiert in YAML-1.1-Parsern, die yes, no, on und off als booleans behandeln. YAML 1.2 hat die Regeln verengt, aber viele Tools bringen weiterhin das 1.1-Verhalten mit. Wenn ein Wert in deinem Diff von einem Wort zu true oder false gewechselt zu sein scheint, ist ein boolean-ähnlicher String ohne Anführungszeichen die wahrscheinliche Ursache. Den Wert in Anführungszeichen zu setzen behebt es.
- Kann ich große YAML-Dateien vergleichen, ohne dass die Seite einfriert?
- Ja, bis zu einem gewissen Punkt. Ein zeilenbasierter Diff bleibt bei Dateien mit Tausenden von Zeilen schnell, weil er zunächst ganze Zeilen statt jedes einzelnen Zeichens vergleicht. Sehr große Dateien (mehrere Megabyte) lassen sich besser mit einem Befehlszeilentool wie yq oder git diff bearbeiten, das die Daten streamt. Für alles, was man bequem in einem Browser durchscrollen kann, ist ein Online-Diff die schnellere Option.
Bereit, es auszuprobieren? Dateien in das YAML-Vergleichstool einfügen und sehen, was sich geändert hat.