Skip to content

v3.0.0

Choose a tag to compare

@github-actions github-actions released this 27 Aug 19:19
· 6 commits to main since this release
f316ce2

3.0.0 (2026-08-27)

  • feat(fetch)!: serve thin packs with serve-time warm tree deltas (337a91f)
  • feat(gc-scheduler)!: run repack as a phase of the GC drain (81db202)
  • feat(ingest)!: reject non-UTF-8 refnames and tree paths at the push boundary (50ff103)
  • feat(object)!: derive commit/tag rows and generations, replacing edge derivation (0f26fa5)
  • feat(reachability)!: replace the edge-CTE closure with row-driven walks and a bitmap reachability epoch (d81dbc9)
  • feat(repo-view)!: advance repo_file by tree diff from a recorded per-branch basis (8a59797)
  • fix(protocol)!: match canonical git on ack suppression, zero-have fetch, and d/f conflicts (fc29e42)
  • refactor(repo-file)!: rename repo-view to repo-file and collapse snapshot vocabulary into projection (1cf2272)

Bug Fixes

  • crash on impossible states instead of silently defaulting (8b558ed)
  • deps: patch postgres driver to surface connection death to copy streams (d5ca6b2)
  • gc: keep a repo eligible until a GC pass runs past its grace horizon (d703472)
  • gc: make the encoding tier's hygiene structural instead of a sweep (95b8f7f)
  • match canonical git on negotiation readiness, delta minimums, and typed-edge policy (f0d70f1)
  • pack: reject malformed delta programs instead of synthesizing zero bytes (750ff99)
  • protocol: emit in-band ERR with canonical git's exact framing (bba0071)
  • protocol: enforce git's refname and typed-graph policies at the receive boundary (7e97b38)
  • reachability,receive-pack: count commit-bit misses even when the oid is also a tag (fe6db6f)
  • reachability: classify tag-parent edges as violations instead of corruption (e882749)
  • reachability: judge a stored tag once across every role at a level (ecd6d0d)
  • receive-pack: judge directory/file conflicts in two ordered phases (0e9328a)

Features

  • gc-scheduler: couple the repack arm to gc-due so a sweep re-covers encodings (7986e02)
  • gc-scheduler: export the drain as a self-contained block with its own pool (5bd8fb1)
  • index: export the offline repack builder from the package entrypoint (4d14c81)
  • pack: derive a delta encoding tier and serve packs from it (ab5c06d)
  • schema: add the derived-state spine tables and retire git_edge (ab4664a)

Performance Improvements

  • fetch: expand client-held content only at the negotiation edges (f23ca33)
  • fetch: seed client-held expansion from boundary parents only (9fd1566)
  • test: raise the vitest worker cap from 3 to 6 (8ec5c13)

BREAKING CHANGES

  • DrainEntry no longer spreads GcResultentry.deletedObjects, entry.epoch, and entry.settled now live under entry.gc, which is nullable on a repack-only pass. GcSchedulerOptions also gains a required repackEnabled boolean, so direct createGcScheduler / resolveGcSchedulerOptions callers must pass it.
  • GitAppDeps.snapshots is renamed to GitAppDeps.projection and ReceiveBackend.syncRefSnapshot to syncRefProjection. Embedders passing snapshots to createGitApp or implementing a custom ReceiveBackend must update those names; createGitDeps callers are unaffected.
  • RepoBackend.commonHaves(haves) => Oid[] is replaced by processHaves(haves) => { common, acks }; custom backends must implement the new method.
  • RepoFileProjection.rebuildRefSnapshot(repoId, refName, fileList) is removed and replaced by applyRefAdvance(repoId, refName, newOid, planner), which takes a commit oid plus a ProjectionPlanner instead of a materialized file list and requires the repo_file_head table.
  • RepoBackend.buildPack and ObjectStore.buildPack take a trailing thinPack argument, and ObjectStore.isConnected takes an optional boundary stop-set. git_edge is gone — commit/tag structure now lives in git_commit/git_tag.
  • GcResult/DrainEntry no longer carry deletedEdges and now carry epoch; reachableClosure is renamed fullClosure and ancestryReachesCommon is renamed ancestry.
  • @/object/edges no longer exists — deriveEdges, EDGE_KIND, and treeBlobOids are removed and validateObject now lives in @/object/derive. Pushes containing tree entries with noncanonical modes are rejected at the ingest boundary and now fail where they previously succeeded.
  • schema: the git_edge table and its GitEdge model are removed, and migration 0010 cannot be rolled back — edge derivation no longer exists, so reverting would leave a permanently empty table that pre-spine readers would silently trust.
  • pggit refnames and tree-entry paths must be valid UTF-8. Pushes that canonical git accepts — a refname or path containing arbitrary non-UTF-8 bytes — are now rejected outright rather than stored U+FFFD-mangled.