How to Query Dolt Commit History for Tables Using dolt_log and dolt_history_*
Dolt exposes every commit as queryable SQL rows through the dolt_log system table and dolt_history_* tables, allowing you to inspect repository and table-level changes using standard SELECT statements.
Dolt treats your database like a Git repository, storing every state change as a commit object that captures the entire database at a specific moment. Unlike traditional databases that overwrite data, Dolt's version-controlled architecture in the dolthub/dolt repository persists all historical states, making Dolt commit history for tables fully accessible via system tables. This guide explains how Dolt stores commit metadata and how to query it using SQL.
How Dolt Stores Commits in the Storage Layer
At the storage layer, Dolt writes commit objects as Noms values into the value store. The core routine that persists these commits lives in go/store/types/value_store.go, specifically the Commit method at line 519, which writes a new root value and a commit address (hash.Hash) into the object store.
Commit addresses use a specific encoding defined in go/store/val/codec.go at line 98, where the CommitAddrEnc field type indicates how commit references serialize into tuples. When building or reading these tuples, the system uses go/store/val/tuple_builder.go at line 487 via TupleBuilder.PutCommitAddr and TupleDesc.GetCommitAddr to handle the low-level encoding and decoding of commit references.
Querying Repository History with dolt_log
The dolt_log System Table Schema
The dolt_log table is a virtual table generated at query time that surfaces commit metadata as rows. Its schema includes:
commit_hash: The SHA-1-like identifier of the commitcommitter: User who created the commitemail: Email address of the committerdate: Timestamp of the commitmessage: Commit messageparent_hashes: Parent commit hashes for merge tracking
Implementation in history_table.go
The table driver implementation resides in go/libraries/doltcore/sqle/history_table.go. The rowConverter function at line 585 maps raw commit Noms tuples into the SQL columns expected by dolt_log. When executing a query, the engine calls GetRows on this virtual table, which walks the commit DAG using the value store's Commit iterator built on top of the tuple descriptors that understand CommitAddrEnc.
Tracking Table-Level Changes with dolt_history_*
For per-table history, Dolt generates history tables dynamically named dolt_history_<tablename>. These tables include all original columns from the user table plus commit metadata columns (commit_hash, committer, etc.), enabling queries like SELECT * FROM dolt_history_orders WHERE commit_hash = 'abc123'.
The conversion logic for these table-specific histories forks from the dolt_log converter in go/libraries/doltcore/sqle/schema_override.go at line 164. This implementation allows you to view any row's value at any point in history using standard SQL predicates.
Query Planning and Optimization
Execution Plans for History Queries
The SQL optimizer recognizes dolt_log and dolt_history_* as system tables. When you add an ORDER BY clause, the planner generates a Sort operator. For example, ordering by commit hash produces a plan documented in go/libraries/doltcore/sqle/enginetest/dolt_query_plans.go at line 90:
Sort(dolt_log.commit_hash ASC)
└─ name: dolt_log
Join Optimization with Commit Tables
Queries joining diff tables with commit logs can use lookup join hints. The engine rewrites these to hash-based joins on the commit_hash column, as tested in go/libraries/doltcore/sqle/kvexec/lookup_join_test.go at line 136. Use the hint format:
/*+ LOOKUP_JOIN(dolt_diff_xy,dolt_log) */
Access Control and Privileges
dolt_log enforces Dolt's privilege system. According to tests in go/libraries/doltcore/sqle/enginetest/dolt_queries.go at line 1608, users without database-wide access receive errors when querying dolt_log('main'), while users granted explicit SELECT privileges can execute SELECT COUNT(*) FROM dolt_log('main').
Practical SQL Examples for Dolt Commit History
List Recent Commits
SELECT commit_hash, committer, date, message
FROM dolt_log
ORDER BY date DESC
LIMIT 10;
Count Commits in a Specific Branch
SELECT COUNT(*) FROM dolt_log('feature-branch');
View a Table's State at a Specific Commit
SELECT *
FROM dolt_history_orders
WHERE commit_hash = 'c3f9a2e1...'
ORDER BY pk;
Find When a Specific Row Changed
SELECT commit_hash, date, message
FROM dolt_history_customers
WHERE customer_id = 42
ORDER BY date DESC;
Combine Diffs with Commit Metadata
SELECT d.from_commit, d.to_commit, l.message
FROM dolt_diff_mytable AS d
JOIN dolt_log AS l ON d.from_commit = l.commit_hash;
Summary
- Dolt stores commits as Noms values in the value store, with addresses encoded using
CommitAddrEncingo/store/val/codec.go. - The
dolt_logsystem table exposes repository-wide commit metadata through the virtual table driver ingo/libraries/doltcore/sqle/history_table.go. - Table-specific history is available via
dolt_history_<tablename>tables, implemented ingo/libraries/doltcore/sqle/schema_override.go. - Query plans for history tables support sorting and lookup joins on
commit_hashfor efficient filtering. - Access control requires explicit
SELECTprivileges on the database to query commit history.
Frequently Asked Questions
How do I view the commit history for a specific table in Dolt?
Query the dolt_history_<tablename> system table, which contains every row version along with commit metadata. For example, SELECT * FROM dolt_history_users WHERE commit_hash = 'abc123' returns the state of the users table at that specific commit.
What is the difference between dolt_log and dolt_history_* tables?
dolt_log shows repository-level commit metadata (hash, author, message) for the entire database, while dolt_history_* tables show row-level data changes for a specific table combined with the commit that produced each version.
Can I join commit history tables with regular tables or diff tables?
Yes, you can join dolt_log with diff tables using the commit_hash column. The optimizer supports lookup joins on these columns, and you can use hints like /*+ LOOKUP_JOIN(dolt_diff_mytable,dolt_log) */ to optimize query performance as implemented in the engine.
Do I need special permissions to query Dolt commit history?
Yes, querying dolt_log requires SELECT privileges on the database. Users without these privileges will receive an error when attempting to query commit history, as enforced by Dolt's privilege system in go/libraries/doltcore/sqle/enginetest/dolt_queries.go.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →