diff, merge and patch sets, dictionaries and lists
- diff(before, after) - returns you all changes in 'after' since 'before'
- merge(diffs) - 3-way merging of multiple diffs on the same base object
- patch(before, diff) - patches an object using a (merged) diff
- its all just diffs: merge should only need diffs as input and returns itself a new diff
- no magic: make any merge conflicts explicit to cater for different conflict resolution mechanisms
- be commutative: the order of diffs in a merge should not matter
- be recursive: implement diff, patch and merge for basic data structures and use them to support complex data structures
##Supported Data Structures
###Sets Sets are represented as JavasScript Arrays:
var before = 1 2 3 4var after1 = 1 2 4 5 6var after2 = 1 2 3 4 5 7
####diff Set diff returns you all inserted and deleted elements:
var diff = require'diff-patch-merge'setdiffvar diff1 = diffbefore after1// returns:diff: delete: 3 insert: 5 insert: 6var diff2 = diffbefore after2// returns:diff: insert: 5 insert: 7
You can merge multiple diffs that are based on the same old object.
It combines all diffs into a new diff annotating each change with the source diff:
var merge = require'diff-patch-merge'setmergevar mergedDiff = mergediff1 diff2// returns:diff:delete: 3 source: 0insert: 5 source: 0 1insert: 6 source: 0insert: 7 source: 1
####patch You can apply diffs as patches to an old set (results of merge() are diffs too):
var patch = require'diff-patch-merge'setpatchvar patched = patchold mergedDiff// returns:1 2 4 5 6 7
###Ordered Lists If you want the order of elements considered when doing a diff/merge/patch, ordered lists are the solution for you!
var before = 1 2 3 4var after1 = 1 2 4 5 7var after2 = 6 1 2 3 4 7
var diff = require'diff-merge-patch'orderedListdiffvar diff1 = diffbefore after1// returns:op: '-' length: 1 indexBefore: 1 indexAfter: 1op: '+' indexBefore: 3 indexAfter: 2 values: 5 7
Merging ordered list diffs never results in conflicts.
var merge = require'diff-merge-patch'orderedListmergevar mergedDiff = mergediff1 diff2// returns:op: '+' indexBefore: -1 values: 6 source: 1op: '-' length: 1 indexBefore: 1 source: 0op: '+' indexBefore: 3 values: 5 7 source: 0op: '+' indexBefore: 3 values: 7 source: 1
var patch = require'diff-merge-patch'orderedListpatchvar patched = patchbefore mergedDiff// returns:6 1 2 4 5 7 7
Ordered Sets are similar to Ordered Lists except that all elements are globally unique.
This allows diff/merge/patch to consider position changes of elements. In ordered list diffs there is no notion of movement, they can only be seen as a delete and insert of the same element.
var before = 1 2 3 4 5var after1 = 2 6 1 5 4 3var after2 = 2 4 1 7 3 5
var diff = require'diff-merge-patch'orderedSetdiffvar diff1 = diffbefore after1// returns:diff:3 insert: 6 move: 04 move: 3 move: 2var diff2 = diffbefore after2// returns:diff:3 move: 0 insert: 7 move: 2
####merge Merging of Ordered List diffs can lead to conflicts:
var merge = require'diff-merge-patch'orderedSetmerge// Note: orderedSet.merge() currently only accepts two diffs as inputvar mergedDiff = mergediff1 diff2// returns:diff:3 insert: 6 source: 0 move: 0 source: 0 1 insert: 7 source: 1 move: 2 conflict: 1 source: 14 move: 3 source: 0 move: 2 conflict: 1 source: 0conflict: 1
Each corresponding conflict receives the same conflict-ID.
To use a diff including conflicts to patch the old ordered set you first have to resolve them.
The library comes with a simple conflict resolution strategy which you can invoke like this:
var resolve = require'diff-merge-path'orderedSetresolve// pick source 0 as the winner of each conflict:var resolvedDiff = resolvemergedDiff 0// returns:diff:3 insert: 6 source: 0 move: 0 source: 0 1 insert: 7 source: 14 move: 3 source: 0 move: 2 source: 0
The algorithm simply picks the conflicting update that comes from the source you pass in.
Depending on your application you may want to implement different resolution strategies.
####patch Diffs can be used to patch the original ordered list:
var patch = require'diff-merge-patch'orderedSetpatchvar patched = patchbefore resolvedDiff// returns:2 6 1 7 5 4 3
The same set of functions is implemented for dictionaries.
var dictionary = require'diff-merge-patch'dictionaryvar before = 1: 1 2: 2 3: 3 4: 4var after1 = 5: 6 3: 8 2: 2 4: 4 1: 5var after2 = 2: 2 1: 9 4: 5var diff1 = dictionarydiffbefore after1// returns:diff:5: value: 61: value: 53: value: 8var diff2 = dictionarydiffbefore after2// returns:diff:1: value: 94: value: 53: value: nullvar diffsMerged = dictionarymergediff1 diff2// returns merged diffs with conflicts:diff:1: value: 5 source: 0 value: 9 source: 13: value: 8 source: 0 value: null source: 14: value: 5 source: 15: value: 6 source: 0conflict: 1 3// resolve all conflicts picking sourc 0 as the winner:diffsMerged = dictionaryresolvediffsMerged 0var result = patchbefore diffsMerged
- Trees (Ordered/Unordered) - can be built using the core data structures
- Tuple set (for tabular data e.g. from a relational database)
##Contributors This project was created by Mirko Kiefer (@mirkokiefer).