GitPorcelain 1.0.0
dotnet add package GitPorcelain --version 1.0.0
NuGet\Install-Package GitPorcelain -Version 1.0.0
<PackageReference Include="GitPorcelain" Version="1.0.0" />
<PackageVersion Include="GitPorcelain" Version="1.0.0" />
<PackageReference Include="GitPorcelain" />
paket add GitPorcelain --version 1.0.0
#r "nuget: GitPorcelain, 1.0.0"
#:package GitPorcelain@1.0.0
#addin nuget:?package=GitPorcelain&version=1.0.0
#tool nuget:?package=GitPorcelain&version=1.0.0
GitPorcelain
GitPorcelain is a managed, dependency-free .NET API for the Git command-line client already installed on a user's machine.
It combines typed operations for common workflows with a raw command escape hatch. Repository behavior, transports, credential helpers, SSH configuration, and compatibility remain Git's responsibility rather than a bundled native library's.
Why GitPorcelain?
- No native library deployment or platform-specific runtime assets
- Windows, Linux, macOS, trimming, and NativeAOT-friendly design
- Asynchronous operations with cancellation and command timeouts
- No shell command construction: every argument is passed as a separate process argument
- Typed results for status, branches, remotes, commits, tags, stashes, worktrees, and submodules
- NUL-delimited and byte-preserving parsing where Git supports it
- Git credential-helper, SSH, and external AskPass compatibility
- Safe defaults: no terminal prompts, no force checkout/push/delete, dry-run clean
- Raw
RunAsyncAPIs for Git features not yet represented by a typed method
Requirements
- .NET 8 or later
- Git 2.31 or later on
PATH, or an explicit executable path
The package has no runtime NuGet dependencies. Once the package is published, install it with:
dotnet add package GitPorcelain --prerelease
Quick start
using GitPorcelain;
GitClient git = new();
GitVersion version = await git.GetVersionAsync();
GitRepository? repository = await git.DiscoverAsync(Environment.CurrentDirectory);
if (repository is null)
return;
GitHead head = await repository.GetHeadAsync();
GitStatus status = await repository.GetStatusAsync(new GitStatusOptions
{
UntrackedFiles = GitUntrackedFilesMode.All,
});
Console.WriteLine(head.Name ?? $"detached at {head.ObjectId}");
foreach (GitStatusEntry entry in status.Entries)
Console.WriteLine($"{entry.IndexStatus}/{entry.WorkTreeStatus} {entry.Path.Value}");
See the runnable sample and the extended API guide.
Operations
| Area | Typed APIs |
|---|---|
| Client | version detection, init, clone, repository discovery, raw commands |
| Status | porcelain-v2 branch/status, untracked, ignored, conflicts, renames, stash count |
| File-manager metadata | batched status and last-commit metadata for many paths |
| History | log, last commit for a path, author/committer/parents/message metadata |
| Diff and index | diff, stage, unstage, restore, move, remove, commit |
| Branches | list, HEAD, validate, create, switch, rename, delete, upstream |
| Integration | merge, rebase, cherry-pick, revert, operation aborts |
| Stash and reset | list, push, apply, pop, drop, five reset modes |
| Remotes | list URLs/refspecs, add, remove, change URL |
| Network | clone, fetch, pull, push, progress, pruning, shallow operations |
| Tags | list, lightweight/annotated/signed create, delete |
| Worktrees | list, add, lock, unlock, remove, prune |
| Submodules | list, add, init/update, sync, deinitialize |
| Configuration | get all values, replace, append, unset; local/worktree/global/system scopes |
| Maintenance | dry-run-first clean and raw command access |
Authentication
GitPorcelain does not collect or persist passwords or tokens. By default, terminal prompts are disabled, while Git's configured credential helpers and SSH agents continue to work.
For a UI application, provide an AskPass executable:
GitClient git = new(new GitClientOptions
{
PromptMode = GitPromptMode.AskPass,
AskPassExecutablePath = askPassPath,
SshAskPassExecutablePath = sshAskPassPath,
});
Console applications that deliberately want interactive Git prompts can use GitPromptMode.Inherit.
Progress and cancellation
using CancellationTokenSource cancellation = new(TimeSpan.FromMinutes(5));
Progress<GitProgress> progress = new(update =>
Console.WriteLine($"{update.Phase}: {update.Percentage}%"));
GitRepository clone = await git.CloneAsync(
"https://github.com/example/project.git",
@"C:\source\project",
progress: progress,
cancellationToken: cancellation.Token);
Clone, fetch, pull, push, and submodule transfers report parsed stderr progress while retaining Git's complete stderr for diagnostics.
Errors
Failed Git commands throw GitCommandException. Its Result contains the exit code, argument vector, stdout, stderr, and duration. FailureKind classifies common authentication, authorization, conflict, dirty-tree, invalid-reference, lock, network, and repository errors.
Process startup, missing Git, timeout, parsing, repository discovery, and bare-repository failures have dedicated exception types.
Paths and output fidelity
Status and changed paths are read from NUL-delimited output. GitPath.Bytes preserves Git's original bytes, while GitPath.Value provides a replacement-safe UTF-8 view. This avoids parsing filenames through quoting, whitespace, tabs, or line breaks.
Raw commands
Typed APIs intentionally do not hide Git. Unmodeled features remain accessible without invoking a shell:
GitCommandResult result = await repository.RunAsync(
["rev-list", "--count", "HEAD"]);
result.ThrowIfFailed();
Building
dotnet build GitPorcelain.slnx -c Release
dotnet test GitPorcelain.slnx -c Release --no-build
dotnet pack src/GitPorcelain/GitPorcelain.csproj -c Release --no-build
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 104 | 8/26/2026 |
See CHANGELOG.md in the package or repository.