Executive Summary

A paper posted to arXiv on 2 September by six researchers at MatrixOrigin and Jianguo Wang of Purdue University proposes putting branch and merge into a relational database as SQL statements. The design treats the database as a repository and a table as a versioned object, and it goes by the name Git4Data. What makes the proposal arrive now is a change in who edits the data. A human engineer holds one snapshot and works through it in order, while a fleet of agents rummages through candidate states of the same table in parallel.

Branching a 100 GB table took 0.20 seconds and left 314 KB of metadata behind, because nothing is copied except the list of objects the snapshot points at. Once branching got that cheap, the bottleneck moved. Thousands of speculative branches now compete for the same compute and I/O, and the authors write that the open problem has shifted from storage efficiency to resource governance.

The first four sections below follow the syntax and the measurements the paper defines. Section 5 opens with the work the authors left unfinished, and the state of the open-source repository that follows it is not in the paper. It was checked directly on 6 September 2026.

Key figures

Source: Gou et al., Git4Data: Database-Native Version Control for AI Agents, arXiv:2609.02106 (2026), Tables 1 and 4 and Section 4.2

0.20 s

Cloning a 100 GB table

Building the same table with INSERT ... SELECT takes 114.6 seconds

314 KB

All the clone leaves behind

Actually copying the table costs 34 GB of additional storage

400 s

1,000 agents branching at once

DoltDB did not finish the same load within two hours

18.5×

Widest gap over DoltDB

On the data cleaning workload. The authors picked the comparison

1

When one agent splits a table three ways

The situation the paper opens with is data repair. A raw table holds duplicate entities and malformed fields, and there is no way to know in advance which cleaning strategy is right. So the agent does not commit to one strategy. It splits the source three ways: one branch normalizes categorical values by rule, another groups similar names to remove duplicates, and the third reads context to fix the meaning.

Run all three and no branch wins outright. Each strategy repairs a different subset of the records. The last step is therefore not picking a winner but taking the usable rows out of each branch and folding them into a single state, and what was tried, what was accepted and what was rejected all have to survive as a record.

Testing three cleaning strategies in parallel, then folding back row by row The data-repair scenario the paper opens with Raw table duplicate, malformed fields Branch 1 Rule-based normalization Branch 2 Fuzzy-match dedup Branch 3 Context-based repair Merged state rows accepted individually Only the rows each branch actually fixed return to a single state — Source: arXiv:2609.02106, Section 1
▲ Pebblous original diagram (data-repair scenario reconstructed) | Source: arXiv:2609.02106, Section 1

The four requirements the paper states come out of that picture. Fork the data before speculative updates, inspect row-level diffs, merge only validated changes, and roll back failed paths without copying the base version. That these should be first-class operations the database itself provides, rather than external tools, is where the proposal this article covers begins.

This paper is not the first to name those requirements. The observation that agents read relational data, propose transformations, evaluate SQL and iterate has been accumulating in the data management literature for several years, and a 2026 CIDR paper arguing for redesigning data systems to be agent-first already gave the pattern a name, agentic speculation. The benchmark used later in this article comes out of the same current. What this paper pushes in is not the diagnosis but the SQL operations that answer it.

The moment an agent gets write access, what it needs is not a better model but an isolated workspace, state that can be rolled back, and a record that stays behind. Software engineers secured all three with Git long ago. Data engineers have had no counterpart.

2

Forking works, comparing and merging do not

It is not that nobody has tried to treat data as versioned. The problem is that each attempt stops in a different place. The paper walks through five strands of prior work and marks how far each one gets before it halts.

Existing approach Where it stops
Git, Git LFS, DVC Diff and merge load the whole dataset into memory. Large files are handled as pointers only, so there is no record-level difference and no conflict resolution
MVCC Row versions are kept in a linear history, but there is no tracing back to a specific version
Snapshots, point-in-time recovery (PITR) Read and restore on a single timeline. Two writable lines of work cannot be held at the same time
Zero-copy clones in Snowflake and Supabase, Neon Parallel development and testing work. Neither reporting the row-level differences between two branches nor merging one into the other is possible, so divergence is one-way. Neon's branches are coarse-grained, and a single table cannot branch alone
Apache Iceberg, Nessie, lakeFS The metadata-only branching philosophy is the same. But the unit of diff identity is an object or a table rather than a row, so two branches that update disjoint rows still collide, and resolution means keeping one side's file whole
PostgreSQL 18 reflink cloning The copy can be delegated to the file system, but no other session may touch the source database while it runs. That makes it an offline operation in practice
DoltDB A MySQL-compatible database that already has Git-style branch, diff and merge. It is the closest prior work to this paper and the benchmark comparison target

Source: arXiv:2609.02106, Sections 1 and 5, arranged as a table.

Read the table down the column and the diagnosis converges. What databases lack is not the ability to capture or fork data changes. In the paper's own sentence, what is missing is the SQL-level operations to manipulate the resulting versions: comparison and conflict-aware reintegration.

3

Four statements to split a table and put it back

Git4Data borrows four words. A snapshot plays the part of a commit or tag, a branch is a new table cloned from a snapshot, a diff reports the rows on which two versions disagree, and a merge folds accepted changes back under an explicit conflict policy.

All four are SQL statements, so they inherit the transactions, authentication and access control that are already in place. That also means engineers and agents version data through one interface, and that changes spanning several tables publish in a single transaction. Snapshots can be taken at database granularity too, but the paper develops the syntax on a single table to keep the explanation simple.

In the workflow the paper uses as its example, table T records a snapshot called sn1, a clone called TClone branches off it and evolves on its own until sn3, T does not stand still in the meantime and advances to sn2, and at the end the two lines come together at sn4.

The four statements in order, from branch to merge T keeps taking writes while TClone evolves on its own T TClone sn1 sn2 sn4 sn3 DATA BRANCH DIFF CREATE SNAPSHOT DATA BRANCH CREATE TABLE DATA BRANCH MERGE time → Source: arXiv:2609.02106, Listing 1
▲ Pebblous original diagram (redrawn from Listing 1) | Source: arXiv:2609.02106, Section 2.1

The lightest form of snapshot is never declared at all. A multi-version storage engine already retains point-in-time history for a recent window of about 24 hours, so a past state can be queried directly by timestamp. Only the states that have to be kept for longer get promoted to a name.

-- query a recent state directly, without naming it SELECT * FROM T{timestamp='2026-08-01 12:34:56'}; -- give a name only to the states worth keeping CREATE SNAPSHOT sn1 FOR TABLE T;

A named snapshot becomes the starting point for a clone. TClone inherits the schema and data of T, and from that moment the two no longer affect one another. This is where an agent gets the isolation it needs to try a speculative change without endangering production state.

-- branch a new table off a snapshot DATA BRANCH CREATE TABLE TClone FROM T{snapshot='sn1'}; -- report only the rows where the two versions disagree DATA BRANCH DIFF T{snapshot='sn2'} AGAINST TClone{snapshot='sn3'}; -- fold accepted changes back; three conflict policies DATA BRANCH MERGE TClone{snapshot='sn3'} INTO T WHEN CONFLICT FAIL | SKIP | ACCEPT;

A comparison does not depend on ordering at all. A table version is treated as an unordered multiset of rows, and the operation picks out the rows whose signed counts do not cancel. The result is the same whatever the physical layout, and when a primary key is present it supplies a stable row identity across versions.

Why a merge does not simply overwrite the target is already visible in the example workflow. T advanced to sn2 while TClone was being explored, so swapping T for the branch would silently discard that progress. Git4Data therefore infers the common base revision sn1 on its own and performs a three-way merge. Users need not name the base, because the system tracks snapshot and clone lineage. When the base cannot be found at all the merge uses an empty base, and even then two clones share many objects, so skipping the shared ones still beats hand-written SQL.

3.1What counts as a real conflict

With a primary key the judgement is simple. The corresponding row is compared across the base, target and source snapshots, and a genuine conflict is flagged only when both branches independently modify the same key. Two branches inserting the same new key belong here too. If only one branch touched the row, or if both applied identical changes, the outcome is unambiguous and the system resolves it automatically.

A real conflict only shows up when three snapshots disagree on one key The verdict depends on how base, target and source values diverge Key Base sn1 Target T{sn2} Source TClone{sn3} Verdict K1 a b a One side only → auto-resolved K2 a b c Conflict → WHEN CONFLICT K3 a b b Both sides identical → auto-resolved A conflict is genuine only when both branches change the same key to different values — Source: arXiv:2609.02106, Section 2
▲ Pebblous original diagram (conflict-detection logic reconstructed) | Source: arXiv:2609.02106, Section 2

Without a primary key there is no identity tying one row to another, so the logic falls back to multisets. Inserted rows are grouped by their full values and deleted rows are tracked through the storage engine's physical row identifiers. A conflict is suspected only when the same change appears in both branch deltas and cannot be cancelled out, while a change confined to one side is simply applied.

The care in the design shows somewhere else. When compaction or garbage collection rewrites valid rows into new objects, the values stay the same but the position moves. Read a relocated row as a change and storage housekeeping starts masking a perfectly good update from the other branch. Git4Data recognizes equal values as a relocation and does not manufacture a false conflict. The authors add that the case does not come up often. Branches typically start from well-organized snapshots, so compaction within the common base revision is rare, and this is also the only case that requires reading the deleted base row in full.

4

Cloning a 100 GB table in 0.2 seconds

Put these operations on any OLTP database and they mean the same thing. What depends on the storage design is their cost. For the syntax to run at a price worth paying, the storage engine has to have three things already. Data appended as immutable units rather than modified in place, deletions recorded as marks, and version-control operations executing as transactions.

Why the second one matters is clear as soon as you picture diff and merge. Deletion marks are what let a diff report deleted rows without scanning the full table, and what let a merge tell a row deleted on one branch from a row deleted on both. The point the paper stresses is that on an engine with those three, Git4Data is a thin interpretation layer over them. The MatrixOne implementation required no modification to the storage layer.

MatrixOne stores table data as immutable objects in cloud object storage. Deletions are expressed as tombstone objects recording the key and the physical row id of the deleted rows, and a snapshot is nothing more than a directory pointing at those objects. Garbage collection is snapshot-aware and retains referenced objects, so keeping branches and tags alive never involves copying data.

Measure the cost of a clone and the gap opens like this. The figures come from the TPC-H lineitem table at scale factor 100, which is 100 GB.

Operation Time (s) Extra storage
Branch clone (primary key) 0.20 314 KB
Branch clone (no primary key) 0.17 294 KB
INSERT ... SELECT copy (primary key) 114.6 34 GB
INSERT ... SELECT copy (no primary key) 119.3 34 GB

TPC-H lineitem, scale factor 100. Source: arXiv:2609.02106, Table 1.

The same principle drives diff and merge. Only the objects written after the two versions diverged have to be read. With one million random rows updated, the diff took 3.27 seconds and the merge 16.13 seconds, while the hand-written SQL equivalents took 431.50 and 471.16 seconds. Without a primary key, extra lookups are needed to find deleted rows and the advantage narrows: the same conditions give 60.19 seconds for the diff and 68.75 for the merge.

Those figures all come from a single branch. The paper checked separately whether the picture holds with several. Four engineers each fork the same table and merge mostly non-overlapping updates, with two of the branches conflicting on a 10 percent primary-key overlap that is resolved by ACCEPT. Even at one million updates, the built-in diff and merge remained orders of magnitude faster than the SQL counterparts. The earlier tables had the source table sitting still while only the branch changed, so no conflict could arise. This is the one place in the paper where a conflict was created deliberately and then measured.

The lesson the authors draw here sits outside the performance tables. Git matches ordered lines of text heuristically, whereas a relational engine obtains cleaner semantics for free, because the primary key gives a row its identity. The paper writes that reconciliation based on a primary key index outperforms traditional value-based matching by more than an order of magnitude, and the two rows just above, with and without a primary key, are where that shows.

Move to end-to-end workloads and the comparison target becomes DoltDB. BranchBench is a benchmark that treats branch lifecycle, branch-local SQL, cross-branch comparison and pruning as workload dimensions. On roughly 47 million rows, five concurrent agents run 20 steps each, forking, querying, then merging or discarding. The paper runs four end-to-end workflows on it: software development, failure reproduction, data cleaning and Monte Carlo tree search, which its tables label software_dev, failure_repro, data_cleaning and mcts.

BranchBench warm runtimes across four workloads Scale factor 100 (about 47 million rows), five agents, 20 steps Git4Data DoltDB software_dev 122.1 1925.6 failure_repro 198.9 1677.3 data_cleaning 58.6 1084.2 mcts 39.8 410.2 Seconds, warm-run averages. The speedups (15.8, 8.4, 18.5, 10.3×) are ratios of these values. Source: arXiv:2609.02106, Table 4.
▲ Pebblous original diagram (redrawn from Table 4) | Source: arXiv:2609.02106, Section 4.2

Across the four workloads the gap runs from 8.4× to 18.5×. The authors explain it by what each system reads: DoltDB materializes and compares table contents on every branch operation, while Git4Data reads only the changed deltas. Runtime therefore tracks the size of the change rather than the size of the table.

That property shows most sharply in an experiment that raises the agent count to 1,000. Each agent forks the database and runs one branch-local step, and Git4Data finished in 400 seconds while DoltDB failed to finish within two hours. Grow the data tenfold and the same simulation stretched only to 600 seconds. Per-fork cost is bound to metadata alone, independent of data size.

The exception is recorded in the paper too. At ten times the data, software_dev and data_cleaning slowed by at most 3.2×, and mcts stayed under 40 seconds warm, essentially flat. Only failure_repro slowed, by 13.5×. Its repairs scan and rewrite the entire table, so the cost tracks data size rather than change size. The authors have drawn the boundary of their own delta-based design.

These numbers come with one condition attached. Six of the seven authors work at MatrixOrigin, which builds and sells MatrixOne, and the seventh is at Purdue University. These are measurements taken by the vendor on a feature in its own product, with the comparison target and the experimental setup chosen by the authors. It is not third-party verification. What balances it is where the benchmark came from and whether the implementation is open. BranchBench was built by another team, and the implementation is open source, so anyone can check the syntax and the code.

5

Cheap branches exposed the next bottleneck

Once forking became a metadata operation and merges committed atomically, branch creation stopped constraining concurrency. What came to the front instead was the branch-local work competing for shared compute and I/O. In the authors' own phrasing, the open problem shifted from storage efficiency to resource governance.

The paper lists four things still to be done, and the first two bite right away. One is how to set scheduling, admission control and per-branch quotas across thousands of speculative branches. The other is that conflict resolution is row-level today, so two branches that edit different columns of the same row are still flagged as a conflict, and going down to the cell is the natural next step. The harder problem lies in the semantics. Two changes that each satisfy a constraint on their own can break it once they are combined.

The other two show up when a branch lives a long time. A schema change breaks the premise that diff and merge rest on, and named snapshots pin the objects they reference, so storage grows as branches pile up. Both are left without a policy. The conflict policies themselves stop at three, and one of the directions the authors mark as unexplored is handing the merge driver role to an agent that has read the diff output.

To see how far the code had come on the things the paper marks as open, this article opened the repository. MatrixOne ships more statements than the four the paper describes. Alongside branch creation and deletion at table and database granularity, plus diff and merge, the parser's syntax tree holds one more statement that does not appear in the paper.

-- take only the rows for approved keys (not in the paper) DATA BRANCH PICK src INTO dst KEYS (SELECT id FROM approved) WHEN CONFLICT SKIP;

It is the counterpart of Git's cherry-pick, and it was merged on 9 April 2026. Primary key values can be written as literals or passed in as a subquery to move specific rows into the target table, and the scope can also be narrowed to the changes between two snapshots. The three conflict policies are the same as for merge, and a table without a primary key is rejected outright. It maps onto the last step of the data-repair workflow at the top of this article, folding back only the deltas that were accepted. The paper does not discuss this statement, so connecting the two is this article's reading. Being able to pass an approval list as a subquery is particularly practical for a team that wants its review step to live inside SQL.

Resource governance is moving too. A change merged on 29 August puts per-account quotas on snapshot creation and branch creation, and enforces ordering so that a request arriving at another node right after an administrator changes a limit cannot slip through on a stale catalog. If there is no limit it passes straight through, and if the quota is finite the quota row is locked while usage is counted, with metadata publication bound into the same transaction. This is still some way from the per-branch quotas the paper describes, that is, from scheduling that reflects how far each agent has got. Even so, it reads as a signal that resource control is moving out of the operations document and into the engine.

Agent governance is usually treated as a matter of policy documents and approval steps. The conclusion of this paper comes from the other side. If isolation, rollback and an audit trail can be secured just by exposing properties the storage engine already had as SQL statements, then a good part of governance is a problem the storage layer solves.

Editor's Note

One question comes up often when Pebblous diagnoses data quality. Can you trace where this data came from and what it passed through? When people did the editing, a change history full of gaps could still be reconstructed somehow. When the editing is done by a fleet of agents, that changes. If what was tried and what was accepted does not stay in the data itself, there is no way to rebuild the lineage after the fact. Bringing branch and merge inside the database is, in the end, also a way of moving where that record is kept.

Thank you for reading this far. The full paper is at arXiv:2609.02106. The syntax and figures in this article come from its Sections 2, 3 and 4, and the state of the code was checked directly in the MatrixOne repository on 6 September 2026. If your team has already opened data write access to agents, we would be glad to hear which layer is carrying rollback and record-keeping for you.

R

References

Academic Papers

  • 1.Gou, H., Zhang, Z., Sun, Y., Xu, P., Tian, F., Wang, L., Wang, J. (2026). "Git4Data: Database-Native Version Control for AI Agents." arXiv:2609.02106.
  • 2.Ang et al. (2026). "Supporting Our AI Overlords: Reimagining Data Practices for AI Agents." CAIS'26 workshop. — Source of the BranchBench comparison benchmark, a team separate from the Git4Data authors.

Implementation & Comparison Targets

  • 3.MatrixOrigin. (2026). "matrixorigin/matrixone." GitHub. — The repository where Git4Data is implemented.
  • 4.DoltHub. (2026). "dolthub/dolt." GitHub. — The BranchBench comparison target and closest prior implementation.
  • 5.Neon. (2026). "Branching." Neon Docs. — Instance-level copy-on-write forking; no table-level branching or row-level merge.