Skip to content
gitmeta-csharp

c# · .net 8 · sync + async

Per-file git metadata for .NET.

A C#/.NET port of gitmeta — one batch scan, then constant-time per-path lookups for last commit, author, churn, and tracked/ignored — with full synchronous and asynchronous (CancellationToken) APIs.

MIT licensed · zero third-party dependencies · .NET 8.0+

Program.cs
using GitMeta;

var cache = GitMetaCache.Create("/path/to/repo");
if (cache is null) return; // not a git working tree

if (cache.Lookup("Program.cs") is { } info)
    Console.WriteLine($"{info.LastCommitTime:yyyy-MM-dd} " +
                      $"{info.LastCommitAuthor} — {info.CommitCount} commits");

what you get

Git history, one scan at a time.

A single batch scan up front, then every per-path question answers in constant time — the same design as the Go original, ported to idiomatic C#.

One scan, then O(1)

The same batch design as the Go original: one git ls-files + git log pass up front, then constant-time per-path lookups instead of a git log call per file.

FileGitInfo

Last-commit time, author and subject, first-seen time, and commit count (a churn proxy) — everything about a path in one readonly record struct.

Sync + async

Every I/O entry point comes in both flavors — Create / CreateAsync and Get / GetAsync — with each async variant taking a CancellationToken.

GitMetaPool

Keeps one cache per repo, re-validated on HEAD change so an unchanging tree isn't re-scanned. Safe for concurrent use — ideal for a long-running server or watcher.

Zero dependencies

Shells out to the system git binary — no third-party imports. A null return is the clean "no git data" signal; GitCommandException fires only on a broken git.

Modern C#

DateTimeOffset in UTC, nullable reference types, and a readonly record struct for results. Targets .NET 8.0+.

usage

Sync or async — same result.

Build a cache once, then read metadata per path. Use the synchronous form for scripts and one-shots; the async form when you have a CancellationToken to honor.

// Synchronous — scripts, one-shots
var cache = GitMetaCache.Create("/path/to/repo");
if (cache is null) return; // no git data

if (cache.Lookup("Program.cs") is { } info)
    Console.WriteLine(info.LastCommitAuthor);
// Asynchronous — honors a CancellationToken
var cache = await GitMetaCache.CreateAsync(path, ct);
if (cache is null) return;

var info = await cache.GetAsync(path, ct);
Console.WriteLine(info?.CommitCount);
  • GitMetaCache.Create
  • CreateAsync
  • Lookup
  • GetAsync
  • GitMetaPool.Get
  • IsTracked
  • IsIgnored

install

Add it to your project.

One package, no transitive dependencies. Requires .NET 8.0+ and the system git binary on PATH.

dotnet dotnet add package GitMeta
using using GitMeta;

The C#/.NET port of gitmeta. Source, issues, and the full API live on the GitHub repository.