Options reference¶
Two families of option, applied at different moments.
RepoOptconfigures the repository object, and is passed toNewRepo/NewThreadSafeRepo.CloneOptionconfigures a single clone, and is passed toClone,OpenInMemoryandOpen.
RepoOpt: constructor options¶
One is exported.
WithConfig¶
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:
CloneOption: per-clone options¶
type CloneOptions struct {
git.CloneOptions
SparseCheckoutDirectories []string
}
type CloneOption func(*CloneOptions)
CloneOptions embeds go-git's struct, so every go-git clone field is reachable through
it by promotion, and carries beside it what the module does after the clone.
| 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 |
WithSparseCheckout(dirs ...string) |
CloneOptions.NoCheckout = true and SparseCheckoutDirectories, then a sparse checkout after the clone |
the whole tree is materialised |
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. Write your own if you need a
different one; see writing a clone option by hand.
Nothing else in this module touches submodules. There is no update, sync or status operation for them.
WithSparseCheckout¶
Materialises only the paths under the given directory prefixes. The clone itself runs
with NoCheckout, and the module then checks out the branch (the branch argument to
OpenInMemory, or the clone's HEAD for Clone and an empty branch) limited to those
prefixes, through go-git's CheckoutOptions.SparseCheckoutDirectories.
_, _, err := r.OpenInMemory(ctx, url, "main",
repo.WithSingleBranch("main"),
repo.WithNoTags(),
repo.WithShallowClone(1),
repo.WithSparseCheckout("data/releases/"),
)
What it saves is the working-tree copy, not the objects. Every object the clone
fetches is held either way, so this composes with, rather than replaces, WithShallowClone
and WithSingleBranch. Measured on 300 incompressible 20 KiB files with go-git v5.19.2:
12.6 MiB live heap after a full in-memory open, 5.4 MiB after a sparse one.
Matching is by string prefix, because that is what go-git does: data/releases also
keeps data/releases-old/. End a prefix with / to ask for exactly that directory. A
leading / is stripped, since it would match nothing.
Two mistakes are refused rather than applied:
- No directories,
""or"."returnErrNoSparseDirectories. Each would be a full checkout spending what you asked to save. - A set that matches no path in the tree returns
ErrNoSparseMatch. Without it the working tree is empty and the first symptom iscannot create empty commitfrom a later commit, which reads as "nothing to do".
Commits after a sparse checkout keep the full tree: the paths outside the sparse set stay
in the index flagged skip-worktree, so AddAll does not stage them as deletions.
The working tree stays sparse for the life of the handle. See what this module does not do.
Writing a clone option by hand¶
CloneOption is a func(*repo.CloneOptions), and the go-git fields are promoted through
the embedded struct, so an option for a field the module does not name is a literal:
Releases up to v0.4.0 took *git.CloneOptions here. The body of such an option is
unchanged; only the parameter type moves, and the compiler names every site.
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.
Related¶
- Work in memory: where these options matter most
- Settings reference: the options that configure authentication
- Errors reference