Powered by the MatrixOne kernel

Git for your data

Snapshot, branch, diff, merge and roll back your tables the way you already do with code — at row level, in milliseconds, with zero copies, using plain SQL.

mysql — git4data@matrixone
-- name the state you are about to fork from
CREATE SNAPSHOT sn1 FOR TABLE orders;

-- fork it. metadata only: a 100 GB table clones in 0.20 s / 314 KB
DATA BRANCH CREATE TABLE orders_fix FROM orders{snapshot='sn1'};

-- an agent runs its repair on the branch. production never sees it.
UPDATE orders_fix SET region = 'EMEA' WHERE country IN ('FR','DE');
CREATE SNAPSHOT sn3 FOR TABLE orders_fix;

-- diff reads only the deltas, never the base table
DATA BRANCH DIFF orders{snapshot='sn2'} AGAINST orders_fix{snapshot='sn3'};
1000 rows in set (0.19 sec)

-- fold the accepted rows back: three-way, conflicts stop the world
DATA BRANCH MERGE orders_fix{snapshot='sn3'} INTO orders WHEN CONFLICT FAIL;
Query OK, 1000 rows affected (0.35 sec)

Measured on BranchBench — see the full results →

Why now

One engineer works on one snapshot. A fleet of agents works on hundreds.

LLM agents are starting to act as data engineers: they read relational data, propose transformations, evaluate the SQL, and iterate. Each agent must fork the data before it speculates, inspect a row-level diff, merge only what was validated, and roll back the paths that failed — without copying the base table. Version control stopped being a convenience the moment the number of concurrent candidate states went from one to a thousand.

Capabilities

Four verbs. Everything else is a workflow.

Git4Data maps Git's vocabulary onto a relational engine: the database is the repository, each table is a versioned object. Because the storage is append-only and MVCC-governed, a version is just lightweight metadata — so every operation costs in proportion to the change, not to the size of the data.

Snapshot

Freeze a table at an instant and give that state a name — the analogue of a commit or a tag. Nothing is copied; the snapshot is the object directory as it stood.

CREATE SNAPSHOT sn1 FOR TABLE T;

Branch

Clone a table from a snapshot into a new one that then evolves independently. Inserts, updates and deletes on either side stop affecting the other — exactly the isolation a speculating agent needs.

DATA BRANCH CREATE TABLE TClone FROM T{snapshot='sn1'};

Diff

Report the rows on which two versions disagree. Each version is an unordered multiset of records, so the diff reads only the deltas written since they split — never the base table.

DATA BRANCH DIFF T{snapshot='sn2'} AGAINST TClone{snapshot='sn3'};

Merge

Fold accepted changes back into the live table. Git4Data infers the common base revision and performs a genuine three-way merge, so non-overlapping work from several agents survives instead of being overwritten.

DATA BRANCH MERGE TClone{snapshot='sn3'} INTO T;

Time travel

The engine already retains point-in-time history for a recent window, so a past state is queryable by timestamp without anyone having declared it interesting in advance.

SELECT * FROM T{timestamp='2026-08-01 12:34:56'};

Cost tracks the change, not the table

Immutable objects mean two versions differ only in what was written after they diverged. Cloning a 100 GB table takes 0.20 s and 314 KB of metadata, where materialising it costs 114.6 s and 34 GB.

100 GB clone → 0.20 s · 314 KB

Conflict resolution is currently at row granularity: a conflict is flagged only when both branches independently modify the same key. The WHEN CONFLICT clause decides what happens then — FAIL aborts, SKIP keeps the target's row, ACCEPT keeps the source's.

How it works

A pull request, for a table.

Record a version, branch from it, compare versions, reintegrate the accepted changes. The same four moves you make every day in Git — expressed as SQL your ORM, dbt model or agent can already emit.

  1. 01

    Snapshot

    Name a past state. It is metadata, not bytes — and the engine already keeps a recent window you can query by timestamp without naming anything.

  2. 02

    Branch

    Clone a table from that snapshot. The clone inherits schema and data, then evolves independently — writes on either side stop touching the other.

  3. 03

    Diff

    Report the rows where the two versions disagree. Because it scans only the deltas, it beats the equivalent SQL by orders of magnitude.

  4. 04

    Merge

    Fold the accepted rows back with an explicit conflict policy — or drop the branch and pretend it never happened.

01 · Freeze

Every statement runs as a transaction inside the database, over the MySQL wire protocol. Version control inherits the transactions, authentication and access control you already rely on — no sidecar service, no object-store mount, no second catalog to keep in sync.

BranchBench

Up to 18.5× faster than DoltDB.

End-to-end wall-clock time on BranchBench's four agentic workflows at scale factor 100 — roughly 47 million rows, five concurrent agents, twenty steps each. Warm runs.

Landscape

Everyone has branches. Almost nobody has merge.

Zero-copy clones are common. What is missing elsewhere is the way back: comparing two versions at the row level and reintegrating one into the other. In most systems divergence is one-way.

Capability Git4Data DoltDB Neon lakeFS DVC
Unit of diff identity RowRowPage / branchObject or tableFile
Smallest thing you can branch One tableOne tableWhole databaseA namespaceA file tree
Zero-copy branch
Compare two live branches object-level
Merge a branch back three-way, per rowone-wayobject-level
Explicit conflict policy FAIL / SKIP / ACCEPTpartial
Lives inside an OLTP engine storage layer
Wire protocol MySQLMySQLPostgresS3 APICLI

Positioning follows the related-work analysis in the Git4Data paper. Third-party projects move fast — check their current documentation before you standardise on one.

Where it pays off

The shapes agentic work actually takes.

These are the four workflows BranchBench models — and the reason it models them is that this is what agents do to a database.

software_dev

Schema change with a rehearsal

An agent edits schema and code, backfills, and re-runs the tests on each attempt. The rehearsal and the release are the same statement.

failure_repro

Bisecting a bad change

Binary search through the transaction log to isolate what broke. Each probe needs its own writable state, not a read-only copy.

data_cleaning

Competing repair strategies

Normalisation, fuzzy dedup and semantic fixes each repair a different subset. No branch wins outright, so you merge the accepted deltas instead of picking one.

mcts

Search over a data plan

Tree search expands a deep, narrow frontier — one branch per node, most of them discarded. Branch creation has to be free, or the search never gets deep.

Get started

Pull the image. Break something on purpose.

MatrixOne is open source under Apache 2.0. Bring a MySQL client you already have.

bash
# 1 · run MatrixOne
docker run -d -p 6001:6001 --name matrixone \
  matrixorigin/matrixone:latest

# 2 · connect with any MySQL client
mysql -h 127.0.0.1 -P 6001 -u root -p111

# 3 · your first versioned table
CREATE SNAPSHOT s0 FOR TABLE demo.t;