You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace LibGit2Sharp with a hybrid Git backend: a vendored fully-managed reader for all read/history operations plus git CLI shell-out for writes and network. After this, GitVersion ships zero native binaries.
Supersedes the exploration in arturcic#236. Full design document: docs/design/managed-git-migration.md (landing on next/v7).
Status (2026-07, v7.0 prep)
Phases A, B-pre and B are complete and integrating into next/v7 via #5075 (managed backend opt-in behind GITVERSION_GIT_BACKEND=managed, libgit2 the default). C, E and F remain as post-7.0 work; D was dropped.
The seam is already clean: GitVersion.Core has zero LibGit2Sharp references. Only GitVersion.LibGit2Sharp (adapter), GitVersion.Testing (fixtures), and new-cli's source-linked copy touch it. All write/network operations funnel through a single consumer: GitPreparer (CI normalization: clone/fetch/checkout/ls-remote/ref mutation, username/password HTTPS auth only).
git on PATH will be required only for CI-normalization/dynamic-repo scenarios; pure version calculation on a prepared checkout needs no git binary at all.
Proposed architecture
As shipped (Phase B.5): the vendored reader and the git-CLI executor both live in src/GitVersion.Git.Managed — it implements the GitVersion.Core/Git/ interfaces directly (mirroring GitVersion.LibGit2Sharp), with the CLI executor as its CommandLine/ folder. The interim standalone GitVersion.Git.CommandLine and a separate thin GitVersion.Git adapter project described below were not kept as separate projects. Backend selection lives at the composition roots via GITVERSION_GIT_BACKEND (GitBackendSelector in GitVersion.Core).
src/GitVersion.Git.Managed — vendored reader (no Core dependency): pack/idx/delta + loose objects ported from NBGV ManagedGit (MIT, attributed); fresh implementations of the parity-critical pieces: revwalk (topo/time/first-parent with libgit2-identical ordering — version output depends on it), merge-base, tree diff (changed paths), .git/index v2–v4 reading for UncommittedChangesCount, discovery/worktrees/shallow. Hash-agnostic object ids (SHA-256-ready); reftable detected with a clear error initially.
src/GitVersion.Git.CommandLine — git CLI executor: ArgumentList (no shell), plumbing-only parsing, credentials via per-invocation -c http.<url>.extraHeader, stderr mapped onto existing LockedFileException/401/404 handling, git version probe (≥2.30).
src/GitVersion.Git — thin adapter implementing IGitRepository/IMutatingGitRepository; DI surface unchanged; new-cli later source-links the read-only subset.
Phasing (each shippable)
Phase
Scope
Est.
A
git-CLI mutator replaces GitRepository.mutating.cs (reads stay libgit2) — retires the fragile native network/SSL/credential paths first
Managed reader behind GITVERSION_GIT_BACKEND=managed|libgit2; dual-backend CI matrix runs the full integration suites both ways + order-sensitive parity tests + real-world corpus JSON diffing
8–12 wk
C
Default flip to managed; libgit2 escape hatch for one release
1 wk + soak
D
GitVersion.Testing fixtures → pure git-CLI writes (already partially shells out for init/pull/gc)
2–3 wk, parallel
E
Delete LibGit2Sharp projects + package; nupkg assertion test: zero runtimes/**/native/*
1–2 wk
F
Optional: commit-graph accelerator (generation numbers for topo/merge-base)
2–3 wk
~4–5 months elapsed to a LibGit2Sharp-free GitVersion.
Top risks (mitigations in the design doc)
Revwalk ordering parity with libgit2 (port the algorithm precisely; order-sensitive dual-backend tests; corpus diffing gates the default flip)
Merge-base candidate selection on criss-cross merges
Shallow-clone boundaries (the CI default) and worktree/commondir resolution
Fixture suite slowdown from process spawns (batch with git fast-import if needed)
Description
Replace LibGit2Sharp with a hybrid Git backend: a vendored fully-managed reader for all read/history operations plus
gitCLI shell-out for writes and network. After this, GitVersion ships zero native binaries.Supersedes the exploration in arturcic#236. Full design document:
docs/design/managed-git-migration.md(landing onnext/v7).Status (2026-07, v7.0 prep)
Phases A, B-pre and B are complete and integrating into
next/v7via #5075 (managed backend opt-in behindGITVERSION_GIT_BACKEND=managed, libgit2 the default). C, E and F remain as post-7.0 work; D was dropped.GitVersion.Testing)Motivation
libgit2load failures: LibGit2Sharp.Core.NativeMethods cannot be initialized: Unable to load shared library 'git2-7ce88e6' or one of its dependencies #1852, LibGit2Sharp.Core.NativeMethods threw an exception. #2615, GitVersion.Tool does not find LibGit2 library on Ubuntu 19.04 #1744, GitVersion fails on linux (debian) #1203, GitVersion.CommandLine does not work on Linux #1097, [Bug] No error message has been provided by the native library #2884 — RID/libc mismatches (musl vs glibc, ARM, new OpenSSL) and MSBuild assembly-load fragility.LibGit2Sharp.NativeBinariespacks ~12 native binaries intoruntimes/<rid>/native/of every artifact — per TFM in GitVersion.MsBuild.Key research findings (2026-07)
ManagedGit, GitReader, ManagedGitLib — is read-only. NBGV itself keeps libgit2 for write paths.GitVersion.Corehas zero LibGit2Sharp references. OnlyGitVersion.LibGit2Sharp(adapter),GitVersion.Testing(fixtures), and new-cli's source-linked copy touch it. All write/network operations funnel through a single consumer:GitPreparer(CI normalization: clone/fetch/checkout/ls-remote/ref mutation, username/password HTTPS auth only).giton PATH will be required only for CI-normalization/dynamic-repo scenarios; pure version calculation on a prepared checkout needs no git binary at all.Proposed architecture
src/GitVersion.Git.Managed— vendored reader (no Core dependency): pack/idx/delta + loose objects ported from NBGV ManagedGit (MIT, attributed); fresh implementations of the parity-critical pieces: revwalk (topo/time/first-parent with libgit2-identical ordering — version output depends on it), merge-base, tree diff (changed paths),.git/indexv2–v4 reading forUncommittedChangesCount, discovery/worktrees/shallow. Hash-agnostic object ids (SHA-256-ready); reftable detected with a clear error initially.src/GitVersion.Git.CommandLine— git CLI executor:ArgumentList(no shell), plumbing-only parsing, credentials via per-invocation-c http.<url>.extraHeader, stderr mapped onto existingLockedFileException/401/404 handling,git versionprobe (≥2.30).src/GitVersion.Git— thin adapter implementingIGitRepository/IMutatingGitRepository; DI surface unchanged; new-cli later source-links the read-only subset.Phasing (each shippable)
GitRepository.mutating.cs(reads stay libgit2) — retires the fragile native network/SSL/credential paths firstCommitFilter, remove publicToGitRepository()leakGITVERSION_GIT_BACKEND=managed|libgit2; dual-backend CI matrix runs the full integration suites both ways + order-sensitive parity tests + real-world corpus JSON diffingGitVersion.Testingfixtures → pure git-CLI writes (already partially shells out for init/pull/gc)runtimes/**/native/*~4–5 months elapsed to a LibGit2Sharp-free GitVersion.
Top risks (mitigations in the design doc)
git fast-importif needed)