zit 0.3.0 is a workflow release. 0.2.0 closed the store and dialect work;
0.3.0 is what happens when a person then sits down and uses the verbs all
day. Its centre is the Fossil-parity programme on everyday verbs:
a Fossil user's fingers now work, the receipts and narration Fossil prints
are printed, and a differential harness runs one scripted session through
both tools and pins every place they differ. Around that sit landings and
strata (a branch proposed for trunk as a reviewable artifact, and stacks of
them), per-request branch protection for a fronted serve, Fossil's user
table, and a round of read-path performance work that took the common
verbs from "scales with the store" to "scales with the change".
Nothing in this release changes an artifact, a tag namespace, or a sync
message. A stock fossil still clones, pushes, and pulls a 0.3.0 repository
byte-for-byte. Two local records grew an optional field each (the checkout
record and the undo journal); both read older records unchanged.
Highlights
- Fossil muscle memory. Verb prefixes and Fossil's aliases (
ci,co,rm/delete,changes,rename, …), a suggester for typos, Fossil's update and merge receipts, network narration that names the peer, the commit editor when-mis absent, and checkout-relative names (current,prev,next,trunk~2).zig build muscleruns the same 27-step session throughfossilandzitand fails on any divergence that is not recorded as deliberate. - The weekly verbs, filled in.
branch new|close|reopen|hide|unhide| current|info;clone URLderives its directory and opens the tree;mvtakes many operands and directories;difftakes paths and grew--numstat,--invert,--checkin,--branch,--by;merge --integrate,--baseline, a baremergeonto the one other open leaf;stash snapshot|diff|gotoandapply --merge;revert -r;-nonrevert,undo,redo,mv,merge;settings editor,autosync pullonly,--changed,--value;grep -i -c -l -v --once;annotate -n -l;timeline -F html. - Landings and strata.
zit landingproposes a branch for trunk as a forum thread plus a tag on the check-in — a reviewable record any forge can display, accept, or reject, from a bare store. Landings stack (strata): a branch may target another branch with its own open landing. servecan protect branches on a trusted front's say-so: membership changes to a named branch are refused per request, including a check-in's own singleton claim.- Fossil's user table travels.
import-fossilandconfig pull usercarry logins, capabilities, and password hashes;zit usersreads them. - Read paths scale with the change.
diff,status,stat,settings,artifact, and store open no longer derive the whole store per call: a stat memo skips re-hashing unchanged files, index v3 carries a sorted directory so opening builds no hash map, adopted index entries slice the blob instead of copying it, and CRC32 uses the ARMv8 instruction where present.updateandopenmaterialize large trees about twice as fast. import-fossil --submanifestis usable on real corpora. Each check-in's tree is built from its parent's with the sub-manifest editor, SSH-signed manifests are accepted, the whole-history replay gate is gone, and the conversion also runs straight from a Fossil URL or assubmanifest converton a zit store. A 26-hour pkgsrc import became a matter of minutes.
Everyday verbs
The programme's three rules held throughout: no artifact, tag namespace, or sync message changed; the exit-status contract and silent success on stdout survived; where Fossil has a spelling it was adopted exactly, with zit-only forms added beside it, never instead.
Dispatch and names
- Any unambiguous prefix of a verb dispatches (
zit statstill meansstat;zit timelistimeline). Ambiguity is a two-line diagnostic naming the candidates. - Fossil's aliases are accepted:
ci,checkin,co,checkout,rm,delete,changes,rename,ls/dir, and the rest listed underzit help. - The typo suggester never proposes a destructive verb for a short token.
current,ckout,prev/previous,nextresolve relative to the checkout;NAME~NandNAME^Nwalk parents;trunk^alone is the same astrunk(Fossil's trailing-punctuation rule), no longer silently the tip of something else.
Receipts and narration
updateprints Fossil's receipt: a line per changed file, anupdated-from/updated-toblock with dates, tags, and comment, and thezit undohint.-n/--dry-runand--latestare accepted.pull,push,sync, andclonename the peer (pull from URL: …), share one no-op phrase (already in sync), show per-round progress on a terminal, andcloneprints the project code. A dead peer is named.
Commit
- With no
-m,commitopens$VISUAL/$EDITOR(or the neweditorsetting) on a template that lists the changes; the comment survives a failed commit in.zit-ci-comment.-M FILE,--editor PROG,-n,--allow-empty;--no-warningsis--no-checks. - Fossil's warn-by-default on binary and CRLF content was weighed and not
adopted: zit's content gate —
binary-glob/crlf-glob, honoured from versioned.fossil-settings/too — stays opt-in, so an unset glob is "no opinion", never "refuse everything".
Reading history
timeline -b BRANCH | -c,-p PATH,-u LOGIN,-r,--offset N,-v,-F oneline|medium|full|html,*CURRENT*and*MERGE*marks,--weekday.statusclassifies (--added,--edited,--missing,--conflict,--extra,--differ), detects conflict markers, and prints a header with-v;-Rworks onpull,push,sync,remote.- Not taken, and why:
--localtime(no tz database), a global-U(collides withcommit --user),--chdir(no chdir in std.Io).
The weekly verbs
branch new NAME [BASIS],current,close/reopen/hide/unhide(control artifacts, astag add --rawmints them),info NAME, list-c -t -r.clone URLderives DIR from the URL and opens the working tree in it;--no-openkeeps a bare store; the cone is carried into the open.open URLdelegates to clone.mv OLD... NEW|DIR: several files into a directory, a tracked directory as a unit,--softto record without moving,-nto preview. The managed set now records one pending rename per moved file, so a commit carries every old name.revert -r VERSIONrestores another check-in's content without moving the checkout;revert -n,undo -n,redo -nname what they would touch.add -ftakes ignored files in a directory expansion;clean -n,-f,--emptydirs.difftakes PATH operands;--numstat;--invert;--checkin V(against its parent);--branch B(tip against its fork point);-Zis-w;-Nis accepted;--bywrites a side-by-side HTML page under$TMPDIRand opens it from a terminal.merge --integratecloses the merged leaf when the merge is committed (the checkout record carries the leaf's hash as an optional sixth field;commitmints the same control artifactbranch closedoes);--baseline B;-nis--probe; a baremergetakes the one other open leaf and names them when there are several.stash snapshotsaves without touching the tree;stash diff [ID];stash goto [ID]updates to the entry's check-in and applies;apply|pop --mergethree-way merges into a dirty file, with markers, a conflict list, and exit 5.- Settings:
editor CMD(executable tier, after--editor, before the environment; a configured editor makescommiteditor-capable without a terminal),autosync pullonly,--changed,--value. Both new settings ride the keyed config block; older stores read unchanged. grep -i -c -l -v --once;annotate -n N(look back N check-ins) and-l(the check-ins consulted).
The fossil ui answer
diff --byandtimeline -F htmlrender the two pages people open most.zit uilaunches quarry's single-repository local mode (quarry ui <checkout root> ARGS..., binary fromZIT_QUARRYorPATH); when it cannot be started the verb says so, points at the two static renders, and exits 1. quarry RFC 0010 specifies the mode.
Acceptance
zig build muscle runs 27 steps through fossil and zit, comparing exit
classes and speech. Every divergence is either same, by_design with a
reason (the changes alias header, tag list excluding branches, the dead
peer's exit class, binary content gating), or a failure. It runs in CI.
Landings and strata
landing openproposes a branch for trunk as a forum thread plus a raw tag on the check-in;landing ls,show(the check-ins being proposed, mergeability, and the thread),comment(--reply-toaims the I-card at a post),accept,reject,update(bring the target into the proposed branch on the store).accept -Rmerges against a bare store in a working area it creates, refusing conflicts, so a forge can accept without a checkout.merge --probeanswers mergeability for any pair.- Strata: a landing may target another branch with its own open landing; accepted landings close the landed leaf without propagating; cycles, unresolvable targets, already-contained branches, and rejected or already-landed bases are refused with the reason.
- The record scan no longer parses every blob to find landings. The
first line of
-mis the landing's title; N cards follow Fossil's per-type write rule.
Serve and sync
- Per-request branch protection behind a trusted front:
serverefuses membership changes to protected names, including a check-in's own singleton claim, and warms the image only after the refusal check. - The sync client's holdings are log-backed instead of a whole-store
snapshot, and
servereads push policy from the snapshot rather than scanning the log per round — the 20-minute clone stall at ~1.1M artifacts is gone.
Users and configuration
- A
.userframe kind carries Fossil's user table;import-fossiladopts it,config pull userfetches it from a peer with credentials,zit usersreads it. .fossil-settings/*is honoured beside.zit-settings/*, Fossil's spelling winning, so a mirrored Fossil project keeps its ignore globs.settingsandconfigaccept-Ron a bare store.
Performance
- Store open: index v3 carries a sorted directory (no 255k-key hash map to answer one lookup); adopted index entries slice the blob instead of copying it; CRC32 uses the ARMv8 instruction where present. Opening the 302MB tcl store: 47ms → 20ms.
diff,artifact,settings, and thediff/statusbaseline read through the image path and the scan index instead of deriving the whole view per call; a per-file (mtime, size, hash) memo in.zit-cacheskips re-hashing unchanged files.update/openstage payloads once and rename them into place: about 2x on large trees.packtrusts profitable at-rest deltas and no-ops an unchanged log.ls --longper-file cost no longer scales with the store.- The first read after a sync no longer pays a multi-second cache rebuild: two quadratic scans inside the image serializer were the cost, not the maintenance model. Every verb no longer pays O(store) DWARF stack unwinds; the release binary is a third of its former size.
timeline --weekdayuses Ben Joffe's branchless day-of-week.
Sub-manifest import
- Each check-in's tree is built incrementally from its parent's with the sub-manifest editor rather than from scratch; baseline manifests are read and parsed once; SSH-signed manifests are stripped and verified per pair in the mint loop.
- The whole-history replay gate and
--forceare gone: the gate replayed every commit through a second converter and disagreed with the store by 10–20x on cost. import-fossil URL --submanifestconverts straight from a Fossil server;submanifest convert SRC DEST [--k N]re-mints a flat zit store.fossil_convertmints FLAT when the names do not partition.
Indexer feeds
frames --structuralemits only what the crosslink links (content blobs dominated a full stream: 13.2GB on pkgsrc).crosslinkstreams the derived per-check-in records, with the U-card user and the changed files, as a CLI contract for indexers.
Fixes
- A second checkout on a shared store (
open --store) no longer treats the other checkout as "current" forupdateandmerge. updatecarries uncommitted work across the move by three-way merge, recording no merge parent;mergemerges into a dirty tree the same way.undorestores the uncommitted bytes either way.updateon a never-opened clone no longer uses memory that scales with corpus size: the client sits on the same log-backed storeserveuses.logstoreanswers a byte-aligned name prefix from the sorted directory; a complete SHA-1 name resolves.- RFC test vectors are kept inert on disk so Fossil's crosslinker cannot mistake one for a real artifact.
diff -wignores whitespace-only changes in hunks and--brief.
Compatibility
- Artifacts, tags, and the sync protocol are unchanged; Fossil RFC revision 00 remains the target.
- The checkout record (
.zit-checkout) gained an optional sixth field (integrate), written only when set; a record without it is byte-identical to the five-field form. The undo journal's format version is 4 (a sixth string); an older journal reads as damaged, which is the documented posture for transient working-tree state. - The repository config block gained two keyed entries (
editor,autosync_mode); unknown keys were always skipped, so 0.2.0 reads a 0.3.0 store. clone URL DIRnow opens the working tree; scripts that ranzit openafterwards should pass--no-openor drop the second step.mvwith three operands moves into a directory instead of failing;mergewith no NAME merges instead of failing;diffwith a bare word treats it as a PATH instead of failing;clean -f/-nare aliases now.
Qualification
Every change passed zig build test, e2e (711 scenarios), smoke
(12 Fossil interop scenarios against a real fossil), muscle (27
differential steps), git-import-e2e, git-export-e2e, and dst, and the
three-runner CI battery (macOS ARM64, Linux x86-64, Linux ARM64). Each
published binary is built from the same checksum-pinned source and
executed under low-feature CPU models before publication, as since 0.1.4.