Pure managed C# implementation for reading from Git repositories.
- Portable and simple
- No dependencies on native code.
- Reading from local Git repositories
- Resolve HEAD and other references to commit SHAs.
- Load all files from any commit's tree.
- Load files from a specific subdirectory within a commit's tree.
- Supports both loose objects and pack files.
- Reads indexed packs with 64-bit offsets without loading complete packs.
- Supports worktrees, bare repositories, linked worktrees, and alternate object stores.
- Incremental tree traversal with early file and subtree pruning.
- Cloning via Git Smart HTTP
- Efficient partial cloning of subdirectories.
- Configurable API for caching git objects to make cloning more efficient.
NuGet: https://www.nuget.org/packages/GitCore/
dotnet add package GitCore
vargitDir=Path.Combine(repoRootDir,".git");// Load all files from the current HEAD commitvarfilesAtHead=GitCore.LoadFromLocalFiles.LoadTreeContentsFromHead(gitDir);// Or resolve HEAD and load from a specific commitvarcommitSha=GitCore.LoadFromLocalFiles.ResolveHead(gitDir);varfilesAtCommit=GitCore.LoadFromLocalFiles.LoadTreeContentsFromCommit(gitDir,commitSha);// Load only files under a specific subdirectory (paths relative to subdirectory)varsubdirFiles=GitCore.LoadFromLocalFiles.LoadSubdirectoryContentsFromHead(gitDir,["implement","Pine.Core"]);// Or from a specific commitvarsubdirFilesAtCommit=GitCore.LoadFromLocalFiles.LoadSubdirectoryContentsFromCommit(gitDir,commitSha,["implement","Pine.Core"]);// Resolve any reference (branch, tag, etc.)varbranchSha=GitCore.LoadFromLocalFiles.ResolveReference(gitDir,"refs/heads/main");// Load the full in-memory object storevarrepository=GitCore.LoadFromLocalFiles.LoadRepository(gitDir);LocalGitRepository owns pack handles and bounded caches, so keep it open while resolving related
objects and dispose it afterward. Selection runs before a subtree or blob is loaded.
usingvarrepository=GitCore.LocalGitRepository.Open(repoRootDir,newGitCore.LocalRepositoryOptions{MaximumCachedObjectBytes=128*1024*1024,MaximumMaterializedObjectSize=64*1024*1024});varcommitId=repository.ResolveHead()??thrownewInvalidOperationException("HEAD cannot be resolved.");awaitforeach(varfileinrepository.EnumerateTreeAsync(commitId,newGitCore.TreeTraversalOptions{SelectFile=
file =>file.Nameis".order"||file.Name.EndsWith(".md",StringComparison.OrdinalIgnoreCase)?GitCore.TreeFileSelection.Include:GitCore.TreeFileSelection.Skip,SelectSubtree=
subtree =>subtree.Path.Contains(".attachments",StringComparer.OrdinalIgnoreCase)?GitCore.TreeSubtreeSelection.Skip:GitCore.TreeSubtreeSelection.Descend})){awaitusingvardestination=CreateDestination(file.Path);awaitfile.CopyContentToAsync(destination);}LookupObject returns Found, Missing, or MissingPromised together with a typed,
context-rich error. GitCore never fetches a missing object implicitly. Applications can opt into
FetchMissing or Custom and supply a MissingObjectProvider, retaining control of networking,
credentials, cancellation, and persistence. Storage and limit failures use typed exceptions such
as GitObjectNotFoundException, InvalidPackIndexException, InvalidPackObjectException,
GitObjectSizeLimitException, and GitResourceLimitException; each exposes a GitErrorContext.
varsubdirectoryContents=awaitGitCore.LoadFromUrl.LoadSubdirectoryContentsFromGitUrlAsync(gitUrl:"https://github.com/pine-vm/pine.git",commitSha:"c837c8199f38aab839c40019a50055e16d100c74",subdirectoryPath:["guide"]);