Getting Started¶
The module is a .NET library that runs within a GenHTTP web server. This page creates a small console application hosting such a server. If you would like to add a repository to an existing ASP.NET Core application instead, see ASP.NET Core.
Installation¶
You need the .NET SDK (10 or newer). Create a console application and add the module along with a GenHTTP engine, which runs the server:
dotnet new console -n GitDemo
cd GitDemo
dotnet add package GenHTTP.Modules.Git
dotnet add package GenHTTP.Engine.Internal
dotnet add package GenHTTP.Modules.Practices
The module targets .NET 10 and .NET 11 and works with every GenHTTP engine (internal, Kestrel and ioxide). The
Practices package adds recommended defaults such as compression to the server.
Serving a repository¶
The quickest way to see the server in action is the InMemoryGitRepository, which behaves like a regular bare
repository but keeps everything in memory:
using GenHTTP.Engine.Internal;
using GenHTTP.Modules.Git;
using GenHTTP.Modules.Practices;
var repository = new InMemoryGitRepository();
var files = GitTree.Create()
.Add("README.md", "# Hello World\n")
.Add("src/Program.cs", "Console.WriteLine(\"Hello World\");\n")
.Build();
await repository.CommitAsync("main", files, "Initial commit");
var git = GitServer.Create()
.Repository(repository);
await Host.Create()
.Handler(git)
.Defaults()
.RunAsync();
Run the project with dotnet run and use git as you would with any other server:
git clone http://localhost:8080/ hello
cd hello
echo "More content" >> README.md
git commit -am "Extend the readme"
git push
The handler only responds to the endpoints used by git (info/refs, git-upload-pack and git-receive-pack) and
returns nothing for other requests, so it can be combined with other content:
var app = Layout.Create()
.Add("repo", GitServer.Create().Repository(repository))
.Add("api", api);
// git clone http://localhost:8080/repo
Serving your own data¶
The in-memory repository is useful for tests and prototypes. To serve your own data, implement one of two interfaces:
| Interface | Purpose |
|---|---|
IGitRepository |
Clients can clone and fetch the repository. |
IWritableGitRepository |
Clients can additionally push to the repository. |
public sealed class DocumentRepository : IGitRepository
{
public ValueTask<GitReferences> GetReferencesAsync()
{
// which branches and tags exist, and which commit they point to
}
public ValueTask<GitCommit?> GetCommitAsync(GitObjectId id)
{
// the commit with the given id, or null if unknown
}
public ValueTask<GitTree> GetTreeAsync(GitCommit commit)
{
// the files of the given commit
}
}
Before implementing the interfaces, read How It Works: it explains the one rule a virtual repository must follow so that clients do not see their history rewritten.
Trying the playground¶
The repository contains a Playground project that serves an in-memory repository: