grit://cooking/changelog← what’s cooking
Tuesday, October 27, 2026 · release v0.5.23

79 changes landed on main

60 issue fixes · 19 other changes

v0.5.23 mostly cuts time and memory in history walks, diff, push, fetch and status, and fixes many push, rebase, checkout and library-embedding bugs.

  • ›Faster revision ranges: A..B, A...B and --count now stop near the range instead of walking all history
  • ›Faster push and fetch: one-commit push, whole-repo HTTP push, upload-pack negotiation and thin packs; push --atomic and receive-pack fsck/shallow fixes
  • ›Lower memory in status with a MIDX, blame, bounded log, tree diff and stash pop; 7-9x faster rename detection and branch listing
  • ›Rebase fixes: exec edits kept, HEAD reflog written, duplicate-patch replay, JSON head, crash recovery
  • ›Switch and clone roll back on Ctrl-C; checkout operations take index.lock first
  • ›grit-lib: serializable results, cancellation, write_merge_tree, injected RefStore honored, Windows path and NTFS fixes
$ git log a3300042..v0.5.23308 commits on GitHub ↗300+ files +18,230 −1,524
Highlightsmeasured by the reviewers, before → after
One-file commit does ~2000 remote round trips when the object store is layered via OdbBuilder::push_read_source
Layered one-file commit remote calls, 1,000 directories501× better████████████████████████ 2,005 round trips █ 4 round trips
revs --count A..B / RevWalk::count 20-125x slower than git (cargo 0.50.0..HEAD: 18.8s vs 0.15s); listing takes 0.36s
Cargo 0.50.0..HEAD count median127× better████████████████████████ 18.6 seconds █ 0.147 seconds
upload-pack incremental fetch on git/git: 4.4 s with a bitmap (git 21 ms), thin pack 2-7x bigger than git's
HEAD~1 bitmap latency102× better████████████████████████ 3,118 ms median of 3 █ 30.5 ms median of 3
core.ignorecase=true (macOS default): add/commit/clone quadratic in files per dir (4k files: commit 11s vs git 0.03s)
Add 4k new files with ignorecase median (system git: 53 ms)87× better████████████████████████ 6,457 ms █ 74 ms
A Git-written multi-pack-index makes clean status peak at 62 MB vs Git's 8 MB
MIDX-only human status RSS growth85× better████████████████████████ 45,260 KiB █ 532 KiB
issues fixed60
  • ›Current main fails injected RefStore branch deletion regression with inconsistent checked-out error variant#2030e6b95326

    Corrects a stale injected-store test to expect the current-branch error already promised by the library. Adds refusal/state-preservation coverage across ref backends and verifies that both checked-out error variants retain the same CLI JSON kind.

  • ›A Git-written multi-pack-index makes clean status peak at 62 MB vs Git's 8 MB#206409fd2e05

    Clean status now shares one validated MIDX backing within its owning repository cache and releases checksum-only pages. On the exact git/git fixture, median peak RSS fell from 61,728 to 16,616 KiB and elapsed time from 35.99 to 21.64 ms, with no-MIDX human timing unchanged.

    Human status peak RSS, MIDX present (stock Git: 7792 KiB): 61,728 KiB → 16,616 KiB (3.7× better)MIDX-only human status RSS growth: 45,260 KiB → 532 KiB (85× better)Human status latency, MIDX present (stock Git: 11.68 ms): 36.0 ms → 21.6 ms (66% better)
  • ›gc and repack cannot maintain an offline partial clone after a local commit#206580dc322f

    Keeps already available content readable when a partial clone is maintained offline. Marked packs remain separate from newly packed local objects, and ordinary packs holding the only available copies of promised objects now survive cleanup with their sidecars.

    complete gc median wall (Git 1693.283 ms): 1,750 ms → 1,740 ms (1% better)
  • ›rebase --continue --json reports head:null after moving HEAD#2077d989c8fe

    Completed rebase calls now return the HEAD OIDs observed before and after that invocation. Both rebase CLI entry points use that typed result for JSON and Markdown, so a successful continuation no longer hides a real HEAD movement behind null.

    Continuation median wall time (100 replay commits, 1,000 stable files): 5,064 ms → 4,960 ms (2% better)Continuation median peak RSS: 52,788 KiB → 53,020 KiB (0% worse)
  • ›grit diff between two tags on git/git is 9-12x slower than git (2.5-3.6 s vs 0.26-0.78 s): inexact rename detection#1683b8394eb0

    Rename and copy fingerprints now aggregate byte weights once per blob and compare sorted tables without allocating a hash map for each candidate. Scores and all eight measured command outputs remain unchanged; my runs show roughly 7× faster tag name-status and 8.7× faster detection across 1,000 inexact renames.

    Tag name-status wall time (stock Git: 316.8 ms): 1,264 ms → 181.9 ms (6.9× better)Tag name-only wall time (stock Git: 316.6 ms): 1,599 ms → 211.2 ms (7.6× better)Tag numstat wall time (stock Git: 897.1 ms): 2,326 ms → 921 ms (2.5× better)Tag stat wall time (stock Git: 902.5 ms): 2,336 ms → 929.6 ms (2.5× better)
  • ›Default diff fails on clean repos with 1,000+ files and directory symlinks; --threads 1 works#207602e8900b

    Large clean worktrees containing directory, file, or dangling symlinks now produce clean parallel diffs and correctly reject empty commit previews. Retargeted links use their target bytes; regular files retain parallel hashing.

    Regular clean diff: main → fix: 198.8 ms → 197.5 ms (1% better)Regular edited diff: main → fix: 198.2 ms → 198.1 ms (0% better)Regular clean preview: main → fix: 239.4 ms → 239.9 ms (0% worse)
  • ›blame JSON original_path names a nonexistent file in an attributed git-gui commit#2078b4e048f1

    Blame now preserves each pending line's source filename when unchanged edge lines cross a rename-and-edit. Commit, original line, and original path can therefore navigate to an existing source location, including after a subtree move.

    Real git-gui lines 1–3 median wall time; system Git 222.077 ms: 558.8 ms → 558.0 ms (0% better)Large-tail range 100–120 median wall time; system Git 90.983 ms: 42.8 ms → 43.1 ms (1% worse)
  • ›grit rebase --exec silently discards tracked edits made by successful commands#20323c1a41ef

    A successful rebase exec that modifies tracked files now stops immediately with exec_dirty and preserves its index and worktree. Both rebase entry points explain recovery; continue/skip resume the saved command position after edits are saved, and abort explicitly restores the original state.

    Clean exec, 40 commits / 200 files: origin/main to branch: 129.9 ms → 185.3 ms (30% worse)Clean exec, 40 commits / 2000 files: origin/main to branch: 1,501 ms → 2,050 ms (27% worse)200-file peak RSS: origin/main to branch (effectively flat): 21,420 KiB → 21,260 KiB (1% better)
  • ›grit push --atomic over HTTP partially publishes refs when an update hook rejects one#2034e98de8a1

    Wire pushes now explicitly request a single ref transaction when atomic mode is selected. Unsupported servers return a typed error before update commands or objects are written, including dry-run and no-op requests.

    Ordinary two-ref HTTP push median; system Git control 223.047 ms: 318.4 ms → 317.5 ms (0% better)Accepted atomic two-ref HTTP push median; system Git control 222.408 ms: 316.7 ms → 316.2 ms (0% better)
  • ›grit reset HEAD~1 (undo last commit) costs a full-history walk: 610 ms on git/git, git 2 ms (300x)#1855ea7901dc

    This change makes orphan detection stop near the commits being reset instead of traversing deep history kept alive by old tags. It also deduplicates and cheaply peels reset hide refs, then adds regression coverage, a daily benchmark, and matching documentation.

    reset --soft HEAD~1 median on pinned git.git: 592.4 ms → 11.7 ms (50× better)
  • ›Tree metadata diff on 120k files uses 40 MB in grit-lib / 53 MB in grit CLI (Git: 11 MB)#20839e6a6be2

    Tree diffs release completed sibling metadata within the existing ODB cache budget. Metadata-only file output also reuses its input strings, cutting both library and CLI memory while preserving the public API and output.

    Loose public API peak RSS: 39,676 KiB → 19,800 KiB (2.0× better)Loose public API wall (system Git: 47.90 ms): 87.1 ms → 76.3 ms (14% better)Loose CLI default peak RSS: 55,188 KiB → 34,680 KiB (59% better)Loose CLI default wall (system Git: 48.31 ms): 72.8 ms → 59.5 ms (22% better)
  • ›Sparse reset scans the full monorepo: 240k paths/300 visible takes 2.35 s and 140 MB (Git: 36 ms/15 MB)#20815ea10156

    Reset and switch now keep unchanged excluded directories opaque, making a sparse monorepo transition cost roughly the visible working set. The review follow-up prevents stale cleanup paths from deleting external files through replacement symlinks or failing after a directory becomes a regular file.

    120k reset; system Git 28.85 ms: 1,003 ms → 31.1 ms (32× better)120k reset; system Git 10546.00 KiB: 74,062 KiB → 17,912 KiB (4.1× better)120k switch; system Git 37.79 ms: 441.8 ms → 30.8 ms (14× better)
  • ›Bounded log on fresh local git/git clone uses 47 MB vs Git's 17 MB; packing tag refs drops it to 18 MB#2080eff43375

    Packed-object reads now retain at most 16 sparse-read files per pack store, so the 96-pack repository remains fully readable under a 64-descriptor limit. The full change also packs imported clone tags and reduces loose-tag bounded-log RSS from 46,436 to 26,076 KiB, without changing public APIs or repository formats.

    Log 10 loose-tag peak RSS; system Git 16,544 KiB: 46,436 KiB → 26,076 KiB (78% better)Log 10 loose-tag wall time; system Git 21.26 ms: 36.2 ms → 38.2 ms (5% worse)Log 10 packed-tag peak RSS; system Git 16,512 KiB: 17,220 KiB → 17,852 KiB (4% worse)Log 10 packed-tag wall time; system Git 13.43 ms: 4.5 ms → 4.6 ms (2% worse)
  • ›stash pop retains 86–91 MB for 3k edits in a 120k-file tree (Git: 37–38 MB)#20826be1920c

    Stash apply/pop now preserves exact Git filename bytes, including literal grit+pathhex: names and Unix non-UTF-8 paths. Local-overwrite checks protect the real file, and clean applies, deletions, moved HEAD, conflicts and --index produce the same state as system Git. Independent release checks retain roughly 45–46% lower peak RSS and 49–50% lower elapsed time than current main.

    human pop time (origin/main → branch): 294.3 ms median → 149.0 ms median (98% better)human peak RSS (origin/main → branch): 90,824 KiB, maximum warm peak → 49,616 KiB, maximum warm peak (83% better)json pop time (origin/main → branch): 307.6 ms median → 155.6 ms median (98% better)
  • ›sirocco may help with faster decompression#20291306f22e

    Retain flate2 and add the tests and benchmark infrastructure needed to evaluate another decoder reliably. This change ships no Sirocco dependency, production behavior change, public API change, or format change.

    50k packed library walk, no graph; stock Git 139.98 ms: 333.0 ms → 328.4 ms (1% better)50k packed library walk, no graph; stock Git 19156 KiB: 53,436 KiB peak RSS → 53,472 KiB peak RSS (0% worse)
  • ›Ranged blame of 3 git-gui lines peaks at 354 MB vs system Git's 86 MB#207958029b75

    Ranged blame now releases inactive pack readers instead of retaining a file for every historical pack. The 300-pack case succeeds under a 256-descriptor limit, and the exact three-line git/git request uses 1.58 times system Git's memory.

    Exact three-line blame peak RSS (Git: 85,344 KiB): 351,604 KiB → 135,188 KiB (2.6× better)Exact three-line blame time (Git: 206.89 ms): 513.0 ms → 494.3 ms (4% better)Full-file blame time (Git: 268.89 ms): 1,198 ms → 1,193 ms (0% better)
  • ›Local-path push ignores receive.denyNonFastForwards/denyDeletes/denyCurrentBranch (http receive-pack honors them)#193323fb9ba8

    Local-path pushes now enforce the same receive-side ref policies as wire receive-pack, rejecting prohibited non-fast-forwards, deletes, and updates to a checked-out branch. The round-2 fix makes ancestry validation see objects from both sides before a dry run and the populated remote store after a real copy, while tracking the two shared helpers in the public API snapshot.

  • ›Windows: clone/switch accept NTFS stream and trailing-dot paths; .gitmodules::$DATA overwrites .gitmodules#169917fbe0b3

    Windows worktree validation now rejects NTFS alternate streams and illegal characters, trailing spaces or dots, and reserved DOS device names before checkout can create or alias files. The round-2 rewrite expresses those rules as independent per-piece checks and preserves typed library errors.

  • ›Reduce command startup relocation cost while preserving PIE and ASLR#2028ad7f5106

    Keeps automatic GNU installs on the existing stock binary after same-source measurements showed the optional RELR link slows short dist commands. It still publishes a separately named x86_64 GNU RELR artifact for manual use, guarded by PIE, RELRO, BIND_NOW, ABI, oldest-loader, startup, and ASLR checks, and records reproducible benchmark evidence.

    dist tiny branch median, stock → RELR: 2.1 ms (system Git control 1.411891 ms) → 2.2 ms (system Git control 1.411891 ms) (2% worse)dist tiny status median, stock → RELR: 2.5 ms (system Git control 1.713247 ms) → 2.6 ms (system Git control 1.713247 ms) (2% worse)dist tiny resolve median, stock → RELR: 2.2 ms (system Git control 1.280404 ms) → 2.2 ms (system Git control 1.280404 ms) (1% worse)dist tiny help median, stock → RELR: 3.2 ms (system Git control 1.147823 ms) → 3.2 ms (system Git control 1.147823 ms) (1% worse)
  • ›grit revs A..B walks the entire history: 800ms/126MB on git/git for a 20-commit range (git rev-list: 2ms/12MB)#16696be9ffe0

    Unfiltered revision counts with exclusions now use a generation-ordered two-sided paint when a usable commit-graph is present. The walk stops once the included frontier is resolved instead of constructing complete include and exclude ancestor closures; CLI behavior and public signatures do not change.

    Git-written graph range count (debug build): 374.1 ms → 10.0 ms (38× better)grit-written graph range count (debug build): 285.4 ms → 9.2 ms (31× better)Git-written graph count peak RSS (debug build): 42.0 MiB → 40.8 MiB (3% better)Git-written graph range listing (debug build): 24.0 ms → 20.5 ms (17% better)
  • ›stash/reset --hard/switch with index.lock held: exit 1 but worktree already rewritten; stash edits lost (no ref)#2103c5572702

    Mutating checkout-family operations now reserve the index before they can rewrite worktree bytes or create stash objects. The held lock is threaded through checkout/index persistence, so a foreign index.lock returns LockHeld with the repository byte-for-byte unchanged; stash entries remain reachable if a later reset step fails.

    Switch median, 30k files (origin/main → branch): 81.7 ms → 80.8 ms (1% better)Reset --hard median, 30k files (origin/main → branch): 85.7 ms → 81.4 ms (5% better)Stash push median, 30k files (origin/main → branch): 84.6 ms → 75.2 ms (13% better)
  • ›Windows: clone/checkout accepts reserved device names (aux, COM1.txt) and GIT~1. that git rejects (protectNTFS)#18120f5bea28

    This change prevents Windows worktree checkout from creating reserved device names, trailing-dot/space names, and other Win32-invalid components, while extending protectNTFS to reject GIT~1 aliases with stripped suffixes on every platform. The review revision adds a cheap alias prefilter so ordinary checkout paths no longer pay the prior regression.

    validate_path median, 8M calls/run over 8,000 realistic paths, 21 interleaved release runs: 157.8 ns/path → 123.9 ns/path (27% better)validate_path minimum across 21 runs: 157.1 ns/path → 123.4 ns/path (27% better)validate_path maximum across 21 runs: 159.6 ns/path → 125.2 ns/path (28% better)
  • ›core.ignorecase=true (macOS default): add/commit/clone quadratic in files per dir (4k files: commit 11s vs git 0.03s)#2102159bc776

    Adds a per-operation cache for case-insensitive directory spelling resolution, so each parent directory is listed once rather than once per indexed file. Add/commit staging and collision winner accounting share that cache while retaining existing spelling selection behavior.

    4k-file ignorecase commit median (system git: 52 ms): 3,216 ms → 89 ms (36× better)Add 4k new files with ignorecase median (system git: 53 ms): 6,457 ms → 74 ms (87× better)
  • ›pre-push hook never runs (a failing hook doesn't block push); relative core.hooksPath skipped from subdirectories#17998249b714

    Push now executes the repository's pre-push policy gate after remote refs are known and before commands or objects are sent, across local and wire transports, with `--no-verify` as an explicit bypass. Relative `core.hooksPath` lookup is anchored to the worktree root (or git directory for bare repositories), so invocation from a subdirectory no longer silently skips hooks.

    Up-to-date grit push mean (system Git comparator: 4.376 ms): 6.8 ms → 6.9 ms (1% worse)
  • ›grit push of ONE new commit over ssh/http burns CPU like a full-history walk: git/git 1.9s/242MB (git 0.04s/44MB)#19754da3f963

    This change makes a one-commit network push scale with the objects being sent instead of the remote's total advertised branch set. It limits thin-delta candidates to actual history-edge commits, caches peer tree blobs once, avoids broad pack-index/bitmap scans, and buffers git:// and SSH reads.

    git/git fake-SSH one-commit push median wall time: 146.7 ms → 75.2 ms (95% better)git/git fake-SSH one-commit push peak RSS: 59,228 KB → 53,228 KB (11% better)one-commit push median relative to measured system Git: 2.9 x Git → 1.5 x Git (95% better)
  • ›grit-lib: RepositoryOptions::empty() (quickstart) ignores system/global config; status() flags clean CRLF files Modified#21105ebe1d90

    Adds `RepositoryOptions::from_process()` as the discoverable, explicit way for embedders to open user repositories with the same process-derived system/global configuration as grit and Git. Updates user-repository examples and guides to use it, while preserving `empty()` for hermetic repositories, and adds a system-config CRLF status regression against system Git.

  • ›grit-lib on Windows: Repository::work_tree()/git_dir() return \\?\ verbatim paths that never equal the opened path#2111ecc581c6

    Repository handles now expose ordinary drive-letter or UNC paths on Windows when dropping the verbatim prefix preserves the path’s meaning. Unsafe-to-simplify paths remain verbatim, and all internal canonicalization sites use the same spelling so comparisons remain consistent.

  • ›file:// and local-path push/fetch/clone copy the source's whole pack, uploading objects unreachable from the pushed refs#1743c120c8f8

    Local and file:// fetch, push, and clone now transfer only objects reachable from the requested refs, preventing hidden refs and deleted/private work from leaking through shared packs. Plain filesystem-path clone deliberately retains Git's fast local behavior, while exact source packs can still be hard-linked without rebuilding.

    Packed hidden-ref file:// clone object count: 6,555 objects → 5,052 objects (30% better)Packed hidden-ref file:// clone median latency: 0.095 seconds → 0.150 seconds (37% worse)
  • ›revs --count A..B / RevWalk::count 20-125x slower than git (cargo 0.50.0..HEAD: 18.8s vs 0.15s); listing takes 0.36s#2105ec05183a

    Revision-range counting paints included and excluded ancestry once, then counts left-only commits with O(1) membership checks instead of launching fresh ancestry walks for every candidate. Filtered, first-parent, and left/right counts share the faster path, including a correction for hidden commits reached through non-first parents.

    Cargo 0.50.0..HEAD count median: 18.6 seconds → 0.147 seconds (127× better)Cargo 0.50.0..HEAD --since=2023-01-01 count median: 18.4 seconds → 0.157 seconds (117× better)
  • ›grit add <paths> on a 48k-file tree scales ~3.5ms per path: 98 paths 360-540ms (git: <10ms); add . 4x, commit 4x#16828bcf7d7c

    This change removes the index-size-multiplied cost of staging under case-insensitive/macOS path settings. It caches compact directory listings, prefetches parent directories in parallel, avoids unnecessary Unicode and pathspec work, and keeps case-only rename handling compatible with system Git.

    ignorecase add 1 path: 148.6 ms median (5 runs) → 49.8 ms median (5 runs) (3.0× better)ignorecase add 98 paths: 167.4 ms median (5 runs) → 61.6 ms median (5 runs) (2.7× better)ignorecase add all: 305.6 ms median (5 runs) → 112.7 ms median (5 runs) (2.7× better)ignorecase add update: 274.6 ms median (5 runs) → 74.5 ms median (5 runs) (3.7× better)
  • ›receive-pack ignores receive.fsckObjects/transfer.fsckObjects: malformed commits are accepted and refs updated#1818fdd72fdb

    Receive-pack now honors repository fsck settings before quarantined objects are migrated, rejecting malformed commits, trees, and tags without updating refs or polluting the main object database. Round 2 also ensures an accepted missing-committer diagnostic cannot hide a later NUL-in-commit error.

  • ›predict_merge returns Clean{tree} for a tree it never stored; write_commit(tree) fails ObjectNotFound#21136a235147

    Adds a linkable `write_merge_tree` API that materializes a three-way merge into the repository object database and returns the stored tree together with structured conflict and stage data. The existing prediction path remains non-persistent, while docs and the compiled merge guide now explain and exercise the distinction.

    10k merge-check grit median: 20.8 ms → 20.0 ms (4% better)10k merge-check grit peak RSS: 17,969,152 bytes → 18,075,648 bytes (1% worse)
  • ›blame places an inserted block differently from git when another line changes nearby (7-line repro)#2108f6dc0e06

    Blame now lets xdiff-style compaction place changed groups across raw common-prefix/suffix boundaries instead of freezing those lines first. It keeps that correctness affordable by diffing only the reachable window, while preserving whole-file occurrence counts and Git’s no-context common-tail cut.

  • ›grit revs / RevWalk A...B walks the whole history: 7-commit symmetric range 205 ms on cargo (git rev-list 27 ms)#2109be653775

    Default-order `A...B` walks now stop once both sides reach every merge base instead of materializing full ancestor closures. The same work also corrects criss-cross ranges by excluding all merge bases and improves merge-base traversal when only stale commits remain.

    cargo 7-commit A...B mean: 174.0 ms → 3.0 ms (58× better)cargo 1,972-commit A...B mean: 194.8 ms → 64.3 ms (3.0× better)cargo 1,972-commit A...B --count mean: 179.9 ms → 48.6 ms (3.7× better)cargo A..B control mean: 62.6 ms → 63.1 ms (1% worse)
  • ›merge: rename/rename (2 files renamed to the same path) merges cleanly and silently drops one file's content#2112c5d62c02

    This change prevents a tree merge from silently choosing one file when two logical files land at the same destination. It detects the collision before the ordinary path walk, content-merges source-side edits into renamed entries, and records both sides as the established add/add conflict shape.

    Rename-heavy grit merge --check median (30 shuffled runs): 252.7 ms → 251.3 ms (1% better)
  • ›Commit in a linked worktree with an injected RefStore advances the main worktree's branch; no public way to open one#21271a9b008d

    Linked worktrees opened over a custom or in-memory RefStore now use their own admin-directory HEAD and HEAD reflog. Commits, detach, and switch operations therefore affect the linked worktree's branch/state instead of silently moving the main worktree's branch, and embedders gain a public API to reopen linked worktrees on shared injected stores.

  • ›Windows: status/switch/stage fail entirely when one tracked file is locked by another process (git reports M, exit 0)#21073c22bb0a

    A tracked file that cannot be opened during an index-to-worktree scan is now conservatively reported as modified instead of aborting the entire status operation. Switch consequently uses its existing local-change protection, while operations that require bytes—staging that path and producing a patch—continue to fail explicitly.

  • ›RepositoryBuilder::open accepts an injected ObjectStore whose hash algorithm differs from the repo's objectformat#21308d77e4e2

    Repository open now validates every injected object store against the repository’s configured object format and returns a typed error before callers can use an incompatible ODB. Matching custom stores and ordinary files-backed SHA-256 repositories continue to open and write correctly.

    Release custom-store repository open median (15 samples, 2,000 opens/sample): 37.5 µs/open → 36.5 µs/open (3% better)
  • ›Remote::fetch/push ignore the repository's injected RefStore: tracking refs and prune written to .git on disk#2128c3808a8d

    Remote operations now honor the RefStore attached to an open Repository instead of silently reopening the git directory for local tracking refs. Custom backends receive fetched and pushed tracking tips, prune deletions, remote HEAD updates, and inspect reads without creating a competing `.git/refs/remotes` tree.

    20,001-ref no-op fetch median (system Git: 102.2 ms): 88.2 ms → 88.7 ms (1% worse)20,001-ref no-op fetch peak RSS: 29.4 MiB → 31.8 MiB (8% worse)Prune 9,999 of 20,001 refs median (system Git: 700.1 ms): 744.6 ms → 721.8 ms (3% better)Prune 9,999 refs peak RSS: 39.5 MiB → 37.3 MiB (6% better)
  • ›rebase/plan_rebase fails 'object not found: 000…0' when upstream history contains a merge of an unrelated root#2141

    Root commits encountered while scanning the onto side for already-applied patches are now diffed against an empty tree instead of treating the all-zero object ID as a real tree. This allows rebasing over histories that merged an unrelated root while preserving skip-applied behavior.

  • ›repo.reflogs() (refs/entries/query/delete/expire) ignores the injected RefStore: shows no reflog, expire prunes nothing#21310a66e23c

    Repository reflog reads, queries, deletes, expiry, and gc expiry now use the RefStore attached to the open Repository rather than reopening on-disk refs and logs. This fixes embedders using MemoryRefStore or another injected backend, while keeping files and reftable rewrites compatible with system Git.

    200k-entry bounded reflog query median: 2.5 ms → 2.5 ms (1% worse)200k-entry full reflog query median: 1,012 ms → 977.2 ms (4% better)200k-entry expire --dry-run --all median: 177.7 ms → 177.7 ms (0% worse)
  • ›switch_repository cancelled mid-checkout leaves a half-written worktree that looks like user edits; no rollback#2104ab880cf5

    Checkout application now journals every worktree mutation and rolls it back when cancellation or another error occurs, including additions, overwrites, per-file and wholesale deletions, gitlinks, sparse paths, and hard-reset early unlinks. If restoration is incomplete, callers receive a typed error with the original cause and unrestored paths; `grit switch` also converts its first SIGINT into cooperative cancellation so rollback runs.

    Same-size racy edits retained after cancelled hard reset: 5 of 60 files → 60 of 60 files (12× better)reset/hard synth smoke median wall: system Git vs branch Grit: 5.3 ms → 9.4 ms (43% worse)reset/hard synth smoke peak RSS: system Git vs branch Grit: 7,532,544 bytes → 19,582,976 bytes (62% worse)
  • ›grit-lib: no cancellation for clone/fetch/checkout/status, CLI-only uncommitted-diff logic, models not serializable#17040f9752d1

    Adds an opt-in, consistently serializable grit-lib result surface for front ends. It replaces string modes and raw identity headers with typed FileMode and Signature values, serializes errors and operation outcomes, and includes paused status/conflict state without changing grit CLI JSON output.

    status --json median, origin/main to branch (25 runs): 8.6 ms → 8.7 ms (1% worse)log --json -n 1000 median, origin/main to branch (25 runs): 18.4 ms → 18.4 ms (0% worse)diff HEAD~100 HEAD --json median, origin/main to branch (25 runs): 193.5 ms → 193.1 ms (0% better)
  • ›upload-pack v2 never sends `ready`: git fetch of 20 new commits on git/git takes 16.8 s / 298 MB (git: 85 ms / 48 MB)#2134ddc2dc6b

    Protocol-v2 upload-pack now ends negotiation as soon as acknowledged haves cover every commit want. It emits `ready`, a raw section delimiter, and the pack in one response, while preserving the existing `done` path and honoring `wait-for-done`.

    git.git 20-behind fetch wall time (current origin/main → branch): 0.900 seconds → 0.809 seconds (11% better)Protocol-v2 negotiation rounds: 2 rounds → 1 rounds (2.0× better)Have lines sent: 32 haves → 16 haves (2.0× better)End-to-end peak RSS: 99,796 KiB → 100,052 KiB (0% worse)
  • ›receive-pack rejects `shallow <oid>` command line: every push from a shallow clone fails (ssh, file, smart HTTP 500)#21362a6d54e3

    Receive-pack now recognizes a shallow client's boundary packets, exempts those boundary parents during strict loose-object ingest, and decides per ref whether accepting the push would create a new receiver-side shallow root. Ordinary depth-1 CI pushes onto a complete server now work over pipe and smart HTTP; genuinely history-truncating pushes remain refused unless `receive.shallowUpdate` is enabled.

    full one-commit push median (origin/main vs branch): 7.6 ms → 7.5 ms (2% better)shallow push median (system Git vs branch): 11.2 ms → 6.5 ms (72% better)
  • ›Tree metadata diff on 120k files uses 40 MB in grit-lib / 53 MB in grit CLI (Git: 11 MB)#208372715b73

    This change removes avoidable copies from metadata-only tree diffs. Rename detection now returns already ordered modification-only lists directly, the CLI converts entries to output rows in one pass, and parsed tree reads no longer retain a redundant raw-object cache copy.

    Loose CLI median wall time (stock Git measured at 49.04 ms): 56.5 ms → 52.5 ms (8% better)Loose CLI peak RSS (stock Git measured at 12,252 KiB): 34,196 KiB → 30,464 KiB (12% better)Public API consumer median wall time (stock Git control 48.79 ms): 53.0 ms → 51.8 ms (2% better)Public API consumer peak RSS (stock Git control 12,252 KiB): 19,720 KiB → 18,104 KiB (9% better)
  • ›One-file commit does ~2000 remote round trips when the object store is layered via OdbBuilder::push_read_source#21293bbee371

    Cache-tree validation now treats an object reachable through any configured ODB layer as reusable, rather than requiring it in the writable primary. A files-backed batched probe checks loaded pack indexes before loose paths, preserving packed-repository performance while the regression tests cover repeated commits and stash.

    Layered one-file commit remote calls, 10 directories: 25 round trips → 5 round trips (5.0× better)Layered one-file commit remote calls, 1,000 directories: 2,005 round trips → 4 round trips (501× better)Packed 50k-file grit commit median, main vs branch: 129.3 ms → 128.3 ms (1% better)Packed 50k-file grit status median, main vs branch: 40.1 ms → 39.6 ms (1% better)
  • ›After kill -9 during rebase apply, first grit status fails 'commit them before switching' and rolls the rebase back#214326624c38

    Interrupted rewrite recovery now reconstructs the pre-checkout index/worktree state before completing a checkout, so partially written files are not mistaken for user edits. Status returns success, preserves the rewritten tip when completion works, safely rolls back when it does not, and exposes finished/rolled-back/pending outcomes to embedders and CLI users.

    Debug grit status median: 16.7 ms → 16.6 ms (0% better)Debug grit/system-git status median ratio: 2.9 x → 2.9 x (0% better)
  • ›upload-pack incremental fetch on git/git: 4.4 s with a bitmap (git 21 ms), thin pack 2-7x bigger than git's#2135f9691a51

    Incremental upload-pack now derives a small set of client-held tree/blob bases from the have boundary and feeds them into the normal delta search as external-only candidates, producing compact REF_DELTA entries. It also bounds the have-side commit walk and computes bitmap reachability once, eliminating the pathological per-blob whole-bitmap scans.

    HEAD~1 bitmap latency: 3,118 ms median of 3 → 30.5 ms median of 3 (102× better)HEAD~1 bitmap response: 38,266 bytes median of 3 → 1,708 bytes median of 3 (22× better)HEAD~1 no-bitmap latency: 629.2 ms median of 3 → 16.9 ms median of 3 (37× better)
  • ›upload-pack thin pack contains a REF_DELTA whose base is the object itself: `git fetch --unshallow` fails on cargo#21473bb2023c

    This change closes a thin-pack correctness hole by refusing to use a blob already scheduled for transmission as an external REF_DELTA base. It adds a deterministic planner regression and a system-Git round trip proving `index-pack --fix-thin`, object readback, and strict fsck succeed.

    Cargo depth-3 unshallow client wall: origin/main vs review branch: 6.1 seconds → 6.2 seconds (3% worse)Cargo depth-3 unshallow client wall: system Git vs review branch: 7.7 seconds → 6.2 seconds (23% better)
  • ›grit push of a whole repo over smart HTTP peaks at 414 MB RSS on cargo (git 163 MB, 2.5x) and takes 1.4-1.6x as long#21444bc94e24

    Push pack construction now writes directly from a shared source-pack mapping into either the connection or a temporary bundle file. Large smart-HTTP request bodies cross a bounded producer/consumer channel into ureq’s chunked POST instead of accumulating in one or two full-size vectors.

    Full rust-lang/cargo initial push peak RSS (system Git measured 193.48 MB): 430.7 MB → 276.3 MB (56% better)Full rust-lang/cargo initial push wall time (system Git measured 3.133 s): 4.8 seconds → 2.8 seconds (67% better)
  • ›grit-lib: two different Conflict/ConflictKind types (status vs operation) describe the same conflict differently#2145cac7ad52

    This consolidates conflict reporting around `grit_lib::operation::{Conflict, ConflictKind}`. Status, merge, pull, sequenced pick/revert, rebase/history predictions, and stash apply now expose the same path-plus-kind shape, and all affected CLI outputs render the same direction-aware names.

    Status with 5,000 conflicts: 22.1 median ms → 19.9 median ms (11% better)Status latency gap versus system Git: 41.1 percent slower → 27.2 percent slower (51% better)
  • ›grit-lib: commit, add, stash, merge and rebase sessions take no Cancel and ignore ProgressSink::should_cancel#21426f451238

    Long-running staging, commit, stash, merge, replay, restore, and rebase library sessions now expose consistent progress and cancellation plumbing. The round-2 corrections specifically make conflict-stop publication safe for rebase and cover all stash-push reset modes, including hunk selection, pathspec, and staged-only paths.

  • ›grit-lib commit_with_scope turns HunkSelectError/ApplyError into Error::Message(String); CommitPatchError is unreachable#2160689b36ff

    Library callers now receive structured stale/unknown hunk and patch-apply failures from scoped commits instead of losing them as prose. Empty path-scoped commits also have a dedicated error variant, while rendered human messages remain unchanged.

  • ›grit push --delete A B (and --delete A plus a refspec) silently ignores B / the refspec and exits 0#2153a5195a92

    `grit push --delete` is now a mode flag whose positional refs are all planned as deletions, so no requested name is silently discarded. Mixed `src:dst` refspecs and empty delete requests fail with typed planning errors before any ref update is sent, while JSON reports one result per requested deletion.

  • ›gc --auto (auto-gc after commit) packs loose objects with no deltas: 195 MB pack vs 8.7 MB from git repack -d#2158a0c7aab8

    Automatic maintenance now delta-compresses reachable loose objects using the same streaming pack writer and pack tuning as a full repack. It keeps the incremental behavior: the new pack is self-contained, existing packs are untouched, no bitmap is written, and unreachable loose objects remain loose.

    auto-gc pack size on 25 versions of an 8 MiB asset: 200.1 MiB → 8.1 MiB (25× better)auto-gc wall time on the same fixture: 5.4 seconds → 1.8 seconds (3.0× better)branch auto-gc vs system Git wall time: 1.1 seconds (Git control → branch) → 1.8 seconds (Git control → branch) (38% worse)branch auto-gc vs system Git pack size: 16.1 MiB (Git control → branch) → 8.1 MiB (Git control → branch) (99% better)
  • ›Ctrl-C during grit clone leaves a broken destination (.git without HEAD, or files without .git) that blocks retry#2162168242b5

    Ctrl-C now requests cooperative clone cancellation instead of deleting the destination from a signal handler while clone workers are still writing. Once copy/download/checkout work has stopped and checkout rollback has completed, the CLI removes the partial destination and returns exit 130, allowing the identical clone command to be retried.

    Dist local-clone median, 166 MiB repository: 215.2 ms (7 measured runs after warmup) → 219.3 ms (7 measured runs after warmup) (2% worse)
  • ›rebase --continue and --skip never write HEAD's reflog: HEAD@{0} stays at the pre-rebase tip#21548a637481

    Resumed rebases now mirror the completed branch move into HEAD’s reflog before HEAD is reattached. Continue and skip therefore leave HEAD@{0} consistent with HEAD, while a reflog-write failure keeps the operation detached and abortable; skip also records the correct message.

  • ›grit fetch with an explicit +refs/tags/<annotated> refspec is a silent no-op: new or moved annotated tags never arrive#2157f5a37197

    Fetch matching now records whether a tag row came from automatic tag following or from a user refspec. The post-transfer retention pass prunes only automatic rows, so explicit annotated-tag destinations are created and forced refspecs can move release tags without changing normal tag-follow semantics.

    Local fetch median, 1000 commits and 400 tags: 0.111 seconds → 0.111 seconds (0% worse)
  • ›grit rebase drops earlier commits and misplaces the base when a replayed commit duplicates an upstream patch#2152a22edf9d

    Skipped commits now have two distinct destinations: the upstream equivalent remains visible in rewrite reports, while replay chaining and ref movement continue from the rewritten predecessor. This prevents earlier or later topic commits and stacked branch refs from falling back onto an old upstream ancestor.

    320-commit rebase mean, origin/main invalid result vs fix: 738.3 ms → 843.3 ms (12% worse)320-commit rebase mean, system Git vs grit fix: 1,119 ms → 843.3 ms (33% better)
other changes19
  • ›Quality #42: Dead code and dependenciesc7cf2c44

    Deletes three unused internal I/O helpers and their dead-code allowances. Keeps the existing path-display assertion, exercising the formatter used by production ref-store errors.

  • ›Speed: revs/count-author@deep-history7cc79795

    Filtered author/message counts scan commits with a reusable buffer instead of retaining commit maps. The round-two correction reads excluded parent links from the commit-graph, avoiding decompression of roughly 49,500 excluded bodies for a 500-commit range.

    revs/count-author@deep-history time (system Git 150.859 ms): 510.4 ms → 206.3 ms (2.5× better)revs/count-author@deep-history peak RSS (system Git 19740 KiB): 61,440 KiB → 25,804 KiB (2.4× better)revs/count-author-range@deep-history time (system Git 4.642 ms): 315.9 ms → 198.1 ms (59% better)revs/count-author-range@deep-history peak RSS (system Git 7208 KiB): 55,484 KiB → 26,132 KiB (2.1× better)
  • ›Quality #43: Move logic into grit-libd99b149b

    Fsck reports now offer a borrowed, typed summary containing each finding's severity and visibility plus overall integrity and warning status. The CLI uses those results, removing its own policy helpers while preserving output and exit status.

    grit-bench fsck-medium median, warmup 3 / minimum 10 runs: 211.8 ms → 213.3 ms (1% worse)
  • ›Speed: log/oneline-100@git-gitaa196422

    Pack-index lookup now predicts a row from the hash prefix, brackets the candidate with growing steps, and finishes with binary search using full object IDs. It reduces resident mapped pages on short logs without changing public APIs, output, or Git file formats.

    log/all@git-git: wall, 20 runs (Git 54.497 ms): 72.6 ms → 76.7 ms (5% worse)log/all@git-git: peak RSS (Git 18542 KiB): 33,936 KiB → 33,810 KiB (0% better)Headline direct spawn, 200 runs (Git 3.408 ms): 5.1 ms → 5.0 ms (1% better)Warm pack-index lookup: 100 real commit IDs, 20 one-million-call probes: 49.1 ns/lookup → 24.7 ns/lookup (99% better)
  • ›Perf regression 2026-10-26: add/modified@big-blobs, branch/delete@many-refs, clone/bare@synth-10k +19d2f0200d

    Changed large files are hashed and stored once, scoped commits avoid staging a throwaway index, and push selection avoids repeated scans of queued commits. Daily plans now execute real work and honor requested sample counts.

    add/modified@big-blobs wall time (Git 245.88 ms): 171.1 ms → 92.8 ms (84% better)add/modified@big-blobs peak RSS (Git 80180 KiB): 89,184 KiB → 89,908 KiB (1% worse)commit/paths@synth-10k wall time (Git 33.17 ms): 45.2 ms → 43.3 ms (4% better)commit/paths@synth-10k peak RSS (Git 17344 KiB): 27,532 KiB → 27,704 KiB (1% worse)
  • ›Speed: revs/left-right-count@deep-historya2787933

    Symmetric revision ranges reuse parent links and timestamps already parsed while resolving endpoints such as HEAD~500. The change seeds the existing repository cache up to 1,024 entries, with guards for histories whose traversal parents differ from stored parents.

    revs/left-right-count@deep-history latency (system Git 4.260 ms): 8.5 ms → 7.0 ms (21% better)revs/left-right-count@deep-history peak RSS (system Git 6950 KiB): 15,312 KiB → 15,184 KiB (1% better)revs/author-n50@deep-history latency (system Git 3.292 ms): 5.4 ms → 5.4 ms (0% better)revs/count-author@deep-history latency (system Git 157.493 ms): 205.5 ms → 206.7 ms (1% worse)
  • ›Speed: branch/rename@many-refs157db97b

    Branch rename now validates packed refs without allocating a map of unrelated entries or preparing unused replacement text. Independent measurements reproduce a 36–38% speedup and about 12% less peak memory, with compatible repository files and flat or better related timings.

    branch/contains-json@git-git-10k-refs median, 50 interleaved runs; Git 42.488 ms: 33.7 ms → 33.3 ms (1% better)branch/contains@git-git-10k-refs median, 50 interleaved runs; Git 42.278 ms: 32.6 ms → 32.6 ms (0% worse)branch/create@many-refs median, 50 interleaved runs; Git 1.836 ms: 3.1 ms → 3.1 ms (1% better)branch/delete@many-refs median, 50 interleaved runs; Git 2.073 ms: 8.6 ms → 5.2 ms (67% better)
  • ›Speed: log/stat-n50@git-git0d44b890

    Log statistics avoid a second full patch and count only the changed line region using borrowed text. My release measurements halve the target's time and reduce its peak memory, with no material timing regression in 18 other scenarios.

    log/stat-n50@git-git median; stock Git 110.001 ms: 410.8 ms → 200.2 ms (2.1× better)log/stat-n50@git-git peak RSS; stock Git 37984 KiB: 115,924 KiB → 101,444 KiB (14% better)log/all@git-git median; stock Git 56.544 ms: 70.4 ms → 69.7 ms (1% better)log/json-100@git-git median; stock Git 3.054 ms: 4.9 ms → 5.0 ms (2% worse)
  • ›Quality #37: Move logic into grit-lib1c4fdeca

    Diff target selection now lives in grit-lib and is shared by the CLI's normal and patch-text paths. The follow-up makes invalid revisions produce the same revision error whether path limits come from argv or a file.

    diff/worktree@synth-10k wall time (current main → branch): 12.9 ms → 15.0 ms (14% worse)diff/worktree@synth-100k wall time (current main → branch): 129.2 ms → 155.1 ms (17% worse)diff/worktree@deep-tree wall time (current main → branch): 401.1 ms → 395.5 ms (1% better)diff/worktree@big-blobs wall time (current main → branch): 94.6 ms → 94.2 ms (0% better)
  • ›Speed: branch/list@many-refs8da87c46

    Branch inventory shares one configuration snapshot and the existing ref store, while full packed-ref scans avoid an intermediate hash table. My release builds reproduce 7.5x faster listing of 6,667 packed local branches and 9.0x at 99,999 local branches; the daily headline moves from 1.832 to 1.743 ms. No measured latency or peak-RSS regression exceeds 5% across 17 scenarios.

    branch/list@many-refs (system git 1.049 ms): 1.8 ms → 1.7 ms (5% better)branch/list@local-6667 (system git 13.556 ms): 60.6 ms → 8.1 ms (7.5× better)branch/list@100k-local (system git 237.948 ms): 927.0 ms → 103.0 ms (9.0× better)ref/list@100k (system git 45.261 ms): 100.4 ms → 88.1 ms (14% better)
  • ›Speed: branch/list-json@many-refsc4ba99f6

    Share immutable captured environment variables when repository/config setup clones an Environment, while keeping typed overrides independent. Fresh controlled measurements reproduce a small speed improvement. This review follow-up adds a repeatable build procedure and corrects the benchmark evidence; it makes no further production-code change.

    branch JSON hyperfine (main → patch): 2.3 ms → 2.2 ms (4% better)branch/list-json@many-refs median peak RSS (origin/main → branch): 14,562 KiB → 14,068 KiB (4% better)branch/list@many-refs direct wall time (origin/main → branch): 2.2 ms → 2.1 ms (4% better)branch/list@many-refs-loose direct wall time (origin/main → branch): 2.2 ms → 2.1 ms (4% better)
  • ›Quality #44: Deduplicateb3a18044

    Patch headers and attribute patterns now share one decoder for quoted paths. Each caller retains its existing validation and malformed-input behavior.

    Production lines across the three parser modules: 3,313 lines → 3,234 lines (2% better)add/patch-file@synth-10k (system Git 8.003 → 7.838 ms): 8.9 ms → 8.4 ms (6% better)restore/paths@synth-10k (system Git 17.517 → 17.371 ms): 15.0 ms → 14.5 ms (3% better)
  • ›Quality #45: Simplifyd21cd350

    This replaces duplicated, numeric-state, manually indexed trailer handling with shared typed helpers and iterator-based scans. It keeps the public API and CLI unchanged, removes 333 production-library lines, and adds broad comparisons against system Git for trailer placement, config, sign-off, and cherry-pick message rewriting.

    commit/small@small median wall (60 runs): 4.9 ms → 4.7 ms (4% better)commit/small@small peak RSS: 16,531,456 bytes → 16,470,016 bytes (0% better)pick/one@synth-100k median wall (10 runs): 141.9 ms → 138.5 ms (3% better)
  • ›Speed: log/author-n50@deep-history3681c177

    This change reduces bounded author/committer/message-filtered log work in two places: it compiles byte-oriented matchers without the expensive Unicode-dot cache/CPU probe, and it reuses commit bytes already read during traversal for filtering and rendering. It keeps the optimization inside grit-lib and adds unit, Git round-trip, storage-format, and Criterion coverage.

    log/author-n50@deep-history median wall (system Git 1.332 ms): 2.9 ms → 2.8 ms (3% better)log/author-n50@deep-history peak RSS (system Git 6,934,528 bytes): 14,438,400 bytes → 14,544,896 bytes (1% worse)log/author-n50@deep-history-cg median wall (system Git 1.564 ms): 3.0 ms → 2.8 ms (9% better)log/author-n50@deep-history-cg peak RSS (system Git 10,371,072 bytes): 17,063,936 bytes → 16,777,216 bytes (2% better)
  • ›make cursor shorterd76c80b5

    Makes paged log continuation tokens repository-local and compact while keeping ordinary human/Markdown log reads non-mutating. It also removes the redundant “change” label from display and makes Unicode graph lanes the default, with explicit ASCII fallback.

    JSON continuation cursor length: 748 characters → 14 characters (53× better)
  • ›Speed: branch/merged@many-refs39a3db1b

    This resolves each distinct branch tip once during merged/contains filtering and reuses that commit ID throughout the reachability walk. It also avoids duplicate loose-ref/reflog scans in main worktrees and snapshots the CLI process environment once after global arguments are applied.

    branch/merged@many-refs median wall (100 rotating runs): 3.3 ms → 3.2 ms (3% better)branch/merged@many-refs median peak RSS: 15,086 KiB → 15,340 KiB (2% worse)branch/list@many-refs median wall: 2.8 ms → 2.8 ms (2% better)branch/list-json@many-refs median wall: 3.1 ms → 3.2 ms (1% worse)
  • ›Quality #46: Library API quality684152c9

    Repository discovery failures now carry a structured `NotARepositoryReason` rather than an opaque string. Callers can distinguish absence, malformed/special gitfiles, and read failures without matching display text, while the CLI-visible wording remains unchanged.

    resolve HEAD~20 median, grit dist: 2.1 ms → 2.0 ms (5% better)resolve HEAD~20 median, system git control: 1.3 ms → 1.4 ms (3% worse)
  • ›Quality #47: Move logic into grit-libae85d182

    Batch note-removal previews now compose every requested removal against one in-memory notes tree and return the exact commit id that the real batch write produces. The CLI consumes that typed plan directly, and markdown dry-runs clearly use future-tense wording.

    notes add daily median (mean of two 10-run medians): 3.3 ms → 3.2 ms (5% better)notes list daily median (mean of two 10-run medians): 2.4 ms → 2.4 ms (2% better)50-object remove dry-run on 1,000-note repo: 102.7 ms → 11.7 ms (8.8× better)
  • ›Quality #48: Dead code and dependencies11057196

    Removes 17 unused public `grit-lib` items plus three unused `grit-test-support` helpers, mostly remnants of the retired compatibility CLI and dropped commands. It also removes `terminal_size` from grit-lib and simplifies the test pack builder now that its unused omit-trailer mode is gone.

    diff/stat@synth-100k median (latest main vs mean of bracketing branch runs): 72.9 ms → 73.5 ms (1% worse)diff/worktree@synth-10k median (latest main vs mean of bracketing branch runs): 6.6 ms → 6.9 ms (4% worse)Tracked diff size: 359 added-equivalent lines (removed vs added) → 7 added-equivalent lines (removed vs added) (51× better)
$ git log --oneline a3300042..v0.5.23compare on GitHub ↗
20bd7b9bName the UnrelatedHistories and ObjectFormatMismatch error kinds
84fdd17eSerialize commit, switch, reset, fetch, push, stash and rebase results
12076260Add Error::kind_name and serialize Error as kind and message
ee314617Give LoadedCommit typed author and committer signatures
e78886c5Type DiffEntry modes as FileMode instead of octal strings
ab880cf5Keep unstaged edits when a cross-tree hard reset is cancelled
a3aa61e7Record Error::CheckoutRollbackIncomplete in the public API snapshot
405e038fPack the checkout journal's created paths into one buffer
278e1756Keep the delete spool when a rollback cannot restore from it
f5d875cfLet Ctrl+C cancel grit switch so the checkout rolls back
a8eb0f81Document that a stopped checkout leaves the repository unchanged
c9f4e700Roll back the work tree when a checkout fails or is cancelled
4e17df00Update grit-lib tests for Git 2.56 and bare-remote current-branch deletes
bd029617Advertise object-info=size type, as Git 2.56 does
1ade4f4aStage stored paths under their raw bytes
0a66e23cKeep full files-backend reflog reads as fast as before
09b96c65Route repo.reflogs() through the repository's ref store
bf764cbaGive custom ODB primaries an empty promisor boundary
180e7c2bRead files-backend reflogs newest first without loading the whole log
d915f9baMerge pull request #2146 from schacon/detect-copies-source-mode
684152c9Merge branch 'factory/typed-not-a-repository'
6c22f85eType NotARepository errors with a reason enum instead of a message string
c597d77aDiff root commits against the empty tree in rebase cherry detection
06ef3c25List commits in --markdown for log --graph --oneline
c542ab13Give checkout_cli's git commit its identity through the environment
c3808a8dKeep fetch, push and remote tracking refs in the repository's ref store
a953be13Keep CI merge status to the fast checks
8d77e4e2Merge branch 'factory/odb-object-format-mismatch'
8634775fCheck injected store formats against the config snapshot open already loads
a96a310cReject injected object stores whose hash algorithm differs from the repository
19cfb4e0Count path revisions from the fixture HEAD
60c45e3dReset the push/refspec branch and clone outside the client repo
1681979aPrepare the git.git fixture in area_filter_selects_area
06293b97Fix the ignore/check-1000 and remote/rename daily prepares
2a25d707Unstage large.txt in the add/lines and add/hunks prepare steps
4d09411bMake the history-rewrite bench scripts portable to macOS
833e1ecfExempt the serve and checkout-stack commands from the daily matrix
7046f8beRun grit-utils tests one at a time under nextest
0d68a041Print a blank line between commits in log -p with full headers
ac116accPage the log bench with --cursor
446efa1cBuild grit for the tag/tree SHA-256 scenario test
6ce575baSync MATRIX.md with the scenario registry
d515910cRestore the daily plans dropped with the --hunks change
39a3db1bMerge branch 'factory/branch-merged-tip-dedup'
b06ce9dbUpdate git-compat tests that predate deliberate behaviour changes
6b3addd7Leave hunkless file diffs out of a fence in --markdown
ea01ab36Release a streamed pack entry's mapped pages as it is read
1a8a5975Walk each first-parent spine once across tips in --simplify-merges
e5a364d9Decode stored non-UTF-8 paths when deleting and staging
bd402b5bStore reftable reflog time zones as Git does
77490c03Fix partial-clone and child-process tests for the current layout
707a24e4Serve object-info only with transfer.advertiseObjectInfo, like Git
bbd05fd4Ask v2 ls-refs only for the refs a fetch's refspecs can match
c7ad8860Leave a have commit's trees out of filtered packs
e4e9130fExpect local clone and fetch to hard-link loose objects
d2d1a715Date history_undo's dropped tip now, so git gc keeps its reflog entry
a1a53397Run git in each test's own repository, not the crate directory
ac6d6cf8Keep a rescued pack base's deltas when its own entry is corrupt
3c22bb0aMerge branch 'factory/status-unreadable-file'
a8da80b6cli: read the process environment once per run
88ce3670refs: walk loose refs once in a main worktree
4f893536refs: resolve each ref tip once in reachability filters
4f6a285btests: register the unreadable tracked file status tests in the integration binary
40439e32status: report an unreadable tracked file as modified instead of failing
1a9b008dGive linked-worktree handles over injected stores their own HEAD
c4038042Write a linked worktree's HEAD and HEAD reflog to its admin dir over injected ref stores
c5d62c02Document and check the add/add conflict for colliding renames
023793daKeep both files when a rename lands on a path the other side filled
be653775Merge branch 'factory/symmetric-range-frontier'
d76c80b5Merge branch 'factory/log-cursor-short-3da4'
4b37cdf2Merge branch 'factory/home-cli-demo'
521bf8b7Walk A...B down to the merge-base frontier
4600b5abExclude every merge base when expanding A...B
8b74be81Stop the merge-base walk once only stale commits are queued
17bf7238site: cycle clone, switch and commit examples on the homepage
f6dc0e06Merge branch 'factory/blame-compaction-placement'
01058760Only persist log cursors when the token is exposed
b3b39764Document short log cursor APIs in public-api.txt
bfaa7276Shorten grit log cursors and polish graph output
f4d1335bblame: place hunks the way git blame's xdiff does
6a235147Merge branch 'factory/write-merge-tree'
5e7a6e80push: walk history through the commit-graph
efab400cDocument predict_merge versus write_merge_tree and use it in the merge guide
bf24dde6Add write_merge_tree to store a three-way merge result
fdd72fdbMerge branch 'factory/receive-pack-fsck'
02be7651receive-pack: honor receive.fsckObjects and transfer.fsckObjects
44f9e34cfsck: per-message policy for checking received objects
ca1b498cReport source modes on copies when no source tree entries are given
0c5982a6Merge branch 'factory/revs-count-paint'
1c964bc6Merge pull request #2137 from schacon/ignore-pattern-list
8bcf7d7cDocument ignorecase staging speed on the issue's 48k-file tree
55650bf0Benchmark add and add -u with the macOS path config daily
ed6c01afTest ignorecase staging of case-only renames and its cost on 48k files
374ac90bPrune untracked directories against literal pathspecs without allocating
77bba63fSkip the precompose lookup for ASCII worktree paths
75322c83Answer exact ignorecase spellings from cached listings without allocating
ec05183aMerge branch 'factory/revs-count-paint'
1224dcfcDocument single-walk range counts and record their benchmarks
8ddcb1d7Count revision ranges with one hide paint instead of per-commit ancestry checks
cf774fc0Add IgnorePatternList for matching single paths against an exclude file
d4988e6cStrip at most one trailing CR from ignore file lines
c120c8f8Merge branch 'factory/local-transport-reachable'
ecc581c6Merge branch 'factory/windows-verbatim-paths'
a208cf73Store plain Win32 paths on Repository instead of verbatim \\?\ paths
02db7816tests: register local_transport_reachable in the integration binary
5383045btransfer: send only reachable objects over local and file:// transports
5ebe1d90Merge branch 'factory/from-process-options'
8295418dOpen user repositories with from_process in examples and docs
97e80107Add RepositoryOptions::from_process for embedders that must match git
4da3f963Merge branch 'factory/push-tip-boundary'
03e67442Record one-commit push benchmarks over ssh, git:// and HTTP
3e08d935Seed push thin-pack bases from edge commits, not every advertised tip
5ea72e57Look up few pack objects instead of scanning the whole index
7c200d56Buffer git:// and ssh transport reads
4d0ac8efOpen pack bitmaps without reading every pack index
3681c177Compile commit filters without UTF-8 cache or CPU probing
4deaa787Reuse traversal bytes for bounded filtered log walks
8249b714Merge branch 'factory/pre-push-hook'
ba25c79cpush: ignore SIGPIPE while pushing so a hook that skips stdin cannot kill grit
6fe2a178docs: describe the pre-push failure JSON inline and refresh the skill snapshot
76a297b3push: run the pre-push hook before sending anything
12ac726bhooks: resolve a relative core.hooksPath against the work tree top
1dea9fdeMerge branch 'factory/grit-checkout'
d21cd350Register trailer compatibility tests in consolidated suite
a7dbe425List the trailer comparisons in the testing coverage table
f5868c6eSimplify sign-off and cherry-pick trailer handling
f232da42Simplify interpret-trailers parsing and placement
d5804f37Compare trailer rewriting with git across placement, config and output options
f5ab536eDon't mark tests that are already #[ignore] as full-only
544470d4Keep the checkout stack's tests within the fast run and the test guards
2bf39ca9Count a branch a worktree is rebasing or bisecting as checked out there
2af3a57aMerge a path one side turned between file and directory cleanly
61db7deeShare server branches with checkouts: graft log, projection and grit pull <branch>
5d551e18Read reflogs that are not UTF-8, and append to them instead of rewriting
5df29fa4Give commits made with git change ids; accept rebases that keep every commit
76e15355Integrate moves you off landed work instead of replaying it
ab5ffa8eGuard served target branches; integrate and slices take turns and move the worktree
45e03bd8Checkouts fetch and push only snapshots; refresh runs in grit-lib
c99b9051Make server check-ins race-safe and grafts keep the target's work
a6f1daefRebase pulls keep local commits under a merge of upstream
048f2e1dAdd grit checkin, integrate and slice; grit pull refreshes checkouts
805c9f5eCheck in, integrate and slices for snapshot checkouts
0fd4b00dAdd grit checkout: snapshot checkouts from grit serve
70e8a08eShow resumable bundle transfers in grit clone and grit push
33f6eb29grit serve: background clone bundles and a resumable push endpoint
b7273fb7Resumable transfers: bundle-uri clones and TUS push bundles in grit-lib
35eaceb7Sign in to grit serve in the browser with email and password
a21fc18cSign in to grit serve hosts with grit auth <url>
1b3a8e85Send credential helpers protocol and host, not the request URL
5214b068Add grit serve: token-authenticated smart HTTP server with a web view
76265be0Keep auth_logout_cli off the macOS keychain
159bc776Cache directory listings for ignorecase spelling lookups
0f5bea28path_validate: skip .git alias checks for names that cannot spell one
4d0adb35path_validate: treat git~1 followed by spaces, periods or a stream as .git
c5572702Register the index lock test in the integration test crate
01e5937cTake index.lock before stash, reset, switch and restore touch the worktree
385ebcb8Split tests into a fast default run and a nightly full run
3f56865cBuild each crate's integration tests as one test binary
d86a3165CI: run every test with nextest, keep caches fresh, run test-threaded nightly
633b2314Run workspace tests with nextest in make test and the gate
806730a9Keep Git's background maintenance out of reset and commit unit tests
bd97831cStop a transport_path test from moving the whole test process
2a90799dRotate filters through the rev-list option sweep; keep the full product opt-in
0e2decd9Reuse the built grit-http-server in grit-cli tests instead of rebuilding it
004f20afDrop legacy_examples_build: cargo test already builds the examples
c2d04970Lock heavy-disk tests with File::lock instead of flock(1)
ccced87fRoute new pack-index, loose-path and SHA-1 uses through their abstractions
e099381fFix tests and checks that fail on main
6be9ffe0Merge branch 'factory/revs-graph-range'
d05c3fbfRecord revision range count benchmarks and regression coverage
567b2c37Bound graph-backed revision counts by excluded ancestry
f4803b51Merge branch 'factory/site-deploy'
1e4662d9site: upgrade Next.js to 16.4.3
6d8defcfdocs: drop rustdoc link to a feature-gated method
b6f94d89Merge pull request #1233 from jay23606/fix/1229-markdown-mode-rename
ad7f5106Merge branch 'factory/startup-relocations'
bd96ae08Record startup regressions in the reviewed binaries
3f92a6b3Keep GNU installers on the stock artifact
b0171ab6Ship an optional x86_64 GNU RELR artifact
edb77eb4Measure PIE startup and preserve GNU loader compatibility
d4076369Merge branch 'blog-since-0-5-0'
13c3db53blog: what grit shipped since 0.5.0
17fbe0b3Merge branch 'factory/ntfs-path-1699'
23fb9ba8Review: update public-api snapshot; fix local push policy ODB lookup
362385d5Fix Windows NTFS path validation on clone/checkout
73488424Fixes #1933: enforce receive policy on local-path push
b3a18044Share C-style quoted-path decoding across parsers
58029b75Merge branch 'factory/blame-pack-memory'
c14e5840Record ranged blame integration validation
11c42223Bound retained pack readers during ranged blame
49a6a4a1Bound pack residency during ranged blame
c4ba99f6Record isolated branch snapshot performance
ebf56c21Record environment snapshot lifetime and memory validation
a8622709Record branch JSON timing and memory comparisons
b83d1422Share captured variables across environment snapshots
8da87c46Record controlled branch inventory benchmarks and regression evidence
436be9baRecord branch inventory timing and memory comparisons
f90a8a15refs: preserve packed-ref order when building caches and validate scan boundaries
df2b72a5refs: fall back to a whole-file scan when a sorted packed-refs range is out of order
c45a1a68branch list: stop re-parsing config and reopening the ref store per listing
1306f22eMerge branch 'factory/sirocco-inflate'
1c4fdecadiff: preserve revision errors with pathspec files
d020c906diff: make grit diff a thin layer over resolve_diff_request
f5327e2bdiff: resolve diff operands in grit-lib with typed errors
ca37a316Evaluate Sirocco decompression while retaining flate2
0d44b890Document approved log statistics tradeoff and review timing checks
4df7dafaRecord log statistics performance and regression measurements
06ec2a1fReduce log statistics tokenization and duplicate diff work
157db97bAvoid materializing packed refs during branch rename
a2787933Reuse parsed ancestor links for symmetric revision counts
d2f0200dRecord controlled regression benchmarks and streaming guards
a9990586Repair daily benchmark operations and honor minimum sample counts
35b0906dTrack the interesting push frontier without rescanning queued refs
6c09c2e0Validate commit pathspecs without staging a discarded index
8b6fc518Avoid hashing size-changed streamed blobs twice
6be1920cMerge branch 'factory/stash-pop-memory'
eff43375Bound cached pack descriptors under file-limit pressure
29610c87Record bounded-log memory and clone measurements
300656c8Bound tag peeling memory and pack imported clone refs
b747e73dPreserve raw path identity in sparse stash apply
3dbd4372Reduce stash apply memory on wide trees
5ea10156Protect sparse reset cleanup from replaced ancestors
a08eab73Measure sparse reset and switch at monorepo scale
aac06466Keep unchanged sparse trees opaque during reset and switch
9e6a6be2Bound tree metadata retained during diffs
ea7901dcreset: record bounded orphan-report benchmarks
c90c90f2reset: document advisory orphan counts and stabilize benchmarks
3048c54corphans: end the left-behind walk by commit date without a commit-graph
78b4c0ccgrit-bench: add reset/undo-commit@git-git daily scenario
ebef7533tests: index pack_write_parallel packs in a scratch repository
e98de8a1Negotiate atomic transactions for wire pushes
3c1a41efPreserve tracked edits from successful rebase exec commands
aa196422Reduce mapped pack-index probes for short history walks
b4e048f1Track originating paths through affix-only blame renames
02e8900bFix parallel worktree symlink comparisons
b8394eb0Reuse aggregated line weights for inexact rename detection
d989c8feReport completed rebase HEAD transitions
d99b149bMove fsck diagnostic summaries into grit-lib
80dc322fPreserve available promised objects during maintenance
15327500Keep partial-clone maintenance offline
7cc79795Record filtered range count timing and memory comparisons
9f0e675dUse commit graphs for filtered revision exclusions
7096f3aeRecord filtered revision count timing and memory comparisons
51138609Count filtered revisions in one pass without retaining commit maps
09fd2e05Merge branch 'factory/midx-memory'
e6b95326Merge branch 'factory/branch-delete-errors'
cb8909afBound multi-pack-index preparation memory
c7cf2c44Remove unused storage-layout I/O adapters
aa0ffbc6Clarify checked-out branch deletion error contract
c7b0250ffix(markdown): show mode and rename info for hunkless file diffs