Name
go-git — Public documentation for the project.
go-git exposes git repository facts — the current branch, the origin remote URL, and the repository owner — plus a forward-only check, all read through an injected Runner so callers are testable without invoking the real git binary. The functionality lives in the facts package.
- Source:
gomatic/go-git - API reference: pkg.go.dev/github.com/gomatic/go-git/facts
Install
go get github.com/gomatic/go-gitUsage
Everything is driven by a Runner, which runs a git subcommand and returns its stdout. In production, pass NewExecRunner() — the real-git implementation; in tests, pass a fake.
package main
import (
"fmt"
"log"
"github.com/gomatic/go-git/facts"
)
func main() {
r := facts.NewExecRunner()
branch, err := facts.Branch(r)
if err != nil {
log.Fatal(err)
}
fmt.Println("branch:", branch)
origin, err := facts.Origin(r)
if err != nil {
log.Fatal(err)
}
fmt.Println("origin:", origin)
owner, err := facts.OwnerOf(r)
if err != nil {
log.Fatal(err)
}
fmt.Println("owner:", owner)
}Functions
Branch(r Runner) (BranchName, error)— the current branch name (git symbolic-ref --short HEAD), orErrDetachedHeadwhen HEAD is detached.Origin(r Runner) (OriginURL, error)— theremote.origin.url, orErrNoOriginwhen it is not configured.OwnerOf(r Runner) (Owner, error)— the owning account/org, parsed from theupstreamremote and falling back toorigin; handles bothhttps://and scp-style (git@host:owner/repo) URLs. ReturnsErrNoOriginwhen neither remote yields an owner.EnsureForwardOnly(r Runner) error— verifies HEAD is on a branch tip rather than a detached commit (returnsErrDetachedHeadotherwise).
Errors
Both sentinels are gomatic/go-error constants, matched with errors.Is — never by string:
if _, err := facts.Branch(r); errors.Is(err, facts.ErrDetachedHead) {
// HEAD is detached
}ErrDetachedHead— HEAD is not on a branch tip.ErrNoOrigin— no origin remote configured.
Testing with a fake Runner
Because every function takes a Runner, tests never touch a real repository — supply canned output:
type fakeRunner struct {
out facts.CommandOutput
err error
}
func (f fakeRunner) Run(args ...facts.Arg) (facts.CommandOutput, error) {
return f.out, f.err
}
func TestBranch(t *testing.T) {
branch, err := facts.Branch(fakeRunner{out: "main\n"})
// branch == "main", err == nil
}Design
- Injected runner, no hidden globals. The git binary is reached only through the
Runnerinterface;ExecRunneris the sole real implementation, so every code path is reachable from a test with a fake. - Named domain types. Arguments and results use dedicated newtypes —
Arg,CommandOutput,BranchName,OriginURL,Owner— rather than bare strings. - Value receivers, immutable, private by default.
ExecRunneris an empty value type; only what callers need is exported. - Extracted from
skykernel/skym’sinternal/git— generalized and moved togomaticfor reuse.