$darkmode
Elektra 0.11.0
How-To: kdb merge

Introduction

The kdb tool allows users to access and perform functions on the Elektra Key Database from the command line. We added a new command to this very useful tool, the merge command. This command allows a user to perform a three-way merge of KeySets from the kdb tool.

The command to use this tool is:

1 kdb merge [options] ourpath theirpath basepath resultpath
2 # RET: 7

The standard naming scheme for a three-way merge consists of ours, theirs, and base:

This works very similarly for KeySets, especially ones that consist of mounted configuration files.

For mounted configuration files:

If the user is just trying to accomplish a three-way merge using any two arbitrary keysets that share a base, it doesn't matter which ones are defined as ours or theirs as long as they use the correct base KeySet. In kdb merge, ourpath, theirpath, and basepath work just like ours, theirs, and base except each one represents the root of a KeySet. The argument resultpath is pretty self-explanatory, it is just where you want the result of the merge to be saved under. It's worth noting, resultpath should be empty before attempting a merge, otherwise there can be unintended consequences.

Options

As for the options, there are two basic options:

Strategies

Additionally, there is an option to specify a merge strategy, which is very important.

The option for strategy is:

The current list of strategies are:

If no strategy is specified, the merge will default to the preserve strategy as to not risk making the wrong decision. If any of the other strategies are specified, when a conflict is detected, merge will use the Key specified by the strategy (ours, theirs, cut or import) for the resulting Key.

Basic Example

Basic Usage:

1 kdb merge system:/hosts/ours system:/hosts/theirs system:/hosts/base system:/hosts/result

Examples Using Strategies

Here are examples of the same KeySets being merged using different strategies. The KeySets are mounted using a property format, the left side of '=' is the name of the Key, the right side is its string value.

We start with the base KeySet, system:/base:

1 key1=1
2 key2=2
3 key3=3
4 key4=4
5 key5=5

Here is our KeySet, system:/ours:

1 key1=apple
2 key2=2
3 key3=3
4 key5=fish

Here is their KeySet, system:/theirs:

1 key1=1
2 key2=pie
3 key4=banana
4 key5=5

To add the keys to the key database, execute the following commands:

1 kdb set user:/tests/base/key1 1
2 #> Create a new key user:/tests/base/key1 with string "1"
3 
4 kdb set user:/tests/base/key2 2
5 #> Create a new key user:/tests/base/key2 with string "2"
6 
7 kdb set user:/tests/base/key3 3
8 #> Create a new key user:/tests/base/key3 with string "3"
9 
10 kdb set user:/tests/base/key4 4
11 #> Create a new key user:/tests/base/key4 with string "4"
12 
13 kdb set user:/tests/base/key5 5
14 #> Create a new key user:/tests/base/key5 with string "5"
15 
16 
17 kdb set user:/tests/ours/key1 apple
18 #> Create a new key user:/tests/ours/key1 with string "apple"
19 
20 kdb set user:/tests/ours/key2 2
21 #> Create a new key user:/tests/ours/key2 with string "2"
22 
23 kdb set user:/tests/ours/key3 3
24 #> Create a new key user:/tests/ours/key3 with string "3"
25 
26 kdb set user:/tests/ours/key5 fish
27 #> Create a new key user:/tests/ours/key5 with string "fish"
28 
29 
30 kdb set user:/tests/theirs/key1 1
31 #> Create a new key user:/tests/theirs/key1 with string "1"
32 
33 kdb set user:/tests/theirs/key2 pie
34 #> Create a new key user:/tests/theirs/key2 with string "pie"
35 
36 kdb set user:/tests/theirs/key4 banana
37 #> Create a new key user:/tests/theirs/key4 with string "banana"
38 
39 kdb set user:/tests/theirs/key5 5
40 #> Create a new key user:/tests/theirs/key5 with string "5"

Now we will examine the result KeySet with the different strategies.

Preserve

1 kdb merge -s preserve user:/tests/ours user:/tests/theirs user:/tests/base user:/tests/result
2 # RET: 11
3 # STDERR: 1 conflicts were detected that could not be resolved automatically:⏎user:/tests/result/key4⏎ours: CONFLICT_DELETE, theirs: CONFLICT_MODIFY⏎⏎Merge unsuccessful.

The merge will fail because of a conflict for key4 since key4 was deleted in our KeySet and edited in their KeySet. Since we used preserve, the merge fails and the result KeySet is not saved.

Ours

1 kdb merge -s ours user:/tests/ours user:/tests/theirs user:/tests/base user:/tests/result

The result KeySet, user:/tests/result will be:

1 kdb ls user:/tests/result
2 #> user:/tests/result/key1
3 #> user:/tests/result/key2
4 #> user:/tests/result/key5

The values of the keys are:

1 kdb get user:/tests/result/key1
2 #> apple
3 
4 kdb get user:/tests/result/key2
5 #> pie
6 
7 kdb get user:/tests/result/key5
8 #> fish

The conflict of key4 (it was deleted in ours but changed in theirs) is solved by using our copy, thus deleting the key.

Now we delete the result keys and try the next merging strategy.

1 kdb rm user:/tests/result/key1
2 kdb rm user:/tests/result/key2
3 kdb rm user:/tests/result/key5

Theirs

1 kdb merge -s theirs user:/tests/ours user:/tests/theirs user:/tests/base user:/tests/result

The result KeySet, user:/tests/result will be:

1 kdb ls user:/tests/result
2 #> user:/tests/result/key1
3 #> user:/tests/result/key2
4 #> user:/tests/result/key4
5 #> user:/tests/result/key5

The values of the keys are:

1 kdb get user:/tests/result/key1
2 #> apple
3 
4 kdb get user:/tests/result/key2
5 #> pie
6 
7 kdb get user:/tests/result/key4
8 #> banana
9 
10 kdb get user:/tests/result/key5
11 #> fish

Here, the conflict of key4 is solved by using their copy, thus key4=banana.

We delete the result keys again and finally try the cut merging strategy.

1 kdb rm user:/tests/result/key1
2 kdb rm user:/tests/result/key2
3 kdb rm user:/tests/result/key4
4 kdb rm user:/tests/result/key5

Cut

1 kdb merge -s cut user:/tests/ours user:/tests/theirs user:/tests/base user:/tests/result

The result KeySet, user:/tests/result will be:

1 kdb ls user:/tests/result
2 #> user:/tests/result/key1
3 #> user:/tests/result/key2
4 #> user:/tests/result/key4
5 #> user:/tests/result/key5

The values of the keys are:

1 kdb get user:/tests/result/key1
2 #> 1
3 
4 kdb get user:/tests/result/key2
5 #> pie
6 
7 kdb get user:/tests/result/key4
8 #> banana
9 
10 kdb get user:/tests/result/key5
11 #> 5

Here the state of theirs is simply copied to the resultpath.

SEE ALSO