Rift Star on GitHubv0.3.0

Rift / Guide

Git integration

Git calls any file over 512 MiB binary and prints no diff. rift git-diff gives git a real diff for those files.

rift git-diff ships in 0.3.0.

On a 640 MiB pair of generated SQL dumps, git prints this:

git on a file over 512 MiB
$ git diff --no-index a.sql b.sql
diff --git a/a.sql b/b.sql
index 86d4681..61a1efd 100644
Binary files a/a.sql and b/b.sql differ

With Rift as the external diff, the same command prints git's headers and a unified diff:

git with rift git-diff
$ git -c diff.external='rift git-diff' diff --no-index a.sql b.sql > out.diff
$ head -n 12 out.diff | cut -c1-100
diff --git a/a.sql b/b.sql
index 86d4681..61a1efd 100644
--- a/a.sql
+++ b/b.sql
@@ -380,7 +380,6 @@
 INSERT INTO public.orders (id, customer_id, status, amount, note) VALUES (380, 514366, 'shipped', 5
 381	178722	cancelled	2930.54	wmojdqnzik
 INSERT INTO public.orders (id, customer_id, status, amount, note) VALUES (382, 679322, 'cancelled',
-383	668107	shipped	5325.74	zu
 INSERT INTO public.orders (id, customer_id, status, amount, note) VALUES (384, 442363, 'new', 6149.
 385	359182	cancelled	475.15	ztbyhdlmxk
 INSERT INTO public.orders (id, customer_id, status, amount, note) VALUES (386, 967299, 'shipped', 4

Set it up for large files only

Name the large files in .gitattributes and define the driver, so everything else keeps git's own diff:

echo '*.sql diff=rift' >> .gitattributes
echo '*.csv diff=rift' >> .gitattributes
git config diff.rift.command 'rift git-diff --mem 1G'

Git runs the command through the shell, so options go inside the quotes.

rift git-diff takes the seven arguments git passes: path old-file old-hex old-mode new-file new-hex new-mode, and for a rename or copy also the new path and git's rename lines. It prints git's headers (diff --git, mode lines, index, --- a/path, +++ b/path, and /dev/null for an added or deleted file) and the unified diff from Rift.

Exit status

The command exits 0 whether or not the files differ, because git treats any other status as a failure and stops with status 128. The status of git diff is git's own: 0, or 1 with --exit-code when there are differences. Rift exits 2 on an error.

What differs from git's output

LFS pointers

If a side is a Git LFS pointer, Rift reads the object from .git/lfs/objects of the common git directory and reads it in place. A missing object stops the run and names its oid: fetch it with git lfs fetch. If the object's size differs from the pointer's, Rift stops. Rift does not check the hash and ignores lfs.storage.

The cost without LFS

Git writes every blob that is not in the work tree to a temporary file before it runs the command. For a file that is not stored with LFS, that is a full copy: on a 10 GB file, 10 GB of disk and the time to write it. Comparing a work tree file with the index makes one copy. Comparing two commits makes two.

The terminal view

git difftool opens the terminal view. It passes the two files as $LOCAL and $REMOTE and does not resolve LFS pointers:

git config difftool.rift.cmd 'rift -i "$LOCAL" "$REMOTE"'
git config difftool.prompt false
git difftool -t rift