Format-aware diff, three-way merge, and patch for files that line-based tools handle badly.
One binary, splinter, that diffs and merges images, archives, structured data,
PDFs, databases, and 3-D meshes. It runs on its own and plugs into Git as a textconv, diff driver, and
merge driver. C++20, built with CMake and vcpkg. MIT licensed.
Pre-release and in testing. Every v1 format diffs and merges; the binary releases are not out
yet, so you build from source. On text, it reproduces GNU diff, diff3, and git merge-file byte
for byte on the golden corpus.
No binaries yet, so clone the repository and build from source. The steps and toolchain are in BUILDING.md.
git clone https://github.com/AlphaPixel/SemanticSplinter.git
# or, with the GitHub CLI
gh repo clone AlphaPixel/SemanticSplinter
The tool lands at build/<preset>/src/cli/Release/splinter
(splinter.exe on Windows). splinter --version prints the version to quote in a bug report.
Change one pixel in a PNG and most of its compressed bytes change too. Git reports "Binary files differ" and cannot merge two artists editing different parts of the same image. Splinter parses each format into its real units, pixels, chunks, archive members, XML elements, JSON keys, table rows, PDF objects, diffs and merges those units, and writes a valid file back.
Untouched units are copied byte for byte, so Git deltas stay small. Sizes, offsets, CRCs, and checksums are recomputed for you, and compressed streams are compared by content, so recompression noise never shows up as a change. When two sides edit the same unit it reports a conflict with a stable ID and stops. It does not average, and it does not guess.
splinter a.png b.png behaves like diff, splinter -m like
diff3 -m, and splinter -P like patch. Exit codes match whichever tool
it is standing in for.
splinter old.png new.png # changed regions, metrics, metadata splinter -u old.png new.png # unified diff over canonical dump lines splinter --json=report.json a.png b.png # machine-readable report splinter -m mine.png base.png theirs.png # three-way merge, as diff3 -m splinter -m mine.zip base.zip theirs.zip # archive members merged by path, each by its format splinter -m mine.db base.db theirs.db # SQLite rows by key, cells merged splinter --binary a.png b.png > logo.patch # a patch you can apply later splinter -P < logo.patch # apply it, as patch splinter git-setup # wire it in as a Git diff and merge driver
Everything below diffs and merges today. The checkmarks show where patch output exists; per-format limits live in the format documents.
| Format | Diff | Merge | Patch | Document |
|---|---|---|---|---|
| Text | yes | yes | yes | text |
| Unknown binary | yes | opt-in | no | binary |
| ZIP, TAR (gz/zst/xz/bz2) | yes | yes | yes | containers |
| XML | yes | yes | yes | xml |
| JSON, JSONC | yes | yes | yes | json |
| CSV, TSV | yes | yes | no | csv |
| SVG, SVGZ | yes | yes | no | svg |
| PNG | yes | yes | yes | png |
| JPEG | yes | yes | no | jpeg |
| TIFF, GIF, WebP, BMP, TGA, QOI | yes | yes | no | raster-misc |
| SQLite | yes | yes | no | sqlite |
| yes | partial | no | ||
| OBJ/MTL, PLY, STL | yes | yes | no | mesh |
PDF merges metadata, annotations, and form values but not page content yet. Rendering and page-content merge, plus signature verification and re-signing, come after v1.