Skip to content

feat(git): fully managed Git backend selectable via GITVERSION_GIT_BACKEND#5084

Open
arturcic wants to merge 14 commits into
GitTools:mainfrom
arturcic:feature/managed-git
Open

feat(git): fully managed Git backend selectable via GITVERSION_GIT_BACKEND#5084
arturcic wants to merge 14 commits into
GitTools:mainfrom
arturcic:feature/managed-git

Conversation

@arturcic

Copy link
Copy Markdown
Member

Follow-up to #5075 (closed).

Implements the managed Git backend for the v7.0 dual-backend window (#5031, design: docs/design/managed-git-migration.md): a vendored, fully managed reader for all read/history operations paired with the git CLI for mutations and network, selectable at runtime alongside the existing libgit2 backend.

What's in the branch

Layered bottom-up, one commit per layer, each with its tests:

  • Object database — hash-agnostic GitObjectId, zlib/random-access streams, pack + idx v2 readers with delta application, bounded pack memory cache, multi-pack-index, loose objects, SHA-256 detection with a clear failure message (NOTICE attribution for code ported from Nerdbank.GitVersioning ManagedGit, MIT).
  • Parsers — commit (signatures, encoding with Latin-1 fallback), tree (streaming reads), annotated tags.
  • Refs & repository layout — loose/packed refs (peeled, symrefs, .lock skipping), walk-up discovery with .git-file indirection, worktrees/commondir, shallow detection, config parsing, reftable rejection.
  • Revision walker — libgit2-parity time/topo ordering with exact tie-break mechanics, mark-uninteresting limiting, paint-down-to-common merge-base, .git/shallow boundaries grafted parentless.
  • Diff & status — changed-paths tree diff in raw byte order, index v2–v4 reader, gitignore matching, working-tree status matching the libgit2 adapter's uncommitted-changes expression.
  • CLI mutator — plumbing-only parsing, ArgumentList invocation (LC_ALL=C, no terminal prompts), per-invocation auth headers, stderr classification mapped to the existing exceptions (Polly LockedFileException retry preserved).
  • Adapters & selectionManaged* implementations of the Core git abstractions over an immutable session snapshot (invalidated after mutations); GITVERSION_GIT_BACKEND=libgit2|managed resolved once in GitBackendSelector (unset ⇒ libgit2 in v7.0; unknown values fail fast); the resolved backend is logged at startup.

Behavior

  • v7.0 default is unchanged (libgit2) — the managed backend is opt-in for validation; v7.1 flips the default per the release plan.
  • With managed, git on PATH is required only for normalization/dynamic-repo scenarios; plain version calculation on a prepared checkout needs no git binary.

Validation

  • CI unit-test matrix runs every leg against both backends (git_backend dimension) on three OSes — the full integration suites assert exact SemVer strings over complex histories.
  • DualBackendParityTests: deep-equality on ref enumeration, order-sensitive walks, merge-base over commit pairs (criss-cross, equal timestamps), DiffPaths, UncommittedChangesCount.
  • build/parity-corpus.ps1 diffs gitversion /nocache /output json across backends on real-world repositories.

🤖 Generated with Claude Code

@arturcic
arturcic requested a review from asbjornu July 22, 2026 21:32
@arturcic
arturcic force-pushed the feature/managed-git branch 3 times, most recently from 17b3155 to c3d263d Compare July 23, 2026 23:53
@arturcic
arturcic force-pushed the main branch 2 times, most recently from 1ad796b to 6f8b3ab Compare July 24, 2026 10:58
@arturcic
arturcic force-pushed the feature/managed-git branch from c3d263d to 901fb35 Compare July 24, 2026 11:08
@arturcic

arturcic commented Jul 24, 2026

Copy link
Copy Markdown
Member Author

@asbjornu @HHobeck hey guys would you mind to review this PR and actually give it a try? I really need your feedback, which I can address before we merge it for v7

arturcic and others added 14 commits July 24, 2026 18:37
Research and phased plan for replacing LibGit2Sharp with a vendored
managed reader plus git CLI writes (GitTools#5031).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…primitives

New project (with NOTICE attribution for code ported from Nerdbank.GitVersioning
ManagedGit) and the raw building blocks: hash-agnostic GitObjectId, zlib and
random-access streams, text decoding with Latin-1 fallback, and file helpers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Packfile access with idx v2 lookup, ofs/ref delta stream application, a
bounded pack memory cache with refcounted views, and multi-pack-index support.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author/committer signatures with commit-encoding handling, streaming tree
reads for diff traversal, and annotated-tag target resolution.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Single lookup facade across loose objects, packs, and the multi-pack index,
with SHA-256 repository detection failing fast with a clear message.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Loose and packed refs (peeled entries, symrefs, HEAD, lock-file skipping),
walk-up discovery with .git-file indirection, worktree and commondir
resolution, shallow detection, git config parsing, and reftable/objectformat
rejection with clear messages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Time/topological sorts with exact tie-break mechanics, first-parent walks,
mark-uninteresting limiting, paint-down-to-common merge-base selection, and
shallow boundaries grafted parentless from .git/shallow; unexplained missing
parents fail the walk.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Changed-paths tree diff aligned by raw byte order, .git/index v2-v4 reader
(v4 prefix compression), gitignore matching, and the working-tree status
walk matching the libgit2 adapter's uncommitted-changes expression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plumbing-only parsing, ArgumentList invocation with LC_ALL=C and terminal
prompts disabled, per-invocation auth headers, stderr classification mapped
to existing exceptions (LockedFileException retry preserved), and shared
pull-request tip matching with peeled-entry folding.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Managed* adapters implement IGitRepository/IMutatingGitRepository and the
collection interfaces directly over the managed reader and CLI mutator, with
an immutable session snapshot invalidated after mutations. Backend selection
is centralized in GitBackendSelector: GITVERSION_GIT_BACKEND picks libgit2
(default when unset) or managed at every composition root, failing fast on
unrecognized values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deep-equality parity assertions across both backends on adversarial fixtures,
plus a real-world corpus script diffing gitversion JSON output across
repositories and backends.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the git_backend dimension so every leg runs with libgit2 and managed,
publishing per-backend test summaries and coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GITVERSION_GIT_BACKEND usage, the v7.0 libgit2 default and v7.1 managed flip,
and the git-on-PATH requirement scoped to normalization scenarios.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add shared IntelliJ/Rider run configurations to facilitate debugging the CLI using both libgit2sharp and managed git backends.
@arturcic
arturcic force-pushed the feature/managed-git branch from 901fb35 to 4fbfd69 Compare July 24, 2026 16:45
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant