Files
alkgit/docs/research/gitoxide.md
T
glm-5.3-flash a3cdef909b feat: workspace skeleton + phase 0 research docs
- Cargo workspace with 5 sub-crates: alkgit-core (storage),
  alkgit-transport (smart protocol), alkgit-http, alkgit-ssh, alkgitd
  (binary); sha1 pinned through the gix stack, sha256 passthrough feature
- docs/research/: vision, gitoxide alignment, alk stack fit, server-side
  protocol inventory, license/reference policy, POC plan
- AGENTS.md: conventions mirroring alkcall (no comments, thiserror, tokio,
  no secrets on wire/at rest, visible-surface=authorized-surface,
  gitoxide-only serving path, bounded resources, registry-resolved repos)

Verified: cargo build, clippy -D warnings, fmt, test, check --all-features
2026-09-19 15:36:21 +00:00

5.4 KiB

Research: gitoxide (gix) as the git engine

Status: initial pass complete Date: 2026-09-19 Sources: local clone at /workspace/gitoxide (repo HEAD 77c8cd956, tag-described as gix-transport-v0.59.2-130-g77c8cd956), crates.io API.

TL;DR

gitoxide covers the storage layer (odb, packs, refs, objects, fsck) and gives us the packetline codec, but it does not give us a git server. gix-protocol and gix-transport are client-side (fetch/clone from the point of view of the machine asking for objects). The server half of the smart protocol — capability advertisement, ls-refs command dispatch, fetch negotiation on the serving side, pack generation on demand, and receive-pack application with ref transaction and update-hook semantics — has to be built by us. This is expected and acceptable: it is exactly the narrow protocol-shim layer our security model wants to own anyway (see git-protocol.md).

Version alignment (important)

crate crates.io max stable local clone note
gix 0.87.1 0.87.1 in sync
gix-packetline 0.22.2 0.22.2 in sync
gix-transport 0.59.2 0.59.2 in sync
gix-protocol 0.65.1 0.65.1 in sync
gix-pack 0.74.2 0.74.2 in sync
gix-odb 0.84.0 0.84.0 in sync
gix-ref 0.67.1 0.67.1 in sync
gix-object 0.64.1 0.64.1 in sync
gix-hash 0.26.2 0.26.2 in sync
gix-fsck 0.25.1 0.25.1 in sync

The published 0.87.1 (2026-08-24) matches the clone; the clone carries a handful of unreleased commits on top. Pin published crates.io versions in our manifests; treat the clone as a reading/reference aid, not a path dependency. If an unreleased fix turns out to be required, that is an OQ for architecture (gitoxide git-patch or [patch] section is the fallback).

Hash algorithm gotcha (encountered live)

gix with default-features = false and no hash feature fails to compile: gix-hash emits compile_error!("Please set either the sha1 or the sha256 feature flag"). The workspace manifest now pins features = ["sha1"] throughout (gix, gix-pack, gix-odb, gix-object, gix-hash) and our crates carry a matching sha256 passthrough feature for the future. This is a compile-time-rejected invariant, so the config can't drift silently.

What we can use off the shelf

Storage (strongest area — use as-is)

  • gix-odb — object database with loose + packed stores, dynamic multi-index loading, Handle with caching; the dynamic store refreshes on mtime changes, which suits a long-running server.
  • gix-pack — pack data reading (index file, multi-index, delta resolution) and pack writing (bundle::write → write_to_directory for index-from-stream). Pack writing produces index+pack into a directory; streaming a pack directly to a socket needs evaluation (POC candidate).
  • gix-ref — ref store with transaction module (compare-and-swap semantics, reflog), which is what receive-pack needs for atomic ref updates.
  • gix-object — object parsing/encoding (commit, tree, tag, blob).
  • gix-fsck — connectivity checks for received packs.
  • gix-discover — repository discovery / .git dir resolution.
  • gix facade — repo opening, config, etc. For library-developer usage gitoxide recommends default-features = false + only the components needed; follow that to keep compile times down.

Wire format (use as-is)

  • gix-packetline — pkt-line encode/decode, both blocking and futures-io async (async-io feature). This is the one crate both the http and ssh interfaces need most; it is small and stable (0.22.x).
  • gix-transport — defines Protocol (V0/V1/V2), client::MessageKind, and the fetch-side abstractions. Only the types are reusable server-side; its transport implementations (client) are not what we need.

Client side (exists, mostly irrelevant for us)

  • gix-protocol — handshake, ls-refs, fetch negotiation from the client side (fetch::Response::from_line_reader parses server responses; the negotiate module builds request arguments). Useful as a reference for response shapes we must produce server-side, and possibly reused for alkgit-to-alkgit replication later. gix-transport/src/lib.rs exports only pub mod client — confirming no server-side half exists upstream.

What gitoxide does NOT give us (we own this)

  1. Capability advertisement (V0/V1 first-want line and V2 capability handshake) — must produce ourselves.
  2. Server-side command dispatch — ls-refs, fetch V2 command parsing and the request→response state machine.
  3. Server-side negotiation — evaluating client haves against our refs (ack/NAK logic, shallow handling on the serve side).
  4. On-demand pack generation for a fetch — pack writing exists (gix-pack bundle::write) but "stream a pack computed from a want/have set to a socket" composition needs a POC; worst case we walk objects ourselves via odb and feed gix-pack::data::output::bytes entries-to-bytes writers.
  5. receive-pack — parsing client pack stream (gix-pack::data::input can parse a pack from a reader), fsck, ref CAS updates via gix-ref transaction, reporting status (unpack ok/ng lines).

License

MIT OR Apache-2.0 — same as ours. Clean to depend on and to read for inspiration (attribution not required under either license, though NOTICE-type courtesy is fine).