CodeLogic.GitHelper
5.0.114-preview
See the version list below for details.
dotnet add package CodeLogic.GitHelper --version 5.0.114-preview
NuGet\Install-Package CodeLogic.GitHelper -Version 5.0.114-preview
<PackageReference Include="CodeLogic.GitHelper" Version="5.0.114-preview" />
<PackageVersion Include="CodeLogic.GitHelper" Version="5.0.114-preview" />
<PackageReference Include="CodeLogic.GitHelper" />
paket add CodeLogic.GitHelper --version 5.0.114-preview
#r "nuget: CodeLogic.GitHelper, 5.0.114-preview"
#:package CodeLogic.GitHelper@5.0.114-preview
#addin nuget:?package=CodeLogic.GitHelper&version=5.0.114-preview&prerelease
#tool nuget:?package=CodeLogic.GitHelper&version=5.0.114-preview&prerelease
CodeLogic.GitHelper
Programmatic Git repository management for CodeLogic 5 — clone, fetch, pull, push, commit, branch, and reset, all from configured repositories.
A thin, async wrapper over LibGit2Sharp that manages a pool of named repositories. Every operation returns a CodeLogic Result<T> / Result instead of throwing, with a typed Error (NotFoundError, ValidationError, ...) and a stable git.* code on failure; fetch, pull and push return GitDiagnostics (timing and transfer counters) as their value; and the standout EnsureUpToDateAsync gives you one idempotent call that clones a repository if it's missing or hard-resets it to the remote tip if it already exists.
Install
dotnet add package CodeLogic.GitHelper
Quick start
using CL.GitHelper;
using CL.GitHelper.Errors;
using CodeLogic.Core.Results;
await Libraries.LoadAsync<GitHelperLibrary>(); // register before ConfigureAsync()
await CodeLogic.ConfigureAsync();
await CodeLogic.StartAsync();
var git = Libraries.Get<GitHelperLibrary>();
var repo = await git.GetRepositoryAsync("Default");
// One idempotent call: clones if missing, else fetches + hard-resets to the remote tip.
Result<RepositoryInfo> sync = await repo.EnsureUpToDateAsync();
if (sync.IsSuccess)
Console.WriteLine($"On {sync.Value!.CurrentBranch} @ {sync.Value.HeadCommitSha[..7]}");
else if (sync.Error is ConflictError { Code: GitErrors.UncommittedChangesCode })
Console.WriteLine("Local changes present; not resetting.");
else
Console.WriteLine($"Sync failed: {sync.Error!.Code}: {sync.Error.Message}");
Features
- Idempotent sync —
EnsureUpToDateAsyncclones-or-updates in a single call; the easiest way to keep a working copy at the remote tip. - Full remote workflow —
CloneAsync,FetchAsync,PullAsync,PushAsync, each with an options model andCancellationToken. - Commit & status — stage and commit with author metadata (
CommitAsync), and inspect the working tree (GetStatusAsync). - Branches — list local/remote branches and check them out (
ListBranchesAsync,CheckoutBranchAsync). - Reset & history —
ResetHardAsyncandGetCommitLogAsync. - Batch operations —
FetchAllAsyncandGetAllStatusAsyncrun across every configured repository with bounded concurrency. - Repository caching — configurable in-memory pool with automatic eviction.
- No exceptions — every operation returns a CodeLogic
Result<T>(orResultfor checkout/reset). Failures carry anErrorof the matching kind (NotFoundError,ValidationError,UnauthorizedError,ConflictError,InternalError, ...) with a stable code fromGitErrors(e.g.git.remote_not_found); caught exceptions are logged and their type name is inError.Details.
Configuration
Auto-generated on first run as config.githelper.json:
{
"enabled": true,
"baseDirectory": "",
"defaultTimeoutSeconds": 300,
"maxConcurrentOperations": 3,
"enableRepositoryCaching": true,
"cacheTimeoutMinutes": 30,
"repositories": [
{
"id": "Default",
"name": "My Repository",
"repositoryUrl": "https://github.com/username/repository.git",
"localPath": "my-repo",
"defaultBranch": "main",
"username": null,
"password": null,
"autoFetch": false,
"autoFetchIntervalMinutes": 0,
"timeoutSeconds": 300
}
]
}
| Setting | Default | Description |
|---|---|---|
Enabled |
true |
Master switch; when false the library is inactive and health reports disabled. |
BaseDirectory |
"" |
Root for relative LocalPath values; empty means the library data directory. |
DefaultTimeoutSeconds |
300 |
Default per-operation timeout (1–3600). |
MaxConcurrentOperations |
3 |
Concurrency cap for batch operations (1–20). |
EnableRepositoryCaching |
true |
Keep opened repositories in an in-memory pool. |
CacheTimeoutMinutes |
30 |
Idle eviction window (0–1440; 0 = never expire). |
Repositories |
one entry | Per-repository definitions (URL, local path, branch, credentials). |
Each repository entry: Id, Name, RepositoryUrl (required), LocalPath (required; absolute or relative to BaseDirectory), DefaultBranch, Username, Password (PAT), AutoFetch, AutoFetchIntervalMinutes, TimeoutSeconds. Authentication is HTTPS only — see the full guide for details. SSH key fields exist in config but are not currently wired.
Changing config while running
With CodeLogic 4.9+, config.githelper.json applies live when changed through Libraries.UpdateConfigAsync, Libraries.ReloadConfigAsync, or the config file watcher. Only the repositories that changed are touched:
- Changed or removed repository: dropped from the cache. Its old
GitRepositoryis disposed once the git operation running on it finishes, and the nextGetRepositoryAsyncopens it with the new settings. CallGetRepositoryAsyncagain rather than keeping an old instance. - Added repository: available at once.
- Untouched repositories: keep their open instances.
- Library-wide settings (cache, timeouts, concurrency) apply at once. A changed
baseDirectoryre-resolves every relativelocalPath. - Added or changed repositories with
autoFetchare fetched in the background. - Repositories added with
RegisterRepositoryare kept across changes and never written to the file. enabledcan be switched either way.
Documentation
Full guide: CL.GitHelper documentation
Requirements
- CodeLogic 5.0+ · .NET 11
- LibGit2Sharp 0.32.x
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net11.0 is compatible. |
-
net11.0
- CodeLogic (>= 5.0.0-preview && < 6.0.0)
- LibGit2Sharp (>= 0.32.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on CodeLogic.GitHelper:
| Package | Downloads |
|---|---|
|
CodeLogic.WebLogic
Web application toolkit for CodeLogic 4 — routing, templates, forms, an ordered security pipeline, auth flows and realtime. No third-party dependencies beyond CodeLogic.*. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.0.116-preview | 48 | 11/1/2026 |
| 5.0.115-preview | 102 | 11/1/2026 |
| 5.0.114-preview | 33 | 10/31/2026 |
| 5.0.113-preview | 33 | 10/31/2026 |
| 4.9.98 | 553 | 10/25/2026 |
| 4.8.93 | 62 | 9/23/2026 |
| 4.8.87 | 103 | 9/13/2026 |
| 4.8.86 | 64 | 9/13/2026 |
| 4.8.85 | 60 | 9/12/2026 |
| 4.6.72 | 233 | 6/20/2026 |
| 4.6.69-preview | 65 | 6/20/2026 |
| 4.5.2 | 139 | 5/24/2026 |
| 4.5.2-preview.68 | 88 | 6/20/2026 |
| 4.5.1 | 188 | 5/24/2026 |
| 4.5.1-preview.56 | 127 | 5/24/2026 |
| 4.4.2-preview.53 | 90 | 5/24/2026 |
| 4.4.1 | 129 | 5/24/2026 |
| 4.0.5 | 128 | 5/15/2026 |
| 4.0.4 | 132 | 5/9/2026 |
| 4.0.3 | 138 | 5/9/2026 |
# CL.GitHelper — Changelog
All notable changes to **CodeLogic.GitHelper** are documented here. Versions follow
[Semantic Versioning](https://semver.org/).
## 5.0 (unreleased)
### Breaking
- Targets **.NET 11** (`net11.0`) and requires **CodeLogic 5.0** (`[5.0.0, 6.0.0)`). On .NET 10, stay on
4.9.x. CodeLogic 5 makes `Result<T>` / `Result` C# 15 unions and `Error` a closed record with
kind subtypes (`NotFoundError`, `ValidationError`, ...). This library now returns those types
directly (see below), so its results can be matched exhaustively with `switch`.
- **`GitResult<T>` is removed**; every operation returns CodeLogic's `Result<T>` / `Result`
(`CodeLogic.Core.Results`). `ErrorMessage` → `Error.Message`; `Exception` is gone (the library
logs it, and `Error.Details` holds the exception type name); `Diagnostics` is gone (see below).
- Signature changes on `GitRepository`:
- `FetchAsync`, `PullAsync`, `PushAsync`: `Task<GitResult<bool>>` → `Task<Result<GitDiagnostics>>`.
The diagnostics are now the success value. A pull's diagnostics include its fetch step's
messages, and a failed fetch inside a pull returns the fetch's own error.
- `CheckoutBranchAsync`, `ResetHardAsync`: `Task<GitResult<bool>>` → `Task<Result>`.
- `CloneAsync`, `EnsureUpToDateAsync`, `GetRepositoryInfoAsync`: `Task<GitResult<RepositoryInfo>>`
→ `Task<Result<RepositoryInfo>>`. `CommitAsync` → `Task<Result<CommitInfo>>`, `GetStatusAsync`
→ `Task<Result<RepositoryStatus>>`, `ListBranchesAsync` → `Task<Result<List<BranchInfo>>>`,
`GetCommitLogAsync` → `Task<Result<List<CommitInfo>>>`. Clone, commit and status no longer
return diagnostics; clone logs its duration and messages instead.
- `GitHelperLibrary` / `GitManager`: `FetchAllAsync` → `Task<Dictionary<string, Result<GitDiagnostics>>>`,
`GetAllStatusAsync` → `Task<Dictionary<string, Result<RepositoryStatus>>>`.
- Failures have a kind and a stable code, all listed as constants on the new
`CL.GitHelper.Errors.GitErrors`:
- `NotFoundError`: `git.repository_not_found` (not cloned), `git.remote_not_found`,
`git.branch_not_found` (checkout or reset target), `git.not_found`.
- `ValidationError`: `git.empty_commit_message`, `git.nothing_to_commit`, `git.ssh_not_supported`.
- `UnauthorizedError`: `git.authentication_failed`.
- `ConflictError`: `git.directory_not_empty`, `git.uncommitted_changes`, `git.checkout_conflict`,
`git.non_fast_forward`.
- `UnavailableError`: `git.cancelled`.
- `InternalError` (anything else): `git.clone_failed`, `git.fetch_failed`, `git.pull_failed`,
`git.push_failed`, `git.commit_failed`, `git.status_failed`, `git.info_failed`,
`git.list_branches_failed`, `git.checkout_failed`, `git.reset_failed`, `git.log_failed`.
### Changed
- Fetch now records `ObjectCount` and `BytesTransferred` in its diagnostics.
- Failures of read operations (status, info, branches, log) are logged at debug level with the
full exception; before, the exception was only on the result.
- LibGit2Sharp is pinned to 0.32.0 instead of floating (`0.32.*`).
### Documentation
- Configuration examples in the README and the docs use the camelCase keys the CodeLogic loader reads.
The PascalCase keys shown before are matched case-sensitively and were ignored, leaving defaults active.
### Fixed
- **Cache eviction no longer disposes a repository under a running operation.** The idle-expiry timer,
`GetRepositoryAsync` replacing a stale entry, `EvictFromCacheAsync` and `ClearCacheAsync` disposed the
evicted `GitRepository` at once. Idle time only counts `GetRepositoryAsync` calls, so a clone or fetch that ran
longer than `CacheTimeoutMinutes` had its LibGit2 handle and lock disposed underneath it (the operation's
lock release then threw `ObjectDisposedException`). Evicted instances are now disposed once their current
operation finishes, as config changes and disabling the library already did.
## 2026-10-24
### Added
- **Live config changes** (requires CodeLogic 4.9+). `GitHelperLibrary` implements `IConfigReloadable`:
a change to `config.githelper.json` made through `Libraries.UpdateConfigAsync`,
`Libraries.ReloadConfigAsync` or the config file watcher is applied without a restart, touching only
the repositories that changed. Changed or removed repositories are evicted from the cache and their
old `GitRepository` is disposed once its running git operation finishes; untouched repositories keep
their instances; library-wide settings and `baseDirectory` apply at once; added or changed
repositories with `autoFetch` are fetched in the background. `Enabled` can be switched either way.
The `RequiresRestart` hints on `id`, `repositoryUrl`, `localPath` and `baseDirectory` were removed.
### Changed
- `GitManager` keeps its own copy of the configuration. Repositories added with `RegisterRepository`
no longer appear in `Configuration.Get<GitHelperConfig>()` (and so can no longer be written to
`config.githelper.json` by a later save); they are kept across config changes.
## 2026-09-12
### Changed
- Unified the version line with the CodeLogic framework on **4.8.x**. Every official
library and the framework now share one `major.minor`, so a given `4.8.<patch>`
means the same generation across all packages.
- `version.txt` moved from `4.6` to `4.8`. The patch component remains the CI run
number, composed at pack time; `AssemblyVersion` stays pinned at `Major.Minor.0.0`
(now `4.8.0.0`) so every patch in the line loads interchangeably.
## 2026-06-20
### Fixed
- SSH is not supported by the bundled LibGit2Sharp transport; configuring an SSH
key now logs a clear warning and cloning an SSH URL (`git@…` / `ssh://…`)
fails fast with an explanatory message instead of silently doing nothing.
- `EnsureUpToDateAsync` now refuses to hard-reset (and discard) a dirty working
tree unless called with `discardLocalChanges: true`, preventing accidental
data loss.
- The repository cache now expires entries by idle time rather than absolute
age, so a repository in active use is no longer disposed out from under a
caller; batch concurrency is clamped to at least 1; `CommitOptions` gained a
`CancellationToken`.
### Documentation
- Full house-style rewrite of the README and the `docs/libs/githelper.md` deep guide.
- Documented the repository workflow around `GetRepositoryAsync` and highlighted
`EnsureUpToDateAsync` as the idempotent clone-or-update easy path.
- Documented the per-operation options models (`GitCloneOptions`, `GitFetchOptions`,
`GitPullOptions`, `GitPushOptions`, `GitCommitOptions`) and the `MergeStrategy` enum.
- Documented the `GitResult<T>` / `GitDiagnostics` contract and the result-bearing models
(`RepositoryInfo`, `CommitInfo`, `BranchInfo`, `RepositoryStatus`, `FileStatusEntry`).
- Documented manager batch operations (`FetchAllAsync`, `GetAllStatusAsync`), runtime
registration, repository caching (`CacheStats` / `CacheEntryStats`), and the health check.
- Clarified authentication: HTTPS only, PAT-only auth sends `x-access-token`, and the SSH
key fields are present in config but not currently wired.
## [4.5.2] — 2026-06-20
### Documentation
- Documented the full `GitRepository` workflow in the README: `CloneAsync`,
`FetchAsync`, `PullAsync`, `PushAsync`, `ListBranchesAsync`, `CheckoutBranchAsync`,
`CommitAsync` (with `FilesToStage`), and `GetCommitLogAsync`.
- Documented the `ResetHardAsync` and `EnsureUpToDateAsync` sync helpers with examples.
- Documented the `GitResult<T>` return contract (`IsSuccess` / `Value` / `ErrorMessage`
/ `Diagnostics`).
- Documented `GitManager` access via `GetManager()`, including `ExecuteOnAllAsync`,
`HealthCheckAsync`, runtime `RegisterRepository` / `UnregisterRepositoryAsync`, and
cache control (`GetCacheStats`, `ClearCacheAsync`).
- Clarified authentication: PAT-only auth sends `x-access-token`, and the SSH key
configuration fields are reserved but not currently wired (use HTTPS URLs).
## [4.5.0] — 2026-05-24
### Changed
- **Unified versioning.** All CodeLogic.Libs now share a single version line
controlled by `version.txt` in the repo root. This is a version alignment
release — no functional changes to this library.
## [4.0.4] — 2026-04-16
### Changed
- README + manifest refresh for the v4 baseline. No functional changes vs 4.0.3.
- `LibraryManifest.Version` now reads from assembly metadata.
## [4.0.3] — 2026-04-15
### Added
- Wired credentials through to `Clone` / `Fetch` / `Pull` and added
`ResetHard` + `EnsureUpToDate` helpers.
## [4.0.2] — 2026-04-09
### Changed
- Annotated GitHelper configuration with `[ConfigField]` for the admin UI surface.
- Aligned with the v4 baseline across all libraries.
## [4.0.0] — 2026-04-09
Major rewrite. Republished as v4.0.0 to reset the version line under the
unified v4 baseline. Thin libgit2sharp wrapper for programmatic clone /
pull / fetch / reset.
### Notes
- Earlier history is retained in the
[git log](https://github.com/zyntal-com/CodeLogic.Libs/commits/main/CL.GitHelper).