dyff between: Structural YAML Diffs for GitOps
dyff between a.yaml b.yaml prints a structural, key-aware diff of two YAML documents instead of a noisy line diff.
dyff compares YAML/JSON by structure, not by line, so reordered keys do not show as changes. It is the readable diff tool for Helm output and GitOps drift checks.
What it does
dyff between parses two YAML or JSON inputs into their document trees and reports added, removed, and changed paths in a compact human view. Because it diffs the parsed structure, key reordering and formatting differences are ignored, so the output shows only real changes.
Common usage
# structural diff of two manifests
dyff between old.yaml new.yaml
# compare rendered Helm output before/after
helm template ./chart -f old.values.yaml > a.yaml
helm template ./chart -f new.values.yaml > b.yaml
dyff between a.yaml b.yaml
# machine-readable, and treat any change as failure
dyff between --omit-header --set-exit-code a.yaml b.yamlOptions
| Flag | What it does |
|---|---|
| --set-exit-code | Exit non-zero when differences are found |
| --omit-header | Suppress the summary header |
| --ignore-order-changes | Do not report reordered list entries |
| -o human|brief|github | Output style |
| --exclude <path> | Ignore a given path in the comparison |
| -i / --detect-kubernetes | Use Kubernetes resource identifiers for matching |
In CI
Add --set-exit-code so a drift check fails when the live and desired state differ (dyff returns 0 for no changes and non-zero for changes only when that flag is set). Pipe kubectl get -o yaml or Helm output into dyff to gate a GitOps PR on unexpected structural drift.
Common errors in CI
By default dyff exits 0 even when files differ, so a drift gate silently passes; add --set-exit-code. failed to load input file means a path is wrong or the YAML is invalid. unable to parse on Helm output usually means non-YAML lines (NOTES, warnings) leaked into the file; strip them first. command not found: dyff means the binary is not installed.