history + time travel
Because DoltGres versions the whole database, every past state is still queryable. You can read a table as it looked at any commit, branch, or moment in time, walk the commit log, and ask “who changed this exact row, and to what?” — all in plain SQL.
an audit log you get for free
time travel with AS OF
DoltGres supports SQL:2011-style AS OF. The operand is any valid reference — a commit hash, a branch name, or a timestamp — and it queries the table exactly as it existed at that point.
-- as of a specific commit hash
SELECT * FROM myTable AS OF 'kfvpgcf8pkd6blnkvv8e0kle8j6lug7a';
-- as of the head of another branch
SELECT * FROM myTable AS OF 'add-welcome-note';
-- as of a moment in time
SELECT * FROM myTable AS OF TIMESTAMP('2020-01-01');
-- even the schema is versioned
SHOW CREATE TABLE myTable AS OF 'add-welcome-note';Each table in a query can carry its own AS OF— so you can join today's orders against last month's prices in a single statement to see how a number would have looked.
the commit log
The commit history lives in the dolt schema. Read it like any table, or use the DOLT_LOG table function when you want to scope the walk to specific refs.
-- full history reachable from the current HEAD
SELECT * FROM dolt.log;
-- commits before a date (columns: commit_hash, committer, email, date, message)
SELECT * FROM dolt.commits WHERE date < '2026-01-01';
-- table function: commits on main that are NOT on feat
SELECT * FROM DOLT_LOG('main', '--not', 'feat');per-table history, diff & blame
Every user table gets a family of companion system tables — DoltGres builds them automatically, named after your table. These are the workhorses of data forensics.
| system table | what it gives you |
|---|---|
dolt_history_<table> | Every version of every row across all commits — the full revision trail of the data. |
dolt_diff_<table> | Row-level changes with to_/from_ column pairs and a diff_type of added, modified, or removed. |
dolt_commit_diff_<table> | The diff between any two commits or branches — you pass the two refs as filters. |
dolt_blame_<table> | Who last changed each row, in which commit, when, and with what message. |
-- the full history of one row's every value
SELECT * FROM dolt_history_employees WHERE id = 0 ORDER BY commit_date;
-- only the rows that were modified
SELECT * FROM dolt_diff_employees WHERE diff_type = 'modified';
-- diff one table between two refs (here: main vs the feat branch)
SELECT * FROM dolt_commit_diff_employees
WHERE from_commit = 'main' AND to_commit = 'feat';
-- who last touched each row
SELECT * FROM dolt_blame_employees LIMIT 5;In a dolt_diff_<table> row, uncommitted working-set changes show up with to_commit = 'WORKING', so you can inspect pending edits the same way you inspect committed ones.
diff table functions
When you want a diff scoped by ref rather than reading the per-table system table, DoltGres ships table functions that return rows. Pass the two refs and (where relevant) a table name.
-- the per-row diff of mytable between two branches
SELECT * FROM DOLT_DIFF('main', 'feat', 'mytable');
-- a per-table summary of rows added / modified / deleted
SELECT * FROM DOLT_DIFF_STAT('main', 'feat');
-- a high-level "which tables changed" summary
SELECT * FROM DOLT_DIFF_SUMMARY('main', 'feat');