-
-
Notifications
You must be signed in to change notification settings - Fork 23
yaml merge Hash Options
This document is part of the body of knowledge about yaml-merge, one of the reference command-line tools provided by the YAML Path project.
The yaml-merge
command-line tool enables users to control how it merges Hashes (AKA Maps or Dictionaries). By default, Hashes are deeply merged together with data from the RHS document overriding data in the LHS document wherever both Hashes share structure. Any additional structure in the RHS Hashes is added to the LHS Hashes. The available Hash merge options include:
-
deep
(the default) as described above, every data element in RHS Hashes is merged into LHS Hashes at the same locations. -
left
causes RHS Hashes to be discarded when a Hash already exists at the same location with the LHS document. -
right
causes RHS Hashes to entirely overwrite LHS Hashes at the same location.
Each of these options will be explored in the following sections. All sections will use these two documents for their discussions:
File: LHS.yaml
---
hash:
structure:
with:
several: levels
and:
data: keys
even: more
lhs_exclusive:
key: value
File: RHS.yaml
---
hash:
structure:
with:
several: leaves
having: data
more: structure
even: less
rhs_exclusive:
another_key: another value
In most cases, this is the preferred merge mode for Hashes. For Hashes in the merge documents, these rules apply:
- A Hash in the RHS document but not in the LHS document is added to LHS.
- A Hash in the LHS document but not in the RHS document remains as-is.
- A Hash in both documents is recursively traversed in the RHS document. Any leaf nodes also in LHS are overwritten with RHS data. Any nodes not in LHS are appended to the LHS Hash. Non-Hash leaves in both Hashes are merged according to their own type-specific merge rules.
When the two example documents are merged with --hashes=deep
or -H deep
, the resulting document becomes:
---
hash:
structure:
with:
several: leaves
having: data
and:
data: keys
even: less
more: structure
lhs_exclusive:
key: value
rhs_exclusive:
another_key: another value
If ever you need to prohibit Hashes in RHS documents from merging -- at all -- with LHS Hashes but you want novel Hashes to be added from the RHS document into the LHS document, set --hashes=left
or -H left
. Using the sample documents, this results in the following merged document:
---
hash:
structure:
with:
several: levels
and:
data: keys
even: more
lhs_exclusive:
key: value
rhs_exclusive:
another_key: another value
Notice that the hash
Hash -- which is in both documents at the same location -- is in no way altered during the merge. However, the novel RHS Hash, rhs_exclusive
was appended to the LHS document.
Should you need to completely replace LHS Hashes with their RHS counterparts -- with no merging between them -- set --hashes=right
or -H right
. Using the sample documents, you would generate this result:
---
hash:
structure:
with:
several: leaves
having: data
more: structure
even: less
lhs_exclusive:
key: value
rhs_exclusive:
another_key: another value
Notice that the hash
Hash -- which is in both documents at the same location -- was entirely replaced by the same Hash from the RHS document. Even original nodes from the LHS Hash not present in the RHS Hash were dropped. However, because there is no root-level lhs_exclusive
Hash in the RHS document, it survives the merge.
The yaml-merge
tool can read per YAML Path merging options from an INI-Style configuration file via its --config
(-c
) argument. Whereas the --hashes
(-H
) argument supplies an overarching mode for merging Hashes, using a configuration file permits far more precise control whenever you need a different mode for specific parts of the merge documents.
The [defaults]
section permits a key named, hashes
, which behaves identically to the --hashes
(-H
) command-line argument to the yaml-merge
tool. The [defaults]hashes
setting is overridden by the same-named command-line argument, when supplied. In practice, this file may look like:
File merge-options.ini
[defaults]
hashes = deep
Note the spaces around the =
sign are optional but only an =
sign may be used to separate each key from its value.
The [rules]
section takes any YAML Paths as keys and any of the Hash merge modes that are available to the --hashes
(-H
) command-line argument. This enables extremely fine precision for applying the available modes.
To demonstrate, add this config.ini file along with the sample documents from above:
[rules]
hash.structure.with.several = left
/hash/even = left
All together, the command to execute would become yaml-merge --config=config.ini LHS.yaml RHS.yaml
and the merge output becomes:
---
hash:
structure:
with:
several: levels
having: data
and:
data: keys
even: more
more: structure
lhs_exclusive:
key: value
rhs_exclusive:
another_key: another value
Notice:
- This overrode the default merge mode of
deep
for exactly two Hash nodes. Overall, adeep
merge was still performed. - The
hash.structure.with.several
node becamelevels
from the LHS document rather thanleaves
from the RHS document. - The
/hash/even
node similarly becamemore
rather thanless
.
Any nodes can be targeted with the YAML Paths set in [rules]
. Be sure to specify a correct merge mode for the type of every node that is selected. In other words, don't try to set an Array or Array-of-Hashes exclusive mode to a Hash node. Setting incompatible merge rules will result in an error and cancellation of the merge.