nbdime implements a three-way merge of Jupyter notebooks and a subset of generic JSON objects.
A merge operation with a shared origin object base
and modified objects, local
and remote
, outputs these merge results:
- a fully or partially merged object
- a set of
merge decision
objects that describe the merge operation
Each three-way notebook merge is based on the differences between the base
version and the two changed versions -- local
and remote
. These differences,base
with local
and base
with remote
, are then compared, and for each change a set of decisions are made. A merge decision
object represents such a decision, and is represented as a dict with the following entries:
{
"local_diff": <diff object>,
"remote_diff": <diff object>,
"conflict": <boolean>,
"action": <action taken/suggested>,
"common_path": <JSON path>,
"custom_diff": <diff object>
}
Merge conflicts are indicated with the conflict
field on the decision object, and if true, indicates that the given differences could not be automatically reconciled.
Note
Even when conflicted, the action
field might indicate a suggested or "best guess" resolution of the decision. If no such suggestion can be inferred, the base value will be used as the default resolution.
Each merge decision
has an entry action
which describes the resolution of the merge. It can take the following values:
- local: Use the
local
changes, as described bylocal_diff
.- remote: Use the
remote
changes as described byremote_diff
.- base: Use the original value, that is, do not apply any changes.
- either: Indicates that the
local
andremote
changes are interchangeable, and that either can be used.- local_then_remote - First apply the
local
changes, then theremote
changes. This is only applicable for certain subset of merges, like insertions in the same location (for example two cells added in the same location).- remote_then_local - Similar to local_then_remote, but
remote
changes are taken beforelocal
ones.- clear - Remove the value(s) on the object. Can, for example, be used to clear the outputs of a cell.
- custom - Use the changes as described by
custom_diff
. This can be used for more complex resolutions than those described by the other actions above. A simple example would be for the case of multiple cells (or alternatively, multiple lines of text) inserted both locally and remotely in the same location. Here, the correct resolution might be to take the first element fromlocal
, then theremote
changes, and finally the rest of thelocal
changes.
The common_path
entry of a merge decision describes the path in which the local and remote changes diverge. For example if the local changes are specified as:
patch "cells"
┗━┓ patch index 0
┣━┓ patch "source"
┃ ┗━ addrange <some lines of source to add>
┗━┓ patch "outputs"
┗━ addrange <a new output added>
and the remote changes are specified as:
patch "cells"
┗━┓ patch index 0
┗━┓ patch "outputs"
┗━ removerange <all outputs removed>
then the common path will be ["cells", 0]
, and the diff object
will omit the patch "cells"
and patch 0
operations.