# Deep-merge YAML documents with Helm-style overrides

Deep-merge YAML documents left-to-right with Helm-style overrides. Choose array strategy, precedence, null deletion, key sorting and indentation.

## Run it

- **CLI:** `gizza tool yaml-deep-merge 'image:
  repository: app
  tag: "1.0"
replicas: 1
service:
  ports:
    - 80
---
image:
  tag: "2.0"
service:
  ports:
    - 443'`
- **Web:** https://gizza.ai/tools/yaml-deep-merge/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/yaml-deep-merge/tool.json

## Inputs

- `documents` — YAML documents _(field)_
- `precedence` — Conflict precedence _(field)_
- `object_merge` — Object merge _(field)_
- `array_merge` — Array merge _(field)_
- `array_key` — Array item key _(field)_
- `null_deletes` — Null deletes keys _(field)_
- `sort_keys` — Sort keys A-Z _(field)_
- `indent` — Indent spaces _(field)_

## Output

- Merged YAML (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `documents` — YAML documents
- `precedence` — Conflict precedence
- `object_merge` — Object merge
- `array_merge` — Array merge
- `array_key` — Array item key
- `null_deletes` — Null deletes keys
- `sort_keys` — Sort keys A-Z
- `indent` — Indent spaces

Example: `https://gizza.ai/tools/yaml-deep-merge/?documents=image%3A%0A%20%20repository%3A%20app%0A%20%20tag%3A%20%221.0%22%0Areplicas%3A%201%0Aservice%3A%0A%20%20ports%3A%0A%20%20%20%20-%2080%0A---%0Aimage%3A%0A%20%20tag%3A%20%222.0%22%0Aservice%3A%0A%20%20ports%3A%0A%20%20%20%20-%20443&precedence=last&object_merge=deep&array_merge=replace&array_key=name&null_deletes=true&sort_keys=true&indent=2`

---

## About this tool

This tool deep-merges multiple YAML documents into one YAML result. Paste a
`---`-separated stream the same way you would layer several Helm values files:
the first document is the base, each later document overrides it, and the merged
YAML is produced locally in your browser.

The default mode matches the common Helm mental model:

- mappings merge recursively;
- when two scalar values conflict, the later document wins;
- arrays are replaced by the later document;
- a key set to `null` in a later document deletes that key.

Those defaults are useful for Kubernetes and application config, but the controls
let you choose stricter or more expansive behavior. Use **Conflict precedence**
to keep the first value or reject conflicts, **Array merge** to append or merge
lists, **Array item key** to line up object-list entries such as containers or
environment variables by `name`, and **Sort keys A-Z** when you want a stable
alphabetized output for diffs.

### Worked example

Input:

```yaml
image:
  repository: app
  tag: "1.0"
replicas: 1
service:
  ports:
    - 80
---
image:
  tag: "2.0"
service:
  ports:
    - 443
```

Merged result with defaults:

```yaml
image:
  repository: app
  tag: "2.0"
replicas: 1
service:
  ports:
    - 443
```

`image.repository` stays from the base document, `image.tag` is overridden by the
second document, and `service.ports` is replaced because Helm-style array merging
uses replacement by default.

### Array merge modes

- **Replace arrays** keeps the winning document's list. This is the default and
  matches Helm values layering.
- **Append arrays** concatenates the base list and override list.
- **Append unique items** concatenates, then removes duplicate YAML values while
  preserving first-seen order.
- **Merge object lists by key** lines up mapping items whose `array_key` field
  matches, then deep-merges those pairs. The default key is `name`, which fits
  Kubernetes-style `env`, `containers`, and similar lists.

### Limits and edge cases

- Input is capped at **1 MiB** and **20 YAML documents** per merge.
- The output is canonical YAML, not a byte-for-byte patch. Comments, blank-line
  layout, tags, and anchors are not preserved by the YAML value model.
- Empty documents are ignored, just like empty values files.
- `null` deletes keys only when **Null deletes keys** is enabled. Turn it off when
  you need `key: null` to remain in the final YAML.
- **Error on conflict** reports the key path that disagreed. Identical values and
  newly added keys are still allowed.
- **Shallow top-level merge** replaces entire nested subtrees below a top-level
  key instead of recursively merging them.

## FAQ

<details>
<summary>Does this match Helm values file merging?</summary>

The defaults are intentionally Helm-like for day-to-day values files: later
layers win, mappings merge recursively, lists are replaced, and `null` removes a
key. Helm has additional chart-specific behavior outside raw YAML values, but for
plain layered values documents this tool mirrors the rules most people need to
preview.

</details>

<details>
<summary>How do I merge Kubernetes lists such as containers or env vars?</summary>

Choose **Merge object lists by key** and leave **Array item key** as `name` for
common Kubernetes lists. Items with the same `name` are deep-merged, unmatched
items are kept in order, and items without that key are appended because there is
nothing safe to line up.

</details>

<details>
<summary>Why did my comments or anchors disappear?</summary>

The merge operates on parsed YAML values, not source spans. Comments, blank-line
layout, custom tags, and anchor names are not part of that value tree, so the
result is re-emitted as canonical YAML. This makes the merge deterministic but
not comment-preserving.

</details>

<details>
<summary>What happens if two documents disagree on the same value?</summary>

By default the later document wins. Set **Conflict precedence** to **First
document wins** to keep the base value, or **Error on conflict** to reject any
non-identical scalar/list disagreement and report the YAML path that conflicted.

</details>

<details>
<summary>Can I merge more than two YAML files?</summary>

Yes. Paste them into one stream separated by lines containing `---`. The tool
merges left-to-right, so each later document is applied on top of the accumulated
result. The current limit is 20 documents and 1 MiB total input.

</details>

## Related tools

- [Config Merge Tool](https://gizza.ai/tools/config-merge/): Merge layered JSON, YAML, TOML and .env configuration files with override precedence, array strategy, null deletion and variable substitution.
- [Absolute value, sign, or negation for a whole column](https://gizza.ai/tools/absolute-value-transformer/): Paste a column of numbers and apply absolute value, sign extraction (-1/0/1), sign flipping, or force-negative to every value at once, with rounding and an audit table.
- [Adjacency Matrix Converter](https://gizza.ai/tools/adjacency-matrix-converter/): Convert a graph between edge list, adjacency matrix, and incidence matrix — directed or undirected, weighted or not. Free, private, runs in your browser.
- [Amazon Order Analyzer](https://gizza.ai/tools/amazon-order-analyzer/): Paste an Amazon order-history CSV export to summarize total spend by month, top items, and category breakdowns. Browser-only, private, with Markdown or JSON output.
- [ARFF Converter](https://gizza.ai/tools/arff-converter/): Convert Weka ARFF datasets to CSV and CSV tables back to ARFF locally — nominal attributes, numeric types, dates, sparse rows, missing values, and type rows.
