YAML Compare

Free + AI

Compare two YAML files as data: keys matched by name, list items matched by an identity field, comments and layout set aside, and every change listed by its path. It runs in your browser.

Why compare YAML as data

YAML is read by indentation, so what a line diff shows and what the file means drift apart quickly. Reorder two keys, rewrite [80, 443] as one item per line, or reword a comment, and a line diff reports changes no program reading the file would notice. Move one line two spaces to the left, and it shows a whitespace edit where the file now says something different.

This page parses both files and compares the values they hold. It opens on two versions of a Kubernetes Deployment in which the keys were reordered, a comment was added and the two containers swapped places. It reports the swap as a move and lists the four edits that change what gets deployed, one of them a port that became a string. Replace either side with your own files: two Spring profiles, two Helm values files, or a CI workflow before and after a change.

What it reports

Containers matched by name

containers:
  - name: web
    image: web:1.4
  - name: sidecar
    image: envoy:1.29
containers:
  - name: sidecar
    image: envoy:1.29
  - name: web
    image: web:1.5

One edit, the web image from web:1.4 to web:1.5, and one move. The list items are matched by name, so the swap is not reported as two containers removed and two added.

Comments and list style set aside

# ports the service listens on
ports: [80, 443]
debug: false
debug: false
# public ports
ports:
  - 80
  - 443

No changes. The comment was reworded, the keys swapped order and the list went from one line to one item per line, but every value is the same.

An indentation slip

spring:
  datasource:
    url: jdbc:postgresql://db:5432/app
    username: app
spring:
  datasource:
    url: jdbc:postgresql://db:5432/app
  username: app

Two changes: /spring/datasource/username removed and /spring/username added. A line diff shows two missing spaces; this shows that the setting left the datasource block, where the application looks for it.

Options

Match lists
Automatic looks for a field that is unique on every item of a list. In Kubernetes files that is usually name, which containers, environment variables and ports all carry. You can name another field, or match by position when the order of the items is the point, as it is for the steps of a CI job.
Ignore a path
Compare a manifest with what kubectl get -o yaml returns and the fields the cluster adds get in the way. Ignore /status, /metadata/managedFields or /metadata/resourceVersion from any change row, and everything under that path stops counting.
Noise
A uid or a creationTimestamp that differs between two exports is labelled noise and counted apart, and so are changed hashes, IP addresses and request IDs.
Compare this block
Select a subtree, such as /spec/template or /spring/datasource, and compare only that part of the two files.
Copy as JSON Patch
The difference as RFC 6902 operations, with paths into the YAML's structure. kubectl patch --type=json accepts this format.

In a terminal

  • diff -u <(yq -P 'sort_keys(..)' old.yaml) <(yq -P 'sort_keys(..)' new.yaml)

    Sorts the keys of every map, so reordered keys stop counting. On this page's sample the added comment still shows, and the two containers that swapped places show as one block removed and the same block added.

  • q='(.. | select(tag == "!!seq")) |= sort_by(.name) | sort_keys(..) | ... comments=""'
    diff -u <(yq -P "$q" old.yaml) <(yq -P "$q" new.yaml)

    Also sorts every list by its name field and drops comments. On this page's sample that leaves exactly the four real edits: replicas, the image tag, the timeout and the port.

What the page does that these do not
Sorting lists by name hides the swap instead of reporting it as a move, would also reorder a list whose order matters, and yq prints "8080" in quotes without saying that the port became a string.
What the terminal does better
It runs unattended in a CI step, where diff exiting with 1 can fail the build when a manifest drifts, and it handles large files: the first command took about 16 seconds on two 8 MB manifests.

These are the Go yq (github.com/mikefarah/yq, version 4). The Python package also called yq takes other arguments: there, yq -S -y . old.yaml sorts the keys and drops comments.

Questions

Why is version: 1.10 the same as version: 1.1?

Unquoted, both are numbers, and 1.10 and 1.1 are the same number, so the data has not changed. If the value is a version, quote it ("1.10"): it is then a string, and changing it to "1.1" is reported. The application reading the file sees the unquoted value the same way this page does.

Why is a reworded comment not reported?

Comments are not part of the data a YAML parser returns, so rewording one is not a change here. To review comment edits as well, press Back to line by line and the same two files are compared as text.

Why does enabled: yes to enabled: true show a type change?

This page reads YAML 1.2, where only true and false are booleans and yes, no, on and off are plain strings. Parsers that follow the older YAML 1.1, including PyYAML and SnakeYAML (which Spring Boot uses), read yes as true, so for them the two lines mean the same. The type change is the page telling you the two versions disagree on that point.

Can it compare a file with several documents?

Not as data yet. A file that holds more than one document separated by ---, as rendered Helm charts and multi-resource manifests often do, is compared line by line, and the page says so. Split the documents and compare them a pair at a time to get the path view.

Are anchors and aliases followed?

Yes. An alias such as *defaults is compared as the value it points to, so changing an anchored value shows up at every place that uses it. A merge key (<<) is compared as an ordinary key rather than merged into its map.

Nothing you type leaves this page

The comparison runs entirely in your browser: nothing is uploaded to compare and no account is needed. The one exception is opt-in and visible. If you press Explain with AI, only the changes you ticked are sent, with secrets, email addresses and phone numbers masked first, and the page shows you the exact text before it goes. The explanation keeps change numbers and its own wording, not your text.

Credits are a licence to use these tools - not money, not transferable. Full detail in our privacy policy and AI policy.