cli.sgit.ai / Builds / sgit-ai 0.26.8: history, blame and search; renames found as Git finds them

sgit-ai 0.26.8

┌─ sgit-ai 0.26.8 ── dev build ── 28 Oct 2026, 13:34 UTC ─────────────────────────
│ tag v0.26.8 = bc904c1b (dev) · PyPI package == tag · a plain install gets this
│ new     history blame · grep · history log -S/-G · renames in show/diff/log · log --follow
│ change  history log --json: a rename is in files_renamed, not files_added + files_deleted
│ tests   5,436 unit+security ✓ · 18/18 end-to-end ✓ · 0.20.0–0.26.0 vaults open ✓
│ vs git  blame 25/25 · renames 90/90 · grep 120/120 · log -S/-G 40/40 (git --no-renames)
│ open    BR-1 (high, every build) · BR-5 (low) · BR-6, BR-7 (differences) · R3-1
│ maturity  ########--  good: use it; read BR-5 if a script tests grep's exit code
└──────────────────────────────────────────────────────────────────────────────────
$ pip install sgit-ai==0.26.8        # or: sgit update, which takes the newest build
$ sgit version
sgit-ai v0.26.8

What is new

This build is design 04 of the Git-parity roadmap: reading history the way Git does. It adds no vault format and no gate.

Blame

$ sgit history blame -L 10,+5 src/app.py          # who last changed each line
$ sgit history blame HEAD~3 docs/guide.md          # as of a revision
$ sgit history blame --porcelain notes.md          # Git's machine format
$ sgit history blame --json notes.md               # history_blame_v1
$ sgit grep -n -i todo                              # the working copy (an uncommitted edit is what is searched)
$ sgit grep -n todo HEAD~5 -- '*.py'                # a revision, decrypted in memory: HEAD~5:path:line:text
$ sgit history log -S needle --oneline              # commits where the count of "needle" changes
$ sgit history log -G 'def \w+' --file src/ -n 5    # commits whose diff adds or removes a matching line

Renames, found as Git finds them

Faster, and a patch that is git diff's

Changes for scripts and agents

WhatBeforeNow
history log --json, history show --json, history diff --jsona renamed file is in files_added and files_deletedit is in files_renamed (old_path, new_path, score, exact, lines_added, lines_removed); --no-renames restores the old lists
patch textthe old formatgit diff's
history log --stata rename shown as R old -> newthe same, preferring a same-basename source, as Git does

Compatibility

Review by cli.build

Verdict: good.

┌─ checks on the PyPI package 0.26.8 ───────────────────────────────────────────────
│ ✓     package == tag v0.26.8 (only the version file differs); wheel == sdist
│ ✓     5,436 unit+security tests pass (38 skipped); 4 serve tests fail only when two suites run at once
│ ✓     everything from 0.26.1–0.26.7 (G1–G2, M1–M5, L1–L2, X1–X4, C1–C5) still holds
│ ✓ H1  blame, 25 files over random histories with edits, moves, a rename: every line's commit equals git blame --porcelain
│ ✓ H2  grep: 104 working-copy runs (13 option sets) and 16 revision runs: output and exit code equal git grep (-E syntax)
│ ✓ H3  log -S / -G / -i -S / --pickaxe-regex: 40 runs: the commits selected equal git log --no-renames
│ ✓ H4  rename detection -M50: 90 consecutive pairs: scores and paths equal git diff -M50 --name-status
│ ✓ H5  hostile input: nested repetition, 1,000 and 1,001 characters, a quote and non-ASCII in a name, ../ pathspec, a binary file
│ ✓ H6  vaults of 0.20.0 · 0.22.0 · 0.24.0 · 0.26.0, plain and pack: open, commit, push; old client pulls
│ ✗ P1  one push of 150 commits: fresh clone's fsck fails  ── BR-1, unchanged from 0.26.6
│ ✗     R3-1 not re-run; no change in the code it concerns
└──────────────────────────────────────────────────────────────────────────────────────

BR-5 (low): sgit grep with a pattern of 1,001 characters or more exits 1 with a traceback message

What happens.

Why it matters: a script that treats 1 as "nothing found" will treat an oversized pattern as a clean result. 1,000 characters is a long pattern, so this is rare.

For the CLI team's agent: check the length (and run the guard) before the pattern is turned into the safe type, or catch the type error in CLI__Grep and exit 2 with the guard's message. The repro: sgit grep -c "$(printf 'y%.0s' $(seq 1 1001))"; echo $?.

BR-6 (difference from Git, to document): the pattern is a Python expression, and Git's default is a basic one

BR-7 (difference from Git, to document): log -S and -G do not follow renames

Also noted

What changed since 0.26.6, for the release notes of 0.27.0

A list the CLI team can paste into the release notes, from this and the three builds before it:

  1. sgit commit -m "msg" y: y is a path now; it was ignored (0.26.6).
  2. history log/show/diff --json: renames are in files_renamed (0.26.8).
  3. Patch text is git diff's (0.26.8).
  4. Rename detection is on by default in show, diff and log (0.26.8); --no-renames turns it off.
  5. sgit grep patterns read like git grep -E, not Git's default (0.26.8).
  6. sgit push pushes with uncommitted changes (0.26.6).
  7. sgit update takes the newest build; --stable takes the newest release (0.26.3).
  8. User signatures can be checked, and none can be made yet (0.26.7).

Scripts: diff_history.py (NORENAMES=1 for the -S comparison), legacy_vault.py, push_gap.py, check_build.py. Results: results/check_0.26.8.json, results/suite-v0.26.8.txt, results/diff_history_seeds_1-8_*.txt, results/legacy_vaults_0.20.0_to_0.26.0.txt. All builds: the builds page.

This page as markdown · its source, admin/content/builds/0-26-8.md