# sgit-ai 0.26.3: Git-parity phase 0, merges made safe, and dev builds on PyPI, cli.sgit.ai

> Dev build of 28 October 2026, from the CLI's dev at 16c46e89, and the first published as a plain version. It fixes the bugs the seven Git-parity designs found. sgit commit during an unresolved merge put the .conflict files into the vault; it now refuses. status shows a merge in progress. Identical content on both sides is no longer a conflict. Merges and pushes on forks deeper than 200 commits work. A nested vault is never committed. Object files are written atomically. Merges, writes and sparse commits rebuild only the changed folders. From this build, every dev merge is published as X.Y.N, and a plain pip install takes the newest. Reviewed by cli.build. 4,921 tests pass and every fix held, including a 250-commit fork that 0.26.1 merged against an empty base. Maturity good. One decision for Dinis Cruz: plain installs now get dev builds (BR-4).

*Source: <https://cli.sgit.ai/builds/0-26-3.html> · generated from the same content as the page, so the two cannot drift.*

---
# sgit-ai 0.26.3

```text
┌─ sgit-ai 0.26.3 ── dev build ── 28 Oct 2026, 11:02 UTC ─────────────────────────
│ tag v0.26.3 = 16c46e89 (dev) · PyPI package == tag · the first plain X.Y.N
│ fixed   commit in a merge · status · equal content · deep forks · nested vault
│ tests   4,921 unit+security ✓ · M1–M5 ✓ · 250-deep fork: 0.26.1 ✗ → 0.26.3 ✓
│ decide  BR-4: a plain install now takes dev builds
│ maturity  ########--  good
└──────────────────────────────────────────────────────────────────────────────────
```

## What is new {#new}

From the [Git-parity designs](../research/git-parity-designs-index.md). These fix bugs in today's code and ship before any new feature.

- **`sgit commit` during an unresolved merge** used to go ahead as a single-parent commit. Every teammate who pulled received the `.conflict` copies. It now refuses, naming each file and the way out:
  - edit the file and delete its `.conflict` copy;
  - `sgit resolve <file> --ours` or `--theirs`;
  - `sgit merge-abort`.

  `--amend` refuses too.
- **`sgit status` shows a merge in progress:** which files are still conflicted, which are resolved, and how to finish or abandon it.
- **One rule for "an operation is in progress".** During a merge with conflicts, `write`, `vault stash`, `branch switch` and `branch checkout` are refused by name, as Git refuses them.
- **The same content on both sides is no longer a conflict.** Blobs are encrypted with a random IV, so two clones writing the same bytes used to get different ids. Now equal hash and size select the candidates, and the decrypted bytes decide.
- **Forks deeper than 200 commits.** The merge base and the ahead/behind counts looked at 200 ancestors at most. On a deeper fork a pull merged against an empty base, and a push more than 200 commits ahead was rejected as diverged. A commit graph (Git's paint-down walk) removes the cap.
- **A nested vault is never committed.** A folder holding its own `.sg_vault` is skipped, as Git skips a nested repository, and `status` names it (TM-F38).
- **Atomic object writes** (TM-F39).
- **Merges, `sgit write` of one file, and sparse commits build only the changed folders.** The CLI team measured 3.13 s → 0.13 s on 10,000 files in 10,222 folders.
- **Dev builds on PyPI as plain versions,** and `sgit update --stable`. See [Which build you get](../builds/index.md#channels).

## Review by cli.build {#review}

**Verdict: good.** Every fix held. The deep-fork fix is real: at 250 commits on each side, 0.26.1 conflicts on every file both sides changed, and this build merges cleanly.

```text
┌─ checks on the PyPI package 0.26.3 ───────────────────────────────────────────────
│ ✓ M1  commit during a merge: refused (Vault__Merge_Unresolved_Error)
│ ✓ M2  status: merge_in_progress, merge_conflicts, merge_markers, …
│ ✓ M3  the same bytes on both sides: no .conflict
│ ✓ M4  fork 250 deep each side, pushed 50 at a time: clean, both changes applied
│ ✓ M5  a clone nested in the working copy: never reaches the vault
│       fork, 250 deep:   0.26.1  ✗ a/x.txt=0, 2 conflicts    0.26.3  ✓ a/x.txt=250
└────────────────────────────────────────────────────────────────────────────────────
```

The M4 check pushes 50 commits at a time. One push of 250 hits a different bug, which is in every build: [BR-1](../builds/0-26-6.md#br-1).

### BR-4 (decision): a plain `pip install sgit-ai` now installs dev builds {#br-4}

- **What the code does.** From this build, dev builds go to PyPI as plain versions, so PyPI's "latest" is the newest dev build: 0.26.6 today. `pip install sgit-ai` and `sgit update` install it, and the CLI's README says so.
- **The conflict with the stated intent.** If the intent is that a plain install gets the release and agents opt in to dev builds, this does the opposite. Every agent that runs `sgit update` is on a dev build an hour after it merges.
- **The two ways out:**
  - **Keep it.** Dev builds are tested before they publish, and a plain install has the newest fixes. State it on every release page, and pin releases with `==X.Y.0` or `sgit update --stable` where stability matters.
  - **Make dev builds pre-releases again,** as `0.26.1.dev0` and `0.26.2.dev0` were. A plain install then gets `X.Y.0`, and `pip install --pre sgit-ai` or `sgit update --pre` gets dev. Pip ignores pre-releases unless asked, so this is the only way PyPI can serve both.

*Scripts: `check_build.py`, `deep_fork.py` (`BATCH=50 python -I deep_fork.py 150 250`). All builds: [the builds page](../builds/index.md).*

---

*[Site index for agents](../llms.txt) · [HTML version](https://cli.sgit.ai/builds/0-26-3.html)*
