Rift Star on GitHubv0.3.0

Rift / Guide

Plain diff

Give Rift two files and it writes a unified diff to standard output, the same format as diff -u.

rift a.sql b.sql > changes.patch

The heap Rift holds never passes the limit you set with --mem. The default is 256 MiB.

Here is the start of a diff of two generated SQL dumps. The files are 64 MiB each, and a change starts at about one line in a thousand.

the first and the third hunk of 434
$ rift a.sql b.sql
--- a.sql+++ b.sql@@ -380,7 +380,6 @@ INSERT INTO public.orders (id, customer_id, status, amount, note) VA… 381	178722	cancelled	2930.54	wmojdqnzik INSERT INTO public.orders (id, customer_id, status, amount, note) VA…-383	668107	shipped	5325.74	zu INSERT INTO public.orders (id, customer_id, status, amount, note) VA… 385	359182	cancelled	475.15	ztbyhdlmxk INSERT INTO public.orders (id, customer_id, status, amount, note) VA…@@ -1279,6 +1278,7 @@ 1277	990810	cancelled	3466.36	qppoqa INSERT INTO public.orders (id, customer_id, status, amount, note) VA… 1279	877409	new	9427.22	ivpjtbhdno+383	668107	shipped	5325.74	zu INSERT INTO public.orders (id, customer_id, status, amount, note) VA… 1281	232076	cancelled	3547.41	lkkqfp INSERT INTO public.orders (id, customer_id, status, amount, note) VA…
Timestamps dropped from the two header lines, and each line cut at 70 columns.

Apply the diff

The diff is an edit script. Applied to the first file with patch, it gives the second file byte for byte, line endings and a missing final newline included.

patch round trip
$ rift a.sql b.sql > changes.patch
$ patch a.sql changes.patch
$ cmp a.sql b.sql && echo identical
patching file a.sql
identical

Peak heap and time

--stats prints the peak heap, the time, the approximate regions and the moved blocks to standard error, so the diff on standard output stays clean:

rift --stats
$ rift --stats a.sql b.sql > changes.patch
peak heap 78.6 MiB of 256.0 MiB (82396678 bytes)
time 0.69 s
approx 0 segments, 0 lines in a and b
moved    62 blocks, 2737 lines
  a 21557..21560  b 22434..22437
  a 25038..25048  b 26389..26399
  a 27627..27952  b 28206..28531
  a 36864..36874  b 36680..36690
  a 48226..48235  b 49457..49466
  a 50776..50780  b 50896..50900
  a 59441..59445  b 61396..61400
  a 65493..65499  b 65178..65184
  a 99590..99595  b 99830..99835
  a 110203..110209  b 111213..111219
  ... and 52 more

Rift marks a region it could not align within the budget as approximate: the unified diff puts approx: and the reason after the closing @@ of the hunk header, where diff -p puts a function name, and patch ignores it. Here the count is 0. An approximate hunk is still correct, only coarser than it could be. The reasons:

Reason in the headerWhat it means
too many changes among repeated lines to align them exactlyNo line in the region occurs once in each file, and the search for the smallest diff hit its cost limit.
found no line here that occurs once in each file, so there is nothing to align onThe region was too large to diff in one piece, and Rift found no line to cut it at.
too large to align within --mem; a larger --mem may helpThe region ran out of its share of the budget.

--stats counts the approximate segments for each reason. Two files that share no line come out as one deletion and one insertion without the mark: with nothing in common, that is the smallest diff.

What it does not promise

The diff is not minimal. Like patience diff in git, Rift can show a change as larger than the smallest possible one. Correctness is the promise: the output always rebuilds the second file from the first.