Skip to main content

graft commit

Snapshot the current branch state into the DAG. This creates a permanent, cryptographically-verifiable save point.

Usage

graft commit [-m <message>]

Behavior

  1. Stop container — Database must be at rest for a consistent snapshot
  2. Hash files — Walk the branch directory, BLAKE3-hash every file
  3. Store blobs — Put each file into the object pool (keyed by content hash, deduplicated)
  4. Build Merkle tree — Sort leaves by path, pair-hash up to a single root
  5. Insert into DAG — Write commit + tree entries to SQLite (atomic transaction)
  6. Update ref — Advance the branch ref to the new commit
  7. Start container — Only if it was running before

Flags

FlagAliasDefaultDescription
--message-m"Commit at <timestamp>"Commit message

Examples

Basic Commit

graft commit -m "seeded with production-like data"
Stopping my-postgres to snapshot data...
Hashing ~/.graft/my-postgres/branches/main...
Storing 147 blob(s) in object pool...
Save point a1b2c3d created on main (tree f0e1d2).

How Hashing Works

Graft computes a BLAKE3 hash for every file in the branch directory, excluding socket files (*.sock), PID files (*.pid), and postmaster.pid. Each leaf hash incorporates both the file’s relative path and its content hash:
leaf_hash = BLAKE3(relpath + BLAKE3(file_content))
This means moving or renaming a file changes the tree root even if the content is identical.

Commit Hash

The 7-character commit hash is computed as:
commit_hash = BLAKE3(tree_root + parent_hash + timestamp)[:7]
This means the same tree rooted at different points in the DAG produces different commit hashes.

Exit Codes

CodeMeaning
0Commit created successfully
1Error (not initialized, branch not found, container issue)