GitTools / GitTools/GitVersion

Evaluate .NET 11 SDK, runtime and BCL improvements

Open
#5,210 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
3.1k
Forks
659
Avg merge
13h 15m
Merged PRs (30d)
51

Description

Objective

Evaluate and adopt practical .NET 11 SDK, runtime and BCL improvements after baseline support lands. Start with CI measurements; make narrow API changes only where correctness, maintainability or measured performance justify them.

Blocked by: #4998 (Add support for .NET 11).
Related migration: #5207, which remains draft until GA.
Milestone: 7.0.x.

C# syntax modernization and compiler/parser policy are handled by #5209/#5207 and are outside this follow-up.

Proposed outcomes

  • Complete/reuse GA migration and tooling prerequisites in #4998/#5207.
  • Establish controlled SDK/runtime performance comparisons in CI.
  • Evaluate a narrow managed-backend process capture change with net10 compatibility.
  • Consider a decompression experiment only if profiling justifies it.
  • Record measured results, compatibility checks and deferred candidates.

The full research and proposed plan are included below. Repository links point to the researched revision; PR status and platform documentation are dated snapshots to refresh before implementation.

Research and official-source evidence

GitVersion opportunities in .NET 11

Research snapshot: 2026-09-15. No performance measurements or implementation changes have been made.

Recommendation

At GA, complete the existing additive migration, adopt the SDK for tooling, and measure runtime-only gains before introducing new APIs. The best small implementation candidate is the managed backend's process-output capture. Span-based decompression merits a bounded experiment only if profiling identifies object inflation as material. Defer GC tuning, collection rewrites, runtime-async opt-in, NativeAOT, and packaging-format changes.

No performance improvement has been established for GitVersion. Official runtime microbenchmarks establish mechanisms, not application speedups.

Scope and evidence baseline

  • Local checkout: bd1f3031893f96104f879ad6343a787ebebe074a. Paths below refer to this revision, not the PR branch.
  • PR #5207, read live at 754ad91fe10ab83b96b19b50255910e553986223, is open and draft. Its scope already includes stable net10/net11 multi-targeting, MSBuild tool selection, SDK RC1, and dual-runtime Docker coverage. Its description retains net10 standalone archives, build tooling, and experimental CLI targets; full cross-platform packaging and Windows task-host verification remain open. Description-reported validation is not independently audited CI evidence here.
  • PR #5209 is merged (2026-09-15). C# syntax, language/compiler/parser policy are excluded from this proposal.

Official sources

These are mutable sources checked on the research date; refresh at GA. Microsoft Learn overview/search snapshots lagged the RC1 detail pages, so release status uses the release announcement/download page and features use the RC1 source documents.

ID Official evidence Use
S1 .NET 11 RC1 announcement and download RC1 availability; download marks it go-live, which does not mean GA
S2 Runtime changes, RC1 source JIT, R2R, runtime async, hardware
S3 Library changes, RC1 source Process, streams, compression, collections
S4 SDK changes, RC1 source SDK footprint, native CLI entry point, MSBuild server, test issues
S5 Hardware compatibility note Deployment limits and R2R fallback
S6 Support policy and overview Stable support lifecycle; expected November 2026 GA

Repository boundaries

Surface Concrete local references Consequence
SDK global.json pins 10.0.401 and Microsoft.Testing.Platform SDK upgrade affects build/test/tool dispatch, independently of application TFM
Stable runtime src/Directory.Build.props:3; src/GitVersion.App/GitVersion.App.csproj:14 Local net10 baseline; app sets RollForward=LatestMajor. Record the actual selected runtime: TFM alone cannot identify the runtime in a benchmark
MSBuild consumers src/GitVersion.MsBuild/GitVersion.MsBuild.csproj; src/GitVersion.MsBuild/msbuild/tools/GitVersion.MsBuild.targets Package task hosts and consumer TFMs differ. Reuse #5207's selection/fallback coverage; do not impose net11 on retained net10 consumers
Standalone publishing build/build/Tasks/Package/PackagePrepare.cs; build/common/Utilities/Constants.cs:9 Self-contained, single-file, native self-extraction; publishes the LTS target. Installing SDK/runtime 11 does not upgrade an embedded net10 runtime
Tool/package assembly build/build/Tasks/Package/PackageNuget.cs Global tool pack and MSBuild tool publishing need artifact-level verification, beyond solution compilation
Cake tooling build/Directory.Build.props:4; build/Directory.Packages.props net10 Frosting executables; Cake.Frosting 6.2.0, Compression 0.4.0 and several addins/modules. SDK 11 can build net10; executing tooling on 11 is a separate GA change and compatibility check
Experimental CLI new-cli/Directory.Build.props:3; new-cli/GitVersion.Cli/Program.cs:7; new-cli/GitVersion.Cli/GitVersion.Cli.csproj:23 net10, explicit modules, DI, generated commands, LibGit2Sharp backend. Managed-backend improvements are not automatically new-cli improvements
Generator new-cli/GitVersion.Cli.Generator/GitVersion.Cli.Generator.csproj:4 netstandard2.0 analyzer with Roslyn, PolySharp, Scriban and explicit System.Text.Json package. Keep host-compatible target; net11 BCL calls cannot simply be added because its consuming app targets net11
Test orchestration build/build/Tasks/Test/UnitTest.cs:54; .github/workflows/_unit_tests.yml; .github/workflows/new-cli.yml:75 Stable runner sets framework, rebuilds with CI=false for snapshot paths, and uses NoRestore. Experimental workflow already uses no-build. Do not flatten these into one optimization

Ranked opportunities

Benefit is qualitative and conditional. Evidence distinguishes existence of a platform feature from proof it helps this application.

Rank Opportunity Expected benefit / evidence Effort / risk Decision and validation
1 GA SDK/tooling adoption, preserving #5207 boundaries Broad developer/CI reach; high feature evidence, unknown GitVersion timing Low–medium / medium Proceed at GA; compare SDK startup, repeated Cake-driven commands, full CI and package outputs
2 Runtime-only JIT/BCL baseline on 11 Potential calculation/startup/allocation improvements; high mechanism evidence, no application result Low measurement effort / low change risk Measure before code changes; both Git backends and launch modes
3 Process capture helper inside GitCliExecutor Smaller synchronization surface; possible Windows I/O benefit. Strong source fit; no proven defect or speedup Small–medium / medium First optional API patch after GA and review; prove text, exit, environment and failure parity
4 Streamless Deflate decoder for managed Git objects Potential per-object allocation reduction; documented APIs, unproven bottleneck Medium–high / high Profile first; isolate prototype at decoder seam only if justified
5 R2R publishing experiment Potential cold startup gain; specialized default comparers documented Medium / medium–high Separate artifact experiment; compare startup, size and hardware fallback before any default
6 New memory-stream adapters / comparer factory Convenience or avoided copy only at suitable call sites; poor fit in inspected hot paths Low per site / medium semantic risk Defer; require a specific redundant copy or comparer duplication
1. SDK, build and publish tooling

S4 documents a NativeAOT dotnet entry point, including out-of-process tool resolution/launch, and a default warm MSBuild server. The former is relevant to dotnet gitversion; a direct dotnet-gitversion shim or standalone executable has a different launch path. The latter may help the repeated project invocations in UnitTest.cs, but isolated CI jobs may not retain a warm worker. Neither turns GitVersion into a NativeAOT application.

Linux/macOS SDK assembly deduplication reduces SDK installation footprint (S4). This can help CI/development image acquisition. It does not establish smaller GitVersion packages or runtime-only images. Preserve symlinks if tooling copies SDK directories. Measure compressed downloads and unpacked size separately.

At GA, retarget the Cake executables only as planned, checking addins, package/coverage/docs tasks and generated artifacts. Do not update every package major simply because the SDK changes. S4's SDK container reproducibility features apply to PublishContainer; existing Cake/Docker workflows do not acquire them automatically. A container-pipeline rewrite has insufficient benefit here.

MTP options are possibilities, not proposed command changes. In particular, skipping dependency builds conflicts with the intentional snapshot-path rebuild in UnitTest.cs:58. A current-runtime shortcut would also undermine explicit net10/net11 coverage. S4 records RC1 relative-project-path failures, all-skipped exit-code issues and reduced exit-code diagnostics; check the referenced SDK fixes at GA and do not silently reinterpret failures as success. No local test commands were executed or proposed.

2. Automatic runtime benefits, startup and memory

Running on runtime 11 makes JIT/BCL improvements available without rewriting GitVersion. Recompilation alone with SDK 11 while still executing net10 does not do that. Net11 API use needs a net11 reference surface; changing generated R2R/native code requires publishing again.

S2 documents broader generic/default-interface devirtualization, constant folding and bounds-check elimination. These could affect managed traversal and parsing, but no exact optimized call site has been proven. Inspect src/GitVersion.Git.Managed/History/GitRevisionWalker.cs:29 (commit cache), its dictionaries/sets at lines 77, 128 and 299, and GitPackMemoryCache.cs:31 for representative allocation-heavy workloads. Native libgit2 internals do not become faster from managed JIT improvements; wrappers and surrounding calculation can still benefit.

S2 documents R2R specialization of default comparers. Its operation-level benchmark is not an expected GitVersion multiplier. Distinguish framework R2R improvements available with the installed runtime from choosing R2R for GitVersion application assemblies. No new publish default is recommended.

No reviewed official evidence establishes a GitVersion-specific GC improvement. Track allocated bytes, collection counts/pause time and peak process memory; distinguish retained caches from transient garbage and native allocations. Keep GC settings unchanged. A short CLI may finish before steady-state tiered optimizations matter, while repeated invocations in a long-lived host have different behavior.

Runtime Async remains a preview opt-in for application code in S2. Runtime libraries already use it, so their changes can be inherited while leaving GitVersion code alone. The new CLI's async entry point (Program.cs:24) is not evidence that runtime-async migration will matter. Defer explicit opt-in and broad async rewrites.

3. Process APIs: the most concrete small follow-up

src/GitVersion.Git.Managed/CommandLine/GitCliExecutor.cs:63 creates a Process, two StringBuilders and two ManualResetEventSlim instances, wires both output events, waits for exit and drains both streams. S3 provides RunAndCaptureText/async helpers and documents overlapped redirected I/O on Windows. The underlying Windows improvement may be inherited on runtime 11 even without using a new helper.

Preserve the existing IGitCliExecutor/GitCliResult contract and process configuration: ArgumentList, working directory, no credential prompts, locale, removal of inherited Git repository variables, credential-redacted logs, nonzero exit handling and missing-Git exception. The current event handler normalizes lines via AppendLine; whole-text capture could preserve original newlines/final-line termination instead. Decide and test this explicitly. Exercise simultaneous large stdout/stderr to prove complete capture, plus empty output, Unicode, spaces in arguments, missing executable and nonzero exits. Existing src/GitVersion.Core.Tests/Core/GitCliMutatorTests.cs covers the surrounding integration; a focused executor test would be new work requiring review.

Net10 support means a conditional net11 implementation plus unchanged fallback, or deferral until the fallback can be removed. Prefer one small private boundary; do not spread conditional compilation through callers. Adding timeouts, process-tree termination or cancellation would change semantics and is outside a capture-only patch. New process APIs do not remove the managed backend's dependency on the Git executable for mutation.

4. I/O and compression: measure before implementation

GitPack.cs:41 opens index/pack files lazily. GitZLibStream.cs:33 validates the two-byte zlib header and wraps a DeflateStream; reads and forward seeking carry additional state. S3's span-based Deflate/ZLib decoders and Reset support could reduce stream allocations for repeated objects, but require input/output buffer ownership, partial decode handling and correct decoder reuse.

Do not substitute a full-buffer decode for lazy reads: large blobs, delta chains and concurrent cache views may increase peak memory. GitPackMemoryCacheStream.cs:12 grows a MemoryStream on demand; GitPackMemoryCacheViewStream.cs:48 coordinates views and positions. Fixed memory adapters are not replacements for these behaviors. Validate against GitZLibStreamTests.cs, LooseObjectTests.cs, PackedObjectTests.cs and malformed/truncated/delta-boundary cases in src/GitVersion.Git.Managed.Tests/.

S3's pipe support in RandomAccess/SafeFileHandle is useful for process plumbing, not evidence to rewrite regular-file pack reading. Existing FileStream use already receives applicable runtime fixes. Avoid low-level pipe ownership changes alongside the process helper.

Zstandard is a new compression option, not a replacement for Git's zlib object representation. Defer it for both repository storage and release archives. Existing Cake.Compression abstractions may use different libraries; .NET ZIP behavior changes are relevant only where the actual path uses those BCL APIs. Archive extraction/listing compatibility is part of packaging validation, not a reason to redesign archive formats.

5. Collections and other APIs to defer

S3 adds BitArray span constructors/PopCount and a key-selector EqualityComparer factory. The inspected traversal uses GitObjectId-keyed sets/dictionaries, not an existing BitArray algorithm. Converting to bitsets would require assigning dense IDs and change algorithm/memory tradeoffs. No .NET 11 justification was found for it. The comparer factory may simplify a future exact call site; it is not a performance optimization by itself.

Do not rebrand existing span APIs, Frozen collections, alternate lookup or generic collection tuning as new .NET 11 work. Mutable caches are not candidates for blanket freezing. JSON/new stream helpers warrant adoption only at a demonstrated allocation/behavior need, and never by pulling net11 runtime dependencies into the netstandard generator. No such production call site was established here.

Compatibility and maturity gates

RC1 go-live support does not override the GA merge gate. Revalidate final SDK/runtime pins, support policy and API signatures. .NET 10 remains the LTS compatibility baseline; do not invent a final .NET 11 support-end date from preview information.

S5 raises the x86/x64 baseline and distinguishes that hard requirement from newer R2R targets, which can fall back to JIT. S2 and S5 disagree on the Windows Arm64 minimum in their current text; do not publish a definitive Arm64 claim until the final compatibility note/runtime matrix agree. Include representative older supported CPUs in startup validation where feasible.

Keep native libgit2 RID assets, OS libraries, musl/glibc and architecture checks in artifact CI. Single-file native extraction and Windows MSBuild task hosts deserve explicit smoke tests. New-cli still references LibGit2Sharp; generated commands alone do not prove trimming or NativeAOT compatibility. Defer either deployment conversion until a separate dependency/reflection audit and measurable startup requirement justify it.

Measurement design

Use CI artifacts and controlled runners, not local builds in this research. Hold source SHA, fixture repository, configuration, output mode, backend, CPU/OS, Git/native-library versions and package versions constant. Record actual loaded runtime and SDK. Compare (a) the same compatible net10 IL on runtimes 10/11 with explicit runtime selection, then (b) equivalent net10/net11 builds, then any isolated API or publish change. The existing LatestMajor setting makes accidental cross-contamination possible.

Measure direct executable versus dotnet gitversion, first process versus repeated process, cache miss versus cache hit, loose versus packed repositories, small versus large histories and representative shallow/worktree layouts. Repeated fresh processes are not in-process JIT warm-up. Record elapsed time distributions, CPU, allocation/GC data, peak RSS/working set, bytes read and artifact/download size. Benchmark new-cli separately with redirected input: its Program.cs:25 can otherwise wait for a key.

Require unchanged semantic version variables/JSON and exit behavior. Compare both backends where available; do not attribute Git child-process time or native allocations to managed GC. Use enough repetitions to show variance and confidence intervals; predeclare a practical improvement threshold before inspecting results. Keep noisy performance experiments separate from correctness gates. Publish exact-SHA results and limitations before claiming benefit.

Proposed implementation and validation plan

Proposed .NET 11 follow-ups

Status: proposed follow-up; implementation not started. The research below records source evidence, repository references and uncertainty.

Proposed sequence

A. Finish existing GA migration; do not duplicate it

Owner surface: draft #5207.

  • At GA, refresh SDK/runtime/container pins and confirm final API and platform requirements.
  • Preserve stable net10/net11 support, MSBuild selection/fallback and net10 standalone archive policy already covered there.
  • Verify final-head CI for managed and LibGit2Sharp backends, retained frameworks, real packed tool installation, MSBuild consumers/task hosts, OS/RID artifacts and native loading.
  • Resolve the official Windows Arm64 documentation discrepancy before documenting final requirements.
  • Exclude all syntax/compiler/parser modernization covered by #5209/#5207.

Acceptance: reviewable final GA artifacts and current-head CI evidence. An earlier green commit or PR description alone is insufficient.

B. Narrow tooling adoption at GA

Potential files: global.json, build/Directory.Build.props, build/Directory.Packages.props, relevant setup workflows. Change only what remains after A.

  • Retarget Cake tooling as planned and verify installed addin/module compatibility using CI's build, package, test-report and docs tasks.
  • Keep experimental CLI target changes separate from stable distribution policy; do not retarget new-cli/GitVersion.Cli.Generator/GitVersion.Cli.Generator.csproj away from netstandard2.0.
  • Retain explicit test framework selection and the stable snapshot-path rebuild. No automatic adoption of skip-dependencies/current-runtime options.
  • Check RC1 MTP issues against the GA SDK; preserve meaningful failures and reported counts.

Acceptance: full relevant CI and stable generated/package outputs. Do not mix new API changes into this patch.

C. Establish CI performance evidence

First proposed new work after review: a bounded benchmark job or existing performance-harness extension, selected after checking the current harness. No permanent benchmark dependency or workflow has been added by this research.

  • Start with stable CLI launch + calculation on one controlled runner and pinned small/large packed repositories.
  • Separate SDK launch overhead, runtime-only effects and net11 compilation; confirm loaded runtimes rather than infer them from TFM.
  • Compare managed/libgit2, direct/tool launch, cold/warm repository cache, and elapsed/CPU/allocation/peak-memory metrics.
  • Expand to Windows/macOS and new-cli only when the initial comparison is repeatable. Redirect new-cli input to avoid its interactive wait.
  • Archive source SHA, inputs, runtime/SDK versions, raw measurements and output parity. Agree practical thresholds before assessing the result.

Acceptance: reproducible distributions and no version/output regressions. A neutral result is useful and does not trigger an API rewrite.

D. Optional process capture patch

Proceed only after A–C and review of the net10 fallback maintenance cost.

Potential production file: src/GitVersion.Git.Managed/CommandLine/GitCliExecutor.cs only, plus focused tests selected during implementation.

  • Keep the public/internal caller contract and process configuration unchanged.
  • Use the final net11 capture helper behind one conditional boundary; preserve net10 behavior.
  • Resolve line-ending/final-newline semantics explicitly.
  • Validate large simultaneous streams, exit codes, missing Git, Unicode, arguments, working directory, environment scrubbing and redacted logs on both target frameworks.
  • Measure again; describe maintainability improvement separately from speed.

Acceptance: parity demonstrated in CI, no deadlock/data loss, no new behavior such as timeout or cancellation. If the helper needs comparable custom synchronization or conditional complexity, defer the patch.

E. Conditional decompression experiment

Proceed only if C attributes meaningful cost to managed object inflation.

Candidate boundary: src/GitVersion.Git.Managed/GitZLibStream.cs, with adjacent object/pack readers inspected before edits. Prototype a final net11 streamless decoder without replacing cache architecture.

Acceptance: existing format/header semantics, partial-read/seek behavior, truncated input, delta objects and lifetime handling remain correct; measurable end-to-end benefit and no peak-memory regression. Otherwise discard the experiment. Keep any prototype separate from default production behavior.

Deferred

  • NativeAOT/trimming and application-wide R2R defaults: dependency audit and startup evidence required.
  • Explicit Runtime Async: preview maturity and workload relevance unresolved.
  • GC tuning, bitset/frozen-cache rewrites and broad async conversion: no established bottleneck.
  • Zstandard archive/storage changes and SDK-container pipeline migration: poor fit or separate product decision.
  • BCL stream adapters/comparer factories without a demonstrated local need.

Review decision

Recommended next work: A/B at GA and C as a separate measurement task. Keep D optional and E dependent on profiling. No production changes are needed merely to benefit from the SDK/runtime improvements.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with prerequisites in #4998 and #5207, then inspect global.json, src/Directory.Build.props, build/build/Tasks/Test/UnitTest.cs, and .github/workflows/_unit_tests.yml. Compare SDK/runtime behavior and package outputs in CI before considering the named process-capture or decompression surfaces. Done means measured results, compatibility checks, and documented deferred candidates.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, git, github-actions
Domain
build-system, ci-cd, devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.