Skip to content

Options reference

Two families of option, applied at different moments.

  • RepoOpt configures the repository object, and is passed to NewRepo / NewThreadSafeRepo.
  • CloneOption configures a single clone, and is passed to Clone, OpenInMemory and Open.

RepoOpt: constructor options

type RepoOpt func(*Repo) error

One is exported.

WithConfig

func WithConfig(cfg *config.Config) RepoOpt

Supplies a go-git *config.Config (from github.com/go-git/go-git/v5/config).

It applies only to OpenInMemory, where it is installed on the in-memory storage backend before the clone. Clone, OpenLocal and InitLocal never read it, because those backends take their configuration from the .git directory on disk.

Passing WithConfig and then calling Clone is silently a no-op. To configure an on-disk repository, reach through to go-git after opening it:

err := r.WithRepo(func(gr *git.Repository) error {
    return gr.SetConfig(cfg)
})

CloneOption: per-clone options

type CloneOption func(*git.CloneOptions)
Option Sets Default when the option is absent
WithShallowClone(depth int) CloneOptions.Depth 0, meaning full history
WithSingleBranch(branch string) CloneOptions.SingleBranch, and ReferenceName when branch is non-empty all branches, remote HEAD checked out
WithNoTags() CloneOptions.Tags = git.NoTags go-git's clone default, AllTags
WithRecurseSubmodules() CloneOptions.RecurseSubmodules = git.DefaultSubmoduleRecursionDepth submodules are not initialised

They compose, and are applied in the order given:

_, _, err := r.OpenInMemory(ctx, url, "main",
    repo.WithShallowClone(1),
    repo.WithSingleBranch("main"),
    repo.WithNoTags(),
)

Which methods honour clone options

Method Clone options
Clone(ctx, uri, targetPath, opts...) Applied
OpenInMemory(ctx, location, branch, opts...) Applied
Open(ctx, repo.InMemoryRepo, location, branch, opts...) Applied, forwarded to OpenInMemory
Open(ctx, repo.LocalRepo, location, branch, opts...) Ignored. The local path calls OpenLocal(ctx, location), which takes neither options nor a branch.
OpenLocal, InitLocal Not accepted

That last row is the trap worth knowing. Open has a uniform signature across both backends, so a program that selects its backend from configuration compiles either way. Switching RepoType from inmemory to local then silently drops both the clone options and the branch argument, and nothing warns.

WithShallowClone

depth is passed straight through as go-git's Depth. WithShallowClone(0) is equivalent to not calling it at all.

A shallow clone truncates history, which is what makes it cheap and what stops later operations that need ancestry (a merge base, a full git log) seeing past the cut.

It matters most for in-memory repositories, where everything fetched stays resident in RAM.

WithSingleBranch

Sets SingleBranch: true. With a non-empty branch it also sets ReferenceName to refs/heads/<branch>, so that branch is the one fetched and checked out.

With branch empty it limits the fetch to a single branch but leaves the choice to go-git, which resolves the remote's HEAD.

WithNoTags

Sets Tags: git.NoTags.

Worth knowing what you are turning off. go-git's clone default is AllTags: every tag in the remote, whether or not it is reachable from the branch you asked for. On a repository with a long release history that is a meaningful amount of extra transfer, and for an in-memory clone all of it stays resident.

WithRecurseSubmodules

Sets RecurseSubmodules to go-git's DefaultSubmoduleRecursionDepth, which is 10 levels. The depth is fixed: no exported option sets another value. CloneOption is a func(*git.CloneOptions), so write your own if you need a different one:

depth3 := repo.CloneOption(func(o *git.CloneOptions) {
    o.RecurseSubmodules = 3
})

Nothing else in this module touches submodules. There is no update, sync or status operation for them.

Where the repository is bound

Clone, Open, OpenLocal, OpenInMemory and InitLocal all bind the resulting *git.Repository and *git.Worktree to the receiver, so subsequent calls need no handle. They also return the raw pair for setup-time convenience.

Calling one of them a second time replaces the binding. There is no Close: an in-memory repository is released when the last reference to it is dropped, and an on-disk one holds no long-lived handle to release.