I can't get a usable result with 3-way diffing/merging and I'm starting to believe
that it's not really usable for automatic updating of configuration files due to the
nature of the whole 3-way diffing thing... I conclude that 3-way diffing was designed
to merge differences, not similarities...
Please correct me if I'm wrong!
Here's an example to illustrate the logic behind the 3-way diff:
Two developers are both editing the sourcecode of program v1.0 and after a long
day of fixing bugs and implementing new stuff they decide to combine their work
into a new version v2.0! So one of the developers simply does a 3-way diff/merge
"$diff3 MY_VERSION OLD_VERSION YOUR_VERSION --output NEW_VERSION"
This works for them because differing or new lines are added to the new version
of the program.
But merging configuration files needs a different 3-way diff. We need the similarities
not the differences! So here's what happends:
/etc/example.ancestor (This is the base- or ancestor-file we kept around)Code: Select all
#header v1.0 - dec 2003
param1=customized_value
param2=customized_value
param3=default_value
/etc/example (This is the current configuration file)Code: Select all
#header v1.1 - aug 2004
param1=customized_value
param2=customized_value
param3=default_value
/etc/._cfg0000_example (This is the newest version available):
Code: Select all
#header v1.2 - nov 2005
param1=default_value
param2=default_value
param3=default_value
param4=default_value
Here's what we need to successfully update our config file:
The ._cfg0000_ file has a new parameter (param4) and we want this to end
up in the merged output. But we also have customized values in the current
and ancestor file! So we want our customized values and the new parameter
all to end up in the output file, which will become our updated config file...
Ok, let's try running kdiff3 (or any other 3-way diff tool) like this:
Code: Select all
MINE YOURS ANCESTOR OUTPUT
kdiff3 /etc/example /etc/._cfg0000_example --base /etc/example.ancestor --output /etc/example.merged
/etc/example.merged (The automatically merged result)Code: Select all
<merge conflict - 3 different lines - you have to manually choose>
param1=default_value
param2=default_value
param3=default_value
param4=default_value
Even though both the current config file and the old ancestor config file have
customized parameters, the "differing" version is used in the merged output.
We don't get our customized values but we do get the new parameter line.
To be useful for auto-updating we need both so we can't use 3-way diff like this!
Ok, let's try to trick the 3-way diff by using the ._cfg0000_ file as ancestor:
Code: Select all
MINE YOURS ANCESTOR OUTPUT
kdiff3 /etc/example.ancestor /etc/example --base /etc/._cfg0000_example --output /etc/example.merged
/etc/example.merged (The automatically merged result)Code: Select all
<merge conflict - 3 different lines - you have to manually choose>
param1=custom_value
param2=custom_value
param3=default_value
<no source line>
Cool, now we have our customized values in the merged output. But this time
the new parameter isn't included automatically...
So, looking at these examples I think that 3-way diffing isn't very useful for
automatically merging configuration files. Well... at least it won't merge them
completely without user input. You'll be missing either your customized values
or newly included lines. You can't have both due to the fundamental design of
the 3-way diff. Or am I overlooking something?
