Skip to main content

kvgit 🔀

Git-style versioning for your data. Commits, branches, and merges -- backed by a dict-like MutableMapping.

Features Description
Dict interface MutableMapping[str, Any] -- reads and writes work like a dict
Commits Immutable, content-addressable snapshots with rollback
Branches Cheap forks with CAS-based optimistic concurrency
Tags Immutable names for commits; a tagged commit outlives every branch that reached it, in every kvgit version
Three-way merge Auto-merges non-overlapping changes; pluggable merge fns for conflicts
Pluggable backends In-memory, disk (diskcache), IndexedDB (Pyodide/browser), or bring your own KVStore
Chunked codecs Optional content-addressed dedup for large numpy arrays and pandas DataFrames -- equal buffers stored once across keys, commits, and branches

Install

pip install kvgit              # in-memory only
pip install kvgit[disk]        # adds disk backend via diskcache
pip install kvgit[scientific]  # adds chunked codecs for numpy / pandas
# IndexedDB backend is available automatically in Pyodide (browser) environments

Quick example

import kvgit

main = kvgit.store()

main["user"] = "alice"
main["score"] = 0
main.commit()

# Branch and diverge
dev = main.create_branch("dev")
dev["score"] = 999
dev.commit()

print(main["score"])  # 0   (main unchanged)
print(dev["score"])   # 999 (dev branch)

# Tag a commit by name -- immutable, and safe from garbage collection
main.tag("v1")
print(main.peek("score", tag="v1"))  # 0

Merging

Staged.merge() merges another head -- usually another branch's HEAD -- into the current branch: lowest common ancestor, three-way resolve, and a two-parent merge commit guarded on your own head:

dev["score"] = 500
dev.commit()

result = main.merge(dev.current_commit)  # True when merged
print(main["score"])  # 500 (fast-forward: main hadn't diverged)

Overlapping changes need a merge function per key, or a default_merge fallback. kvgit.merges.text resolves line-oriented text with git-style <<<<<<< markers (see make_text_merge for custom labels); anything it cannot mark -- binary, non-UTF-8, oversized -- raises CantMark, filed as an ordinary conflict:

from kvgit.merges import text

result = main.merge(dev.current_commit, default_merge=text)

A post_check(key, merged_bytes) predicate runs over every merge-produced value; returning False files that key as conflicted. on_conflict="abandon" leaves the branch untouched instead of raising. Merging refuses with ValueError when the staging buffer holds uncommitted changes -- commit or reset first.

Chunked codecs (numpy / pandas)

Large numpy arrays and pandas DataFrames -- and any sliced views of them -- can be stored once and shared across keys, commits, and branches:

import kvgit
import numpy as np

s = kvgit.store(codecs="scientific")

big = np.arange(1_000_000, dtype="float64")  # ~8 MB
s["full"] = big
s["head"] = big[:100_000]
s["tail"] = big[-100_000:]
s.commit()
# All three keys reference the same chunk on disk -- ~8 MB total, not ~24 MB.

Pandas DataFrames piggyback on the numpy codec via their underlying block ndarrays. See docs/quick-start.md and the API reference.

Part of the agex stack

kvgit provides versioned agent memory in agex with branching and rollback. It also works as a versioned backing store for monkeyfs virtual filesystems -- pass a Staged instance anywhere a dict is expected.

Development

uv sync --extra dev
uv run pytest

Documentation

See docs/ for detailed documentation:

  • Quick Start -- common patterns with runnable examples
  • API Reference -- full reference for all classes, methods, and types
  • Browser persistence (Pyodide) -- choosing between the IndexedDB and OPFS-mounted-disk backends, plus the syncfs flush requirement and recommended host-side patterns

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kvgit-0.3.7.tar.gz (89.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kvgit-0.3.7-py3-none-any.whl (79.8 kB view details)

Uploaded Python 3

File details

Details for the file kvgit-0.3.7.tar.gz.

File metadata

  • Download URL: kvgit-0.3.7.tar.gz
  • Upload date:
  • Size: 89.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for kvgit-0.3.7.tar.gz
Algorithm Hash digest
SHA256 668fa15e3d9d2f7f0d094663ba947d5240c43af4268747a1392c35ad866aa683
MD5 379cd886e2c7b7f755ca30e6565e8a75
BLAKE2b-256 0ce4ed87252950026dcf61829da2ad79a97001d20e42c38e14f60ce1d570882d

See more details on using hashes here.

File details

Details for the file kvgit-0.3.7-py3-none-any.whl.

File metadata

  • Download URL: kvgit-0.3.7-py3-none-any.whl
  • Upload date:
  • Size: 79.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for kvgit-0.3.7-py3-none-any.whl
Algorithm Hash digest
SHA256 3777c59e318be4add80687b1d679454bfa231da30db24b980573528968626fa3
MD5 c7d9d4649d684ba12760cf7391359c5a
BLAKE2b-256 9976e74e1ef2a7cc54e933f1feb00e8464d1a749262e48157ae8d100c4abc030

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.7 This release

2 files

0.3.6

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

1 file

0.1.3

2 files

0.1.2

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page