Repository navigation
Git3 Compat + gix speedup for GitPython - #2274
Merged
Merged
Conversation
1 task
Byron
force-pushed
the
gix-backend
branch
4 times, most recently
from
October 7, 2026 13:25
594e7dd to
105114d
Compare
Byron
pushed a commit
that referenced
this pull request
Oct 7, 2026
PR #2274's Python 3.12 CI jobs spent 57m 25s in Windows `pytest` versus 5m 2s on Ubuntu, with 85,777 and 82,683 `Git.execute` launches respectively. A local profile of the file-handle and recursive submodule regressions spent about 65 of 77 seconds executing Git, including 44 seconds in repository construction. Repeated process startup makes the separate metadata probes expensive. Query reference format, object format, bare status and the absolute common directory in one `git rev-parse` call on the CLI construction path. Keep the path last and split only the three fixed scalar fields so embedded newlines remain intact. Git still computes every value. Supported Gix discovery keeps its native metadata and existing CLI format-validation query, with unchanged native launch ceilings and fallbacks. The focused selection drops from 2,447 to 2,009 launches: three saved for each of 146 repository opens. Three paired Windows measurements of 20 opens each reduce the median from 300.74 ms to 221.18 ms per open, with matching metadata and 11 versus eight launches. Add `--durations=30` to CI so future slow tests are visible, and record the profiling evidence and reproduction requirements in `doc/gix-backend.md`. Cover both object formats, both reference formats, bare and non-bare repos, spaces and embedded newlines. The eight applicable Windows cases fail before the fix and pass afterward; all 16 cases pass on Ubuntu WSL. The optional Windows Gix selection reproduces the same 17 failures on the original and patched sources. Document the demonstrated path-formatting and undecodable `commondir` differences under `GIX-14`, distinguishing them from Windows test assumptions. Keep these bugs open pending compatible upstream behavior. Validation: the full Windows CLI suite passes with 1,662 passed, 60 skipped, nine expected failures, two unexpected passes and 40 passing subtests. It records 77,732 launches in 3,715.16s. The initial baseline records 86,032 in 3,990.28s; its only two failures pass on unchanged code after restoring CI's `core.autocrlf=true` and placing `pytest`'s temporary directory outside a Git checkout. The overlapping full runs are not a controlled elapsed-time comparison. Repository-wide Ruff lint/format, all pinned pre-commit hooks, `mypy` (47 files), `basedpyright` (zero errors or warnings), the Sphinx HTML build and `git diff --check` pass.
Byron
pushed a commit
that referenced
this pull request
Oct 8, 2026
PR #2274's Python 3.12 CI jobs spent 57m 25s in Windows `pytest` versus 5m 2s on Ubuntu, with 85,777 and 82,683 `Git.execute` launches respectively. A local profile of the file-handle and recursive submodule regressions spent about 65 of 77 seconds executing Git, including 44 seconds in repository construction. Repeated process startup makes the separate metadata probes expensive. Query reference format, object format, bare status and the absolute common directory in one `git rev-parse` call on the CLI construction path. Keep the path last and split only the three fixed scalar fields so embedded newlines remain intact. Git still computes every value. Supported Gix discovery keeps its native metadata and existing CLI format-validation query, with unchanged native launch ceilings and fallbacks. The focused selection drops from 2,447 to 2,009 launches: three saved for each of 146 repository opens. Three paired Windows measurements of 20 opens each reduce the median from 300.74 ms to 221.18 ms per open, with matching metadata and 11 versus eight launches. Add `--durations=30` to CI so future slow tests are visible, and record the profiling evidence and reproduction requirements in `doc/gix-backend.md`. Cover both object formats, both reference formats, bare and non-bare repos, spaces and embedded newlines. The eight applicable Windows cases fail before the fix and pass afterward; all 16 cases pass on Ubuntu WSL. The optional Windows Gix selection reproduces the same 17 failures on the original and patched sources. Document the demonstrated path-formatting and undecodable `commondir` differences under `GIX-14`, distinguishing them from Windows test assumptions. Keep these bugs open pending compatible upstream behavior. Validation: the full Windows CLI suite passes with 1,662 passed, 60 skipped, nine expected failures, two unexpected passes and 40 passing subtests. It records 77,732 launches in 3,715.16s. The initial baseline records 86,032 in 3,990.28s; its only two failures pass on unchanged code after restoring CI's `core.autocrlf=true` and placing `pytest`'s temporary directory outside a Git checkout. The overlapping full runs are not a controlled elapsed-time comparison. Repository-wide Ruff lint/format, all pinned pre-commit hooks, `mypy` (47 files), `basedpyright` (zero errors or warnings), the Sphinx HTML build and `git diff --check` pass.
Byron
pushed a commit
that referenced
this pull request
Oct 8, 2026
PR #2274's Python 3.12 CI jobs spent 57m 25s in Windows `pytest` versus 5m 2s on Ubuntu, with 85,777 and 82,683 `Git.execute` launches respectively. A local profile of the file-handle and recursive submodule regressions spent about 65 of 77 seconds executing Git, including 44 seconds in repository construction. Repeated process startup makes the separate metadata probes expensive. Query reference format, object format, bare status and the absolute common directory in one `git rev-parse` call on the CLI construction path. Keep the path last and split only the three fixed scalar fields so embedded newlines remain intact. Git still computes every value. Supported Gix discovery keeps its native metadata and existing CLI format-validation query, with unchanged native launch ceilings and fallbacks. The focused selection drops from 2,447 to 2,009 launches: three saved for each of 146 repository opens. Three paired Windows measurements of 20 opens each reduce the median from 300.74 ms to 221.18 ms per open, with matching metadata and 11 versus eight launches. Add `--durations=30` to CI so future slow tests are visible, and record the profiling evidence and reproduction requirements in `doc/gix-backend.md`. Cover both object formats, both reference formats, bare and non-bare repos, spaces and embedded newlines. The eight applicable Windows cases fail before the fix and pass afterward; all 16 cases pass on Ubuntu WSL. The optional Windows Gix selection reproduces the same 17 failures on the original and patched sources. Document the demonstrated path-formatting and undecodable `commondir` differences under `GIX-14`, distinguishing them from Windows test assumptions. Keep these bugs open pending compatible upstream behavior. Validation: the full Windows CLI suite passes with 1,662 passed, 60 skipped, nine expected failures, two unexpected passes and 40 passing subtests. It records 77,732 launches in 3,715.16s. The initial baseline records 86,032 in 3,990.28s; its only two failures pass on unchanged code after restoring CI's `core.autocrlf=true` and placing `pytest`'s temporary directory outside a Git checkout. The overlapping full runs are not a controlled elapsed-time comparison. Repository-wide Ruff lint/format, all pinned pre-commit hooks, `mypy` (47 files), `basedpyright` (zero errors or warnings), the Sphinx HTML build and `git diff --check` pass.
Byron
force-pushed
the
gix-backend
branch
4 times, most recently
from
October 8, 2026 07:14
af1de6a to
c3a2832
Compare
Byron
pushed a commit
that referenced
this pull request
Oct 9, 2026
PR #2274's Python 3.12 CI jobs spent 57m 25s in Windows `pytest` versus 5m 2s on Ubuntu, with 85,777 and 82,683 `Git.execute` launches respectively. A local profile of the file-handle and recursive submodule regressions spent about 65 of 77 seconds executing Git, including 44 seconds in repository construction. Repeated process startup makes the separate metadata probes expensive. Query reference format, object format, bare status and the absolute common directory in one `git rev-parse` call on the CLI construction path. Keep the path last and split only the three fixed scalar fields so embedded newlines remain intact. Git still computes every value. Supported Gix discovery keeps its native metadata and existing CLI format-validation query, with unchanged native launch ceilings and fallbacks. The focused selection drops from 2,447 to 2,009 launches: three saved for each of 146 repository opens. Three paired Windows measurements of 20 opens each reduce the median from 300.74 ms to 221.18 ms per open, with matching metadata and 11 versus eight launches. Add `--durations=30` to CI so future slow tests are visible, and record the profiling evidence and reproduction requirements in `doc/gix-backend.md`. Cover both object formats, both reference formats, bare and non-bare repos, spaces and embedded newlines. The eight applicable Windows cases fail before the fix and pass afterward; all 16 cases pass on Ubuntu WSL. The optional Windows Gix selection reproduces the same 17 failures on the original and patched sources. Document the demonstrated path-formatting and undecodable `commondir` differences under `GIX-14`, distinguishing them from Windows test assumptions. Keep these bugs open pending compatible upstream behavior. Validation: the full Windows CLI suite passes with 1,662 passed, 60 skipped, nine expected failures, two unexpected passes and 40 passing subtests. It records 77,732 launches in 3,715.16s. The initial baseline records 86,032 in 3,990.28s; its only two failures pass on unchanged code after restoring CI's `core.autocrlf=true` and placing `pytest`'s temporary directory outside a Git checkout. The overlapping full runs are not a controlled elapsed-time comparison. Repository-wide Ruff lint/format, all pinned pre-commit hooks, `mypy` (47 files), `basedpyright` (zero errors or warnings), the Sphinx HTML build and `git diff --check` pass.
Byron
force-pushed
the
gix-backend
branch
4 times, most recently
from
October 9, 2026 08:01
75ebc93 to
6881712
Compare
Byron
pushed a commit
that referenced
this pull request
Oct 9, 2026
The Windows Python 3.14 job for PR #2274 failed in `TestSubmodule.test_base_rw` when forced module-only removal called `rmtree`: Windows reported `WinError 32` for `git/ext/gitdb`. The legacy test retains that checkout's `Repo` through `csm.repo` and starts its persistent `cat-file` process while reading parent commits. Closing only the fresh handle created by `Submodule.remove()` cannot release this caller-owned process. Close the retained test-owned parent before deleting its checkout. Keep strict removal and all existing happy-path assertions, and remove the obsolete commented-out skip that claimed removal ignored this error. The original test predates the PR's base, so record this as a follow-up rather than rewriting shared history. The focused `test_base_rw` passed locally with both CLI and Gix. Relevant pre-commit hooks passed. Hosted Windows validation remains part of the PR CI loop.
Byron
pushed a commit
that referenced
this pull request
Oct 9, 2026
The Windows Python 3.14 job for PR #2274 failed in `TestSubmodule.test_base_rw` when forced module-only removal called `rmtree`: Windows reported `WinError 32` for `git/ext/gitdb`. The legacy test retains that checkout's `Repo` through `csm.repo` and starts its persistent `cat-file` process while reading parent commits. Closing only the fresh handle created by `Submodule.remove()` cannot release this caller-owned process. Close the retained test-owned parent before deleting its checkout. Keep strict removal and all existing happy-path assertions, and remove the obsolete commented-out skip that claimed removal ignored this error. The original test predates the PR's base, so record this as a follow-up rather than rewriting shared history. The focused `test_base_rw` passed locally with both CLI and Gix. Relevant pre-commit hooks passed. Hosted Windows validation remains part of the PR CI loop.
Byron
force-pushed
the
gix-backend
branch
2 times, most recently
from
October 14, 2026 09:31
17a316c to
a6c7dba
Compare
Byron
pushed a commit
that referenced
this pull request
Oct 14, 2026
PR #2274's Python 3.12 CI jobs spent 57m 25s in Windows `pytest` versus 5m 2s on Ubuntu, with 85,777 and 82,683 `Git.execute` launches respectively. A local profile of the file-handle and recursive submodule regressions spent about 65 of 77 seconds executing Git, including 44 seconds in repository construction. Repeated process startup makes the separate metadata probes expensive. Query reference format, object format, bare status and the absolute common directory in one `git rev-parse` call on the CLI construction path. Keep the path last and split only the three fixed scalar fields so embedded newlines remain intact. Git still computes every value. Supported Gix discovery keeps its native metadata and existing CLI format-validation query, with unchanged native launch ceilings and fallbacks. The focused selection drops from 2,447 to 2,009 launches: three saved for each of 146 repository opens. Three paired Windows measurements of 20 opens each reduce the median from 300.74 ms to 221.18 ms per open, with matching metadata and 11 versus eight launches. Add `--durations=30` to CI so future slow tests are visible, and record the profiling evidence and reproduction requirements in `doc/gix-backend.md`. Cover both object formats, both reference formats, bare and non-bare repos, spaces and embedded newlines. The eight applicable Windows cases fail before the fix and pass afterward; all 16 cases pass on Ubuntu WSL. The optional Windows Gix selection reproduces the same 17 failures on the original and patched sources. Document the demonstrated path-formatting and undecodable `commondir` differences under `GIX-14`, distinguishing them from Windows test assumptions. Keep these bugs open pending compatible upstream behavior. Validation: the full Windows CLI suite passes with 1,662 passed, 60 skipped, nine expected failures, two unexpected passes and 40 passing subtests. It records 77,732 launches in 3,715.16s. The initial baseline records 86,032 in 3,990.28s; its only two failures pass on unchanged code after restoring CI's `core.autocrlf=true` and placing `pytest`'s temporary directory outside a Git checkout. The overlapping full runs are not a controlled elapsed-time comparison. Repository-wide Ruff lint/format, all pinned pre-commit hooks, `mypy` (47 files), `basedpyright` (zero errors or warnings), the Sphinx HTML build and `git diff --check` pass.
Byron
pushed a commit
that referenced
this pull request
Oct 14, 2026
The Windows Python 3.14 job for PR #2274 failed in `TestSubmodule.test_base_rw` when forced module-only removal called `rmtree`: Windows reported `WinError 32` for `git/ext/gitdb`. The legacy test retains that checkout's `Repo` through `csm.repo` and starts its persistent `cat-file` process while reading parent commits. Closing only the fresh handle created by `Submodule.remove()` cannot release this caller-owned process. Close the retained test-owned parent before deleting its checkout. Keep strict removal and all existing happy-path assertions, and remove the obsolete commented-out skip that claimed removal ignored this error. The original test predates the PR's base, so record this as a follow-up rather than rewriting shared history. The focused `test_base_rw` passed locally with both CLI and Gix. Relevant pre-commit hooks passed. Hosted Windows validation remains part of the PR CI loop.
Merged
Byron
force-pushed
the
gix-backend
branch
4 times, most recently
from
October 15, 2026 08:53
13202ce to
781c620
Compare
Byron
marked this pull request as ready for review
October 24, 2026 20:12
This was referenced Oct 24, 2026
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved object-decoding and branch-renaming errors can return incomplete data or references to the wrong branch.
3 open issues
What changed in this PR
GitHub Copilot review: This PR prepares GitPython for newer Git storage formats and adds an optional GixPython backend, supported by shared fixtures, compatibility checks, and benchmarks.
Changes:
- Delegate storage operations to guarded Git commands or supported Gix APIs, with updated object IDs and index interfaces.
- Introduce reusable scripted fixtures, backend reporting, downstream checks, and benchmark parity enforcement.
- Update installation guidance, dependencies, CI, and fuzzing for Git 2.52+.
| File | Description |
|---|---|
| tox.ini | Select backends and add older-runtime smoke checks. |
| tests/fixtures/util.sh | Prepare lock and symlink scenarios. |
| tests/fixtures/tree-order.sh | Capture Git tree ordering. |
| tests/fixtures/submodule-transport.sh | Prepare submodule transport comparisons. |
| tests/fixtures/submodule-symlinks.sh | Prepare checkout and metadata symlinks. |
| tests/fixtures/submodule-special.sh | Cover special submodule layouts and names. |
| tests/fixtures/submodule-source.sh | Create a reusable submodule source. |
| tests/fixtures/submodule-relative.sh | Prepare relative-URL scenarios. |
| tests/fixtures/submodule-no-fetch.sh | Prepare offline submodule updates. |
| tests/fixtures/submodule-layout.sh | Build varied submodule layouts. |
| tests/fixtures/submodule-cases.sh | Prepare submodule lifecycle and safety cases. |
| tests/fixtures/safety.sh | Prepare command and object safety cases. |
| tests/fixtures/rmtree.sh | Prepare deletion and permission scenarios. |
| tests/fixtures/rev-parse.sh | Build revision-parsing histories. |
| tests/fixtures/remote-timeout.sh | Create a timeout-test repository. |
| tests/fixtures/remote-cli.sh | Prepare fetch and quoted-name scenarios. |
| tests/fixtures/refs.sh | Prepare reference safety cases. |
| tests/fixtures/refs-input.sh | Create option-injection inputs. |
| tests/fixtures/reflog.sh | Prepare reflog and signing scenarios. |
| tests/fixtures/reference-security.sh | Build cyclic and external reference cases. |
| tests/fixtures/quick-doc.sh | Replace remote tutorial setup locally. |
| tests/fixtures/positional.sh | Prepare option-shaped operand cases. |
| tests/fixtures/objects-index.sh | Prepare object, index, and hook scenarios. |
| tests/fixtures/local-environment.sh | Generate isolated test configuration. |
| tests/fixtures/installation.sh | Prepare installation-test environments. |
| tests/fixtures/index.sh | Build index and hook fixtures. |
| tests/fixtures/hook-ownership.sh | Prepare hook ownership layouts. |
| tests/fixtures/history.sh | Create historical repository layouts. |
| tests/fixtures/git-command.sh | Prepare executable and environment cases. |
| tests/fixtures/fun.sh | Construct merge-tree inputs. |
| tests/fixtures/fixture-lifecycle.sh | Support fixture lifecycle checks. |
| tests/fixtures/empty.sh | Supply empty directories or repositories. |
| tests/fixtures/downstream-worktree.sh | Prepare downstream worktree cases. |
| tests/fixtures/downstream-swebench.sh | Create local SWE-bench clone sources. |
| tests/fixtures/downstream-separate-git-dir.sh | Create relocatable separate metadata. |
| tests/fixtures/downstream-revision-path.sh | Prepare revision-path compatibility cases. |
| tests/fixtures/downstream-local-upstream.sh | Configure local tracking branches. |
| tests/fixtures/downstream-literal-repo.sh | Preserve literal variable-shaped paths. |
| tests/fixtures/downstream-index.sh | Prepare immutable index-reader cases. |
| tests/fixtures/docs.sh | Isolate tutorial push destinations. |
| tests/fixtures/diff.sh | Prepare diff formats and edge cases. |
| tests/fixtures/dependencies.sh | Create historical dependency repositories. |
| tests/fixtures/config.sh | Prepare configuration parsing cases. |
| tests/fixtures/commit.sh | Prepare commit metadata and encoding cases. |
| tests/fixtures/command-guards.sh | Prepare guarded-command regressions. |
| tests/fixtures/clone.sh | Prepare clone compatibility cases. |
| tests/fixtures/cleanup.sh | Prepare cleanup failure scenarios. |
| tests/fixtures/benchmark.sh | Create the pinned benchmark repository. |
| tests/fixtures/benchmark-comparison.sh | Generate comparison validation inputs. |
| test/test_typing.py | Update semantic index-entry checks. |
| test/test_remote_progress.py | Check progress override return typing. |
| test/test_remote_cli.py | Check command-derived fetch results. |
| test/test_quick_doc.py | Use local tutorial fixtures. |
| test/test_installation.py | Check installation, backend, and version behavior. |
| test/test_imports.py | Check the actual utility-module binding. |
| test/test_fixture_health.py | Check fixture reuse, isolation, and errors. |
| test/test_exc.py | Remove unnecessary repository setup. |
| test/test_docs.py | Isolate tutorials and update index examples. |
| test/test_cli_process_counts.py | Check subprocess counters and ceilings. |
| test/test_blob_filter.py | Simplify blob-filter inputs. |
| test/test_base.py | Move setup into shared fixtures. |
| test/test_backend_selection.py | Check backend selection and fixture availability. |
| test/test_actor.py | Remove obsolete deprecation checks. |
| test/run-local.py | Add isolated local test execution. |
| test/performance/test_odb.py | Remove legacy object-store timing tests. |
| test/performance/test_commit.py | Remove legacy commit timing tests. |
| test/performance/test_benchmark_comparison.py | Check benchmark parity enforcement. |
| test/performance/README.md | Document benchmark execution and interpretation. |
| test/performance/lib.py | Remove legacy performance helpers. |
| test/performance/compare_backends.py | Validate parity and report measurements. |
| test/performance/cli-budget.json | Define backend subprocess ceilings. |
| test/performance/benchmark-requirements.txt | Declare benchmark dependencies. |
| test/lib/fixtures.py | Manage cached and writable scripted fixtures. |
| test/downstream/projects.json | Define downstream compatibility profiles. |
| test/downstream/checks/swebench.py | Exercise real SWE-bench GitPython callers. |
| test/deprecation/test_types.py | Remove obsolete type-alias deprecation tests. |
| test/deprecation/test_compat.py | Remove platform-alias deprecation tests. |
| test/deprecation/test_basic.py | Remove obsolete deprecation coverage. |
| test/deprecation/lib.py | Remove deprecation test helpers. |
| test/deprecation/__init__.py | Remove the deprecation test package. |
| test/conftest.py | Report backend operations and fixture sources. |
| test/cleanup.py | Add best-effort test-directory cleanup. |
| test-requirements.txt | Add GixPython fixture tooling. |
| README.md | Explain Gix activation and prerequisites. |
| pyproject.toml | Add the Gix extra and adjust typing coverage. |
| MANIFEST.in | Package Gix requirements and exclude fixtures. |
| gix-requirements.txt | Pin the optional GixPython dependency. |
| git/types.py | Remove the deprecated commit-type alias. |
| git/refs/tag.py | Guard tag options and validate operands. |
| git/refs/remote.py | Delegate reference deletion to Git. |
| git/refs/reference.py | Let Git maintain HEAD reflogs. |
| git/refs/head.py | Guard branch operations and support local upstreams. |
| git/objects/util.py | Delegate textual date parsing to Git. |
| git/objects/tree.py | Delegate tree loading and construction to Git. |
| git/objects/tag.py | Add native tag metadata decoding. |
| git/objects/submodule/util.py | Use shared configuration-section escaping. |
| git/objects/submodule/root.py | Update reflog lookup and transport handling. |
| git/objects/base.py | Support repository-specific object ID widths. |
| git/index/util.py | Remove obsolete binary-index helpers. |
| git/index/typ.py | Represent semantic index entries without raw metadata. |
| git/diff.py | Add native dispatch and guarded CLI diffs. |
| git/compat.py | Remove deprecated platform aliases. |
| git/__init__.py | Update version loading and compatibility exports. |
| fuzzing/README.md | Document Git-backed fuzzing requirements. |
| fuzzing/oss-fuzz-scripts/container-environment-bootstrap.sh | Enforce the minimum Git version. |
| fuzzing/oss-fuzz-scripts/build.sh | Validate and bundle the selected Git executable. |
| fuzzing/local-dev-helpers/Dockerfile | Build the minimum supported Git. |
| fuzzing/fuzz-targets/fuzz_repo.py | Exercise Git-backed repository workflows. |
| fuzzing/fuzz-targets/fuzz_diff.py | Adapt object IDs and expected errors. |
| fuzzing/fuzz-targets/fuzz_config.py | Handle expected Git configuration rejection. |
| fuzzing/fuzz-targets/fuzz_blob.py | Respect repository object ID widths. |
| doc/source/tutorial.rst | Update object, index, and reflog guidance. |
| doc/source/intro.rst | Describe storage support and new requirements. |
| CONTRIBUTING.md | Document fixture and cleanup conventions. |
| AGENTS.md | Define Gix implementation and compatibility requirements. |
| .gitignore | Ignore generated fixture caches and archives. |
| .github/workflows/git-cli.yml | Test minimum-Git format and safety contracts. |
| .github/workflows/downstream.yml | Run downstream profiles on both backends. |
| .github/workflows/cygwin-test.yml | Build supported Git and smoke-test installation. |
| .github/workflows/backend-benchmark.yml | Measure backends and enforce parity budgets. |
| .github/workflows/alpine-test.yml | Install fixture tooling and select CLI explicitly. |
| .basedpyright/baseline.json | Remove obsolete typing suppressions. |
Review effort: Balanced
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "reading them raises `AttributeError`" when native decoding has no tagger, and requests preserving initialized fields through a CLI fallback. Four SHA-1/SHA-256 regressions reproduce the native failure. The two cases with a message also expose CLI loss of the first message line, so falling back alone would not restore complete metadata. Adapt `Tag.tagger()` returning `None` to the existing empty `Actor` and zero date/offset defaults through `parse_actor_and_date("")`. Gix already exposes the absence correctly; no new Git semantics or fallback is required. Make the CLI parser recognize the optional tagger header and preserve the entire message. Git 2.54.0's `tag.c::parse_tag_buffer()` accepts an absent tagger and sets its date to zero. The existing GIX-28 strict writer gap remains open. All four regressions now pass on both backends; the native cases forbid `Git.execute()` during metadata access. Reference and CLI object/index tests pass on CLI (105 tests, 24 subtests) and Gix (105 tests, 24 subtests). Ruff, ShellCheck and mypy pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "subsequent iteration or lookup silently accepts that truncated tree" after an entry fails validation. Stored trees containing a `.git` entry reproduce this on both backends: the first iteration rejects the name, but the second accepts an empty tree or the valid prefix. Build the entries in a local list and attach `_cache` only after every record passes parsing and validation. Failed reads leave the lazy cache unset, so later accesses retry and raise the same error instead of exposing partial data. No backend behavior or tree validation policy changes. Git 2.54.0's `mktree` and `ls-tree` accept and emit the fixture's `.git` entry; GitPython applies its existing metadata-path guard while consuming that output. Four regressions cover invalid entries first and last in SHA-1/SHA-256 trees. All fail before the fix and pass afterwards on CLI and native Gix `ls_tree`. All 97 tree tests pass on each backend. Ruff, ShellCheck and mypy pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "the returned head points to `refs/heads/topic`, which may be missing or identify a different branch" after renaming to the short branch name `refs/heads/topic`. A repository with an existing `topic` at commit A and a source branch at commit B reproduces the incorrect returned ref on both backends. Compute the destination by prepending `refs/heads/` to the literal name passed to `git branch`. Validate that same destination and retain it only after Git successfully renames the branch. Git 2.54.0's `builtin/branch.c::copy_or_rename_branch()` uses `refs.c::check_branch_ref()`, which always prepends that namespace. The general `to_full_path()` helper continues to normalize already-qualified references for its other callers. The SHA-1/SHA-256 regressions fail before this fix and pass afterwards. They check the returned path, name and commit, current `HEAD`, and that the original `topic` still points to commit A. All 50 reference tests and 24 subtests pass on each backend, including ordinary and forced renames. Ruff, ShellCheck, mypy and basedpyright pass.
1 task done
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "reading them raises `AttributeError`" when native decoding has no tagger, and requests preserving initialized fields through a CLI fallback. Four SHA-1/SHA-256 regressions reproduce the native failure. The two cases with a message also expose CLI loss of the first message line, so falling back alone would not restore complete metadata. Adapt `Tag.tagger()` returning `None` to the existing empty `Actor` and zero date/offset defaults through `parse_actor_and_date("")`. Gix already exposes the absence correctly; no new Git semantics or fallback is required. Make the CLI parser recognize the optional tagger header and preserve the entire message. Git 2.54.0's `tag.c::parse_tag_buffer()` accepts an absent tagger and sets its date to zero. The existing GIX-28 strict writer gap remains open. All four regressions now pass on both backends; the native cases forbid `Git.execute()` during metadata access. Reference and CLI object/index tests pass on CLI (105 tests, 24 subtests) and Gix (105 tests, 24 subtests). Ruff, ShellCheck and mypy pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "subsequent iteration or lookup silently accepts that truncated tree" after an entry fails validation. Stored trees containing a `.git` entry reproduce this on both backends: the first iteration rejects the name, but the second accepts an empty tree or the valid prefix. Build the entries in a local list and attach `_cache` only after every record passes parsing and validation. Failed reads leave the lazy cache unset, so later accesses retry and raise the same error instead of exposing partial data. No backend behavior or tree validation policy changes. Git 2.54.0's `mktree` and `ls-tree` accept and emit the fixture's `.git` entry; GitPython applies its existing metadata-path guard while consuming that output. Four regressions cover invalid entries first and last in SHA-1/SHA-256 trees. All fail before the fix and pass afterwards on CLI and native Gix `ls_tree`. All 97 tree tests pass on each backend. Ruff, ShellCheck and mypy pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "the returned head points to `refs/heads/topic`, which may be missing or identify a different branch" after renaming to the short branch name `refs/heads/topic`. A repository with an existing `topic` at commit A and a source branch at commit B reproduces the incorrect returned ref on both backends. Compute the destination by prepending `refs/heads/` to the literal name passed to `git branch`. Validate that same destination and retain it only after Git successfully renames the branch. Git 2.54.0's `builtin/branch.c::copy_or_rename_branch()` uses `refs.c::check_branch_ref()`, which always prepends that namespace. The general `to_full_path()` helper continues to normalize already-qualified references for its other callers. The SHA-1/SHA-256 regressions fail before this fix and pass afterwards. They check the returned path, name and commit, current `HEAD`, and that the original `topic` still points to commit A. All 50 reference tests and 24 subtests pass on each backend, including ordinary and forced renames. Ruff, ShellCheck, mypy and basedpyright pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "reading them raises `AttributeError`" when native decoding has no tagger, and requests preserving initialized fields through a CLI fallback. Four SHA-1/SHA-256 regressions reproduce the native failure. The two cases with a message also expose CLI loss of the first message line, so falling back alone would not restore complete metadata. Adapt `Tag.tagger()` returning `None` to the existing empty `Actor` and zero date/offset defaults through `parse_actor_and_date("")`. Gix already exposes the absence correctly; no new Git semantics or fallback is required. Make the CLI parser recognize the optional tagger header and preserve the entire message. Git 2.54.0's `tag.c::parse_tag_buffer()` accepts an absent tagger and sets its date to zero. The existing GIX-28 strict writer gap remains open. All four regressions now pass on both backends; the native cases forbid `Git.execute()` during metadata access. Reference and CLI object/index tests pass on CLI (105 tests, 24 subtests) and Gix (105 tests, 24 subtests). Ruff, ShellCheck and mypy pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "subsequent iteration or lookup silently accepts that truncated tree" after an entry fails validation. Stored trees containing a `.git` entry reproduce this on both backends: the first iteration rejects the name, but the second accepts an empty tree or the valid prefix. Build the entries in a local list and attach `_cache` only after every record passes parsing and validation. Failed reads leave the lazy cache unset, so later accesses retry and raise the same error instead of exposing partial data. No backend behavior or tree validation policy changes. Git 2.54.0's `mktree` and `ls-tree` accept and emit the fixture's `.git` entry; GitPython applies its existing metadata-path guard while consuming that output. Four regressions cover invalid entries first and last in SHA-1/SHA-256 trees. All fail before the fix and pass afterwards on CLI and native Gix `ls_tree`. All 97 tree tests pass on each backend. Ruff, ShellCheck and mypy pass.
Byron
pushed a commit
that referenced
this pull request
Oct 25, 2026
Review item #2274 (comment) reports that "the returned head points to `refs/heads/topic`, which may be missing or identify a different branch" after renaming to the short branch name `refs/heads/topic`. A repository with an existing `topic` at commit A and a source branch at commit B reproduces the incorrect returned ref on both backends. Compute the destination by prepending `refs/heads/` to the literal name passed to `git branch`. Validate that same destination and retain it only after Git successfully renames the branch. Git 2.54.0's `builtin/branch.c::copy_or_rename_branch()` uses `refs.c::check_branch_ref()`, which always prepends that namespace. The general `to_full_path()` helper continues to normalize already-qualified references for its other callers. The SHA-1/SHA-256 regressions fail before this fix and pass afterwards. They check the returned path, name and commit, current `HEAD`, and that the original `topic` still points to commit A. All 50 reference tests and 24 subtests pass on each backend, including ordinary and forced renames. Ruff, ShellCheck, mypy and basedpyright pass.
EliahKagan
added a commit
to EliahKagan/GitPython
that referenced
this pull request
Oct 25, 2026
Since 212573b (gitpython-developers#2274), GitPython requires Git 2.52 or newer for library-managed operations, and the tests require it too. The README says that Git must be "available in `PATH` or selected with `GIT_PYTHON_GIT_EXECUTABLE`", which lets a developer whose default `git` is older point GitPython at a newer one without changing `PATH`. tox did not support the second way. Its environments only receive the variables tox passes by default plus those in `pass_env`, which listed just `SSH_*`. So `GIT_PYTHON_GIT_EXECUTABLE` set in the shell was silently dropped, and `tox` ran the tests against whatever `git` came first in `PATH`, even when that was too old. Add `GIT_PYTHON_GIT_EXECUTABLE` to `pass_env` in `[testenv]`. Every environment inherits it, including `gix` and the `py38` through `py310` import smoke checks, none of which override `pass_env`. `GIT_PYTHON_BACKEND` is still not passed through, since `[testenv]` and `gix` each set it explicitly. Checked locally with tox 4.67.1 by running an environment with its command overridden to print the variable, with `GIT_PYTHON_GIT_EXECUTABLE` set in the calling shell. Before this change it printed `None`; after it, the value that was set. `tox config` shows the variable in `pass_env` for `py311`, `gix`, and `mypy`. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
EliahKagan
added a commit
to EliahKagan/GitPython
that referenced
this pull request
Oct 25, 2026
The tox `ruff`, `format`, and `misc` environments only run tools on the source tree: `ruff check`, `ruff format --check`, and the remaining pre-commit hooks. But they did not set `skip_install`, so they inherited the default of installing GitPython with `extras = test` from `[testenv]`. That has always been unneeded work, but it became a real obstacle when 212573b (gitpython-developers#2274) added GixPython to the `test` extra for Python 3.11 and later. GixPython 0.3.0 publishes wheels only for macOS, so on Linux and Windows installing it builds its source distribution, which needs Rust 1.89 or newer and a linker. So running Ruff through tox on those platforms now needed a Rust toolchain. Set `skip_install = true` in all three environments. `ruff` and `format` already list `ruff` in `deps`. `misc` got `pre-commit` from the `test` extra, so list it in `deps` instead. Like the `test` extra's entry, it is unversioned. The pre-commit hooks themselves are installed by pre-commit into its own environments as before. Run locally with tox 4.67.1, each environment now installs only `ruff` or `pre-commit` and passes. `ruff` reports "All checks passed!", `format` reports 112 files already formatted, and `misc` runs every non-Ruff hook successfully. `ruff` and `format` each took about 1.5 seconds, compared with about 12 seconds for `ruff` before, most of which went to installing the `test` extra. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
EliahKagan
added a commit
to EliahKagan/GitPython
that referenced
this pull request
Oct 25, 2026
Since 212573b (gitpython-developers#2274), GitPython requires Git 2.52 or newer for library-managed operations, and the tests require it too. The README says that Git must be "available in `PATH` or selected with `GIT_PYTHON_GIT_EXECUTABLE`", which lets a developer whose default `git` is older point GitPython at a newer one without changing `PATH`. tox did not support the second way. Its environments only receive the variables tox passes by default plus those in `pass_env`, which listed just `SSH_*`. So `GIT_PYTHON_GIT_EXECUTABLE` set in the shell was silently dropped, and `tox` ran the tests against whatever `git` came first in `PATH`, even when that was too old. Add `GIT_PYTHON_GIT_EXECUTABLE` to `pass_env` in `[testenv]`. Every environment inherits it, including `gix` and the `py38` through `py310` import smoke checks, none of which override `pass_env`. `GIT_PYTHON_BACKEND` is still not passed through, since `[testenv]` and `gix` each set it explicitly. Checked locally with tox 4.67.1 by running an environment with its command overridden to print the variable, with `GIT_PYTHON_GIT_EXECUTABLE` set in the calling shell. Before this change it printed `None`; after it, the value that was set. `tox config` shows the variable in `pass_env` for `py311`, `gix`, and `mypy`. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
EliahKagan
added a commit
to EliahKagan/GitPython
that referenced
this pull request
Oct 25, 2026
The tox `ruff`, `format`, and `misc` environments only run tools on the source tree: `ruff check`, `ruff format --check`, and the remaining pre-commit hooks. But they did not set `skip_install`, so they inherited the default of installing GitPython with `extras = test` from `[testenv]`. That has always been unneeded work, but it became a real obstacle when 212573b (gitpython-developers#2274) added GixPython to the `test` extra for Python 3.11 and later. GixPython 0.3.0 publishes wheels only for macOS, so on Linux and Windows installing it builds its source distribution, which needs Rust 1.89 or newer and a linker. So on those platforms, running Ruff through tox needed a Rust toolchain whenever 3.10 was not found but 3.11 or 3.12 was, since tox then picked one of those for these environments. Set `skip_install = true` in all three environments. `ruff` and `format` already list `ruff` in `deps`. `misc` got `pre-commit` from the `test` extra, so list it in `deps` instead. Like the `test` extra's entry, it is unversioned. The pre-commit hooks themselves are installed by pre-commit into its own environments as before. Run locally with tox 4.67.1, each environment now installs only `ruff` or `pre-commit` and passes. `ruff` reports "All checks passed!", `format` reports 112 files already formatted, and `misc` runs every non-Ruff hook successfully. `ruff` and `format` each took about 1.5 seconds, compared with about 12 seconds for `ruff` before, most of which went to installing the `test` extra. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
EliahKagan
added a commit
to EliahKagan/GitPython
that referenced
this pull request
Oct 25, 2026
Since 212573b (gitpython-developers#2274), GitPython requires Git 2.52 or newer for library-managed operations, and the tests require it too. The README says that Git must be "available in `PATH` or selected with `GIT_PYTHON_GIT_EXECUTABLE`", which lets a developer whose default `git` is older point GitPython at a newer one without changing `PATH`. tox did not support the second way. Its environments only receive the variables tox passes by default plus those in `pass_env`, which listed just `SSH_*`. So `GIT_PYTHON_GIT_EXECUTABLE` set in the shell was silently dropped, and `tox` ran the tests against whatever `git` came first in `PATH`, even when that was too old. Add `GIT_PYTHON_GIT_EXECUTABLE` to `pass_env` in `[testenv]`. Every environment inherits it, including `gix` and the `py38` through `py310` import smoke checks, none of which override `pass_env`. `GIT_PYTHON_BACKEND` is still not passed through, since `[testenv]` and `gix` each set it explicitly. Checked locally with tox 4.67.1 by running an environment with its command overridden to print the variable, with `GIT_PYTHON_GIT_EXECUTABLE` set in the calling shell. Before this change it printed `None`; after it, the value that was set. `tox config` shows the variable in `pass_env` for `py311`, `gix`, and `mypy`. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
EliahKagan
added a commit
to EliahKagan/GitPython
that referenced
this pull request
Oct 25, 2026
The tox `ruff`, `format`, and `misc` environments only run tools on the source tree: `ruff check`, `ruff format --check`, and the remaining pre-commit hooks. But they did not set `skip_install`, so they inherited the default of installing GitPython with `extras = test` from `[testenv]`. That has always been unneeded work, but it became a real obstacle when 212573b (gitpython-developers#2274) added GixPython to the `test` extra for Python 3.11 and later. GixPython 0.3.0 publishes wheels only for macOS, so on Linux and Windows installing it builds its source distribution, which needs Rust 1.89 or newer and a linker. So on those platforms, running Ruff through tox needed a Rust toolchain whenever 3.10 was not found but 3.11 or 3.12 was, since tox then picked one of those for these environments. Set `skip_install = true` in all three environments. `ruff` and `format` already list `ruff` in `deps`. `misc` got `pre-commit` from the `test` extra, so list it in `deps` instead. Like the `test` extra's entry, it is unversioned. The pre-commit hooks themselves are installed by pre-commit into its own environments as before. Run locally with tox 4.67.1, each environment now installs only `ruff` or `pre-commit` and passes. `ruff` reports "All checks passed!", `format` reports 114 files already formatted, and `misc` runs every non-Ruff hook successfully. `ruff` and `format` each took about 1.5 seconds, compared with about 12 seconds for `ruff` before, most of which went to installing the `test` extra. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Tasks
refackiew- no need actually, but perusing I shallGixPythonDetails
Created by Codex on behalf of Byron. Byron will review before this is ready to merge.
Summary
To try it with Git 2.52 or newer installed:
python -m pip install --upgrade "git+https://github.com/gitpython-developers/GitPython.git@gix-backend"GitPython now delegates repository discovery, configuration, references, reflogs, object storage, tree construction, index operations, and revision parsing to guarded Git commands. The default backend supports SHA-1 and SHA-256 objects with either files or reftable reference storage, without interpreting Git's binary storage formats in Python.
The Python
GitDBstorage implementation is removed;git.GitDBandgit.db.GitDBremain compatibility aliases for the managedGitCmdObjectDBbackend. Rawrepo.gitcommand access remains available. The migration notes inchanges.rstdescribe the API changes and differences in Git CLI behavior.Changes
1. Git CLI implementation of the GitPython API surface
The ordinary installation implements the supported GitPython API through guarded
git.cmd.Gitcalls. Git owns repository storage and format handling, including SHA-1/SHA-256 objects and files/reftable references. This removes Python storage-format parsing from the default backend while retaining common documented workflows and rawrepo.gitaccess. Removed low-level APIs have replacements documented in the changelog. The existing context and migration notes below describe safety controls and low-level API changes.2. GixPython implementation for better performance
The optional
GitPython[gix]installation uses the publishedGixPython==0.2.0release on CPython 3.11+. GitPython selects it automatically when thegixmodule is importable; the ordinary installation continues to support Python 3.8+. SetGIT_PYTHON_BACKEND=cliorGIT_PYTHON_BACKEND=gixbefore importing GitPython to select a backend explicitly. To try the native backend:python -m pip install --upgrade "GitPython[gix] @ git+https://github.com/gitpython-developers/GitPython.git@gix-backend"Supported library-managed operations use Gitoxide through GixPython's
gixAPI for object reads/writes, revision and graph queries, tree enumeration and construction, index reads, references and reflogs, commit creation/statistics, tree diffs, status, untracked files, and ignore matching. Unsupported formats and options retain the guarded CLI implementation. In particular, reftable andextensions.compatObjectFormatrepositories currently use Git. Native mutation failures are reported without attempting a second CLI mutation. Private index edits and tag object storage use Git until Gix exposes strict validation; index state in Python consists only of opaque file bytes. Commit/tag reads use structured Gix decoders where compatible; commit text requiring encoding conversion uses Git. Publicrepo.gitcommands retain their CLI behavior.Historical local measurements, using official GixPython 0.1.0 on CPython 3.12.14, macOS arm64, before the 0.2.0 fixture migration:
These are individual local validation runs, not statistical benchmarks or a guarantee for every application. The full suites collect different backend-specific tests; the focused selections overlap. See the backend guide and performance journal for conversion coverage, remaining CLI cases, reproduction details, and the GixPython/Gitoxide follow-up ledger (
GIX-1throughGIX-30). Repository handles are now retained and refreshed through the shared accessor; the historical timings above predate that work.3. Scripted test fixtures and CI
Both backend test suites now require GixPython 0.2.0 for
gix.testtools. Initial repository and filesystem states live in Bash scripts undertests/fixtures. Read-only tests reuse cached output; mutating tests receive independent writable copies. Scripts re-execute only when their contents cannot be copied or relocated correctly, including link/permission cases and private absolute paths. Operations under test remain in Python, and Git CLI behavior defines expectations for both backends. Generated fixture caches and archives are ignored; no generated archives are checked in.Full fixture suites run on Python 3.11+ with Bash and Git 2.52+. Python 3.8–3.10 retain installation/import smoke coverage, including Cygwin's Python 3.9 job. CI installs and imports
gix.testtoolsfor both backend selections, explicitly selects the backend, and prepares Rust and build caches where GixPython must be built from its released source distribution.Historical fixture measurements with GixPython 0.1.0: on the same local coverage-enabled suite, fixture optimizations reduced wall time from 757.85 s (12m38s) to 404.61 s (6m45s): 353.24 s saved, 46.6% less time, about 1.87× faster. CLI fallback decisions decreased from 39,002 to 21,402; these counters do not count every Git subprocess. This is the before/after fixture improvement, separate from the backend comparison above. The changes reduce repeated work in the CI suites; the quoted timings are local measurements, not a hosted GitHub Actions before/after benchmark. No matching pre-optimization full CLI run was recorded.
The branch also adds released downstream compatibility checks for LangChain, MLflow, Bandit, SWE-bench, and DataHub, plus reproducible local test execution and backend-operation reports.
Context
The goal is to support Git's object and reference formats while reducing the attack surface of Python implementations and limiting argument injection and unintended CLI side effects.
git.cmd.Git, existing unsafe option/protocol checks, validated operands, and framed stdin records. Shell execution and option reordering past protective flags are rejected. Persistentcat-filerequests use NUL framing.git hook run. Signing/editor options and custom archive format commands require an unsafe-options opt-in.GitCommandErrorwith Git's status and diagnostics.oldhexsha, precompressed object streams and custom object-output writers,Submodule.rename(), and directRepo.alternatesmutation. Configuration follows Git syntax and no longer subclassesRawConfigParser. Detailed replacements and limitations are in the changelog.The change also updates documentation, format/backend and injection regressions, the minimum-Git CI job, and fuzz harnesses. Obsolete binary-parser, deprecation and timing-only tests have been removed. Happy paths, Python glue failures and representative compatibility regressions remain; the maintained backend benchmark checks parity and CLI budgets. The release announcement above describes the planned release; this PR does not change
VERSIONyet.CI follow-up handles platform path conventions and rejects unsupported index filenames before changing the original index. Submodule updates now close their internally opened repositories, preventing retained log records from keeping Windows checkouts open through Git processes. Cygwin builds the supported Git version in its normal installation layout and verifies detection before installation/import smoke checks.
Migration details and historical validation
The index lifecycle now materializes deferred bytes into private files, verifies that Git retained requested entries, and publishes atomically. Failed ordinary edits preserve pending/published state; hook edits survive failures without advancing HEAD.
IndexFile.entriesremains available as an immutable read snapshot; useiter_entries(),entry()and explicit index edits. Direct mapping mutation remains unsupported. Textual date parsing and final trailer extraction use Git. See the migration notes for removed environment-expansion/error-hiding switches and changed date/trailer behavior.Historical validation at earlier revisions: on macOS with Git 2.54.0, the retained suite passed with 1,767 tests on Gix and 1,672 on CLI, plus focused regressions on both. All five downstream profiles passed on both backends. All 14 benchmark result digests matched and existing Gix CLI ceilings passed; concurrent fast timing samples do not establish a speed change. Lint, typing and documentation checks passed locally. CI follow-up fixes the Bash 3.2 condition on macOS, removes the empty historical Cygwin performance split, makes path and command fixtures respect Windows configuration, closes a test-owned submodule parent before removal, and isolates partial-write failure injection to locked publication. Focused regressions passed locally with both backends. All 64 hosted checks passed on
17a316c, including the complete Windows matrix, Gix on Ubuntu/macOS/Windows, downstream compatibility, backend parity and CLI ceilings, and Cygwin (1,691 passed, 20 skipped, 11 xfailed).Earlier CI validation
All 64 hosted checks passed for
781c620on October 15, 2026. This includes the complete Windows matrix, Gix on Ubuntu/macOS/Windows, Python 3.8–3.10 installation/import checks, Cygwin smoke coverage, Alpine, the minimum-Git job, all five downstream compatibility profiles, backend parity and CLI-process ceilings, and the configured quality checks.Windows Python 3.12 passed 1,674 CLI tests and 1,772 Gix tests, with 61 passing subtests on each backend. The final fixture correction also passed all 40 commit tests and 21 subtests locally on CLI, then Gix, plus the changed files' pre-commit hooks. Git remains the text baseline: malformed UTF-16 fixtures now force conversion failure, with raw-size assertions, rather than assuming stable output after conversion erases Git's header delimiters. Production behavior is unchanged by that correction.
The measurements in earlier sections remain historical; this CI run does not establish a new timing claim. Python 3.8–3.10 receive smoke coverage rather than the GixPython-dependent fixture suites.
Expanded downstream audit and current head
46303c88consolidates the four audit records into one top commit, above the feature and twelve compatibility fixes. The audit index links reports and JSON manifests for 115 distinct projects, covering every identified current declared consumer within the September 2026 top-15,000 PyPI snapshot. The covered 348,530,835 monthly distribution requests include extras and repeat downloads; they do not measure GitPython installations or unique users. Original known-user additions and missing metadata prevent a strict popularity top-115 claim. Selected paths, upstream mocks, isolated helpers, omitted application stacks and CLI fallbacks remain explicitly disclosed.The fixes restore immutable index readers, global
-Cselection, separate-Git-directory checkout context, the managedGitDBselector, local tracking branches, revision tree/path diagnostics, explicit literal-path construction, editable/build version behavior, historicalUnion/Optionalimports and nonempty config section assignment. Current CI repairs use the Python 3.8-compatibletyping.Mapping, make the guaranteed first discovery-loop iteration explicit, and compare Windows test checkout paths by filesystem identity.Remaining actionable gaps are documented: Kas's empty-section creation needs a native section-edit API (downstream can use
set_value()directly); sbxloop's constructor subclass needs supported metadata/include controls or migration; index mapping writes remain unsupported; ambiguous bare/mirror fetch results need full destination identities from Git'sfetch --porcelain. Gix fetch remains a CLI fallback until its binding exposes compatible per-ref outcomes. Other retained downstream failures are distinguished from new GitPython regressions by released-baseline comparisons.Local validation for the CI repairs passed: Python 3.8 import and evaluated annotations, 90 config/downstream tests and 146 repository/downstream tests plus 14 subtests on each backend, followed by 40 final downstream regressions per backend; CLI ran first. Ruff lint/format, mypy and basedpyright pass. Full suites and platform validation are running in hosted CI for this head; the earlier counts above remain historical.