Three-way diffs

Three-way diffs are the set of changes between a parent and two child documents. There are multiple algorithms for computing three-way diffs which are producing different results. PHPDiff implements the Weave merge and Three-way merge algorithms out of the box, while providing an interface for creating other implementations as well.

Weave merge is the default three-way merge implementation provided by this library, however, it can be easily changed either by providing an other three-way diff algorithm implementation in Differ3‘s constructor, or by calling the setter function on that class.

Description of the algorithms can be found on Wikipedia <https://en.wikipedia.org/wiki/Merge_(version_control)>.

Weave merge

Weave merge is a simple algorithm, which produces a diff that contains all units that are present in both modified versions of the files, and none that were deleted from either of them.

This algorithm only produces a merge conflict when the order of the units in the merged documents cannot be determined.

Three-way merge

Three-way merge is maybe the most common three-way merge algorithm out there. It basically produces an output which contains all the changes that are present in either of the modified versions of the document, however, when both documents containing changes at the same place, it produces a conflict.

Examples

Simple three-way diff example, using the three-way merge algorithm:

use CHItA\PHPDiff\Diff3Algorithm\ThreeWayMerge;
use CHItA\PHPDiff\Differ;
use CHItA\PHPDiff\Differ3;
use CHItA\PHPDiff\DifferBase;
use CHItA\PHPDiff\LongestCommonSubsequence\Algorithm\Hirschberg;

$differ = new Differ3(
    new ThreeWayMerge(new Differ(null, new Hirschberg()))
);
$diff = $differ->diff(
    array('a', 'b', 'c', 'd', 'e', 'f'), // Original document
    array('a', 'b', 'w', 'x', 'y', 'e'), // Modified 1
    array('a', 'q', 'r', 's', 'b', 'f')  // Modified two
);

// $diff will contain an array with the following structure:
//
// array(
//     array(
//        'type' => DifferBase::UNCHANGED,
//        array('a')
//     ),
//     array(
//        'type' => DifferBase::ADDED,
//        array('q', 'r', 's')
//     ),
//     array(
//        'type' => DifferBase::UNCHANGED,
//        array('b')
//     ),
//     array(
//         array(
//            'type' => DifferBase::REMOVED,
//            array('c', 'd', 'e', 'f')
//         ),
//         array(
//            'type' => DifferBase::ADDED,
//            array('w', 'x', 'y')
//         )
//     )
// )

Note

For more information about the diff structure generated by the library, please read the Diff structure section.