or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

config.mdindex.mdobjects.mdplumbing.mdreferences.mdremote-operations.mdrepository-operations.mdstorage.mdtransport.mdworktree-operations.md
tile.json

storage.mddocs/

Storage

This document covers storage backends and interfaces in go-git for persisting Git objects and references.

Overview

go-git provides abstraction over Git object and reference storage through the Storer interface. This allows different storage implementations:

  • Filesystem storage - Standard .git directory structure
  • Memory storage - Ephemeral in-memory storage
  • Custom storage - Implement your own backend (database, cloud, etc.)

Storer Interface

type Storer interface {
    storer.EncodedObjectStorer
    storer.ReferenceStorer
}

The main storage interface combines object storage and reference storage.

Storage Interfaces

EncodedObjectStorer

type EncodedObjectStorer interface {
    NewEncodedObject() plumbing.EncodedObject
    SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error)
    EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
    IterEncodedObjects(plumbing.ObjectType) (EncodedObjectIter, error)
    HasEncodedObject(plumbing.Hash) error
    EncodedObjectSize(plumbing.Hash) (int64, error)
    AddAlternate(string) error
}

Stores Git objects (commits, trees, blobs, tags).

ReferenceStorer

type ReferenceStorer interface {
    SetReference(*plumbing.Reference) error
    CheckAndSetReference(*plumbing.Reference, *plumbing.Reference) error
    Reference(plumbing.ReferenceName) (*plumbing.Reference, error)
    IterReferences() (ReferenceIter, error)
    RemoveReference(plumbing.ReferenceName) error
    CountLooseRefs() (int, error)
    PackRefs() error
}

Stores Git references (branches, tags, HEAD).

Additional Interfaces

type ShallowStorer interface {
    SetShallow([]plumbing.Hash) error
    Shallow() ([]plumbing.Hash, error)
}

type IndexStorer interface {
    SetIndex(*index.Index) error
    Index() (*index.Index, error)
}

type ModuleStorer interface {
    Module(string) (Storer, error)
}

Filesystem Storage

Standard Git storage using filesystem.

import "github.com/go-git/go-git/v5/storage/filesystem"

type Storage struct {
    ObjectStorage    ObjectStorage
    ReferenceStorage ReferenceStorage
    IndexStorage     IndexStorage
    ShallowStorage   ShallowStorage
    ConfigStorage    ConfigStorage
    ModuleStorage    ModuleStorage
}

func NewStorage(fs billy.Filesystem, cache cache.Object) *Storage
func NewStorageWithOptions(fs billy.Filesystem, cache cache.Object, ops Options) *Storage

Example:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/storage/filesystem"
    "github.com/go-git/go-billy/v5/osfs"
)

func main() {
    // Create filesystem storage
    fs := osfs.New("/tmp/repo/.git")
    storage := filesystem.NewStorage(fs, nil)

    // Use with repository
    r, err := git.Open(storage, nil)
    if err != nil {
        panic(err)
    }

    _ = r
}

Filesystem Options

type Options struct {
    ExclusiveAccess      bool
    KeepDescriptors      bool
    MaxOpenDescriptors   int
    LargeObjectThreshold int64
    AlternatesFS         billy.Filesystem
}

Example with Options:

package main

import (
    "github.com/go-git/go-git/v5/storage/filesystem"
    "github.com/go-git/go-billy/v5/osfs"
)

func main() {
    fs := osfs.New("/tmp/repo/.git")

    storage := filesystem.NewStorageWithOptions(fs, nil, filesystem.Options{
        ExclusiveAccess:      false,
        KeepDescriptors:      true,
        MaxOpenDescriptors:   100,
        LargeObjectThreshold: 5 * 1024 * 1024, // 5MB
    })

    _ = storage
}

Memory Storage

In-memory storage for testing or temporary repositories.

import "github.com/go-git/go-git/v5/storage/memory"

type Storage struct {
    ConfigStorage    ConfigStorage
    ObjectStorage    ObjectStorage
    ShallowStorage   ShallowStorage
    IndexStorage     IndexStorage
    ReferenceStorage ReferenceStorage
    ModuleStorage    ModuleStorage
}

func NewStorage() *Storage

Example:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/storage/memory"
    "github.com/go-git/go-billy/v5/memfs"
)

func main() {
    // Create in-memory storage
    storage := memory.NewStorage()
    fs := memfs.New()

    // Clone to memory
    r, err := git.Clone(storage, fs, &git.CloneOptions{
        URL: "https://github.com/user/repo",
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Transactional Storage

Provides transaction support for storage operations.

import "github.com/go-git/go-git/v5/storage/transactional"

type ObjectStorage struct {
    // contains filtered or unexported fields
}

func NewObjectStorage(s storer.EncodedObjectStorer) *ObjectStorage

type Storage struct {
    // contains filtered or unexported fields
}

func NewStorage(s storage.Storer) *Storage

Example:

package main

import (
    "github.com/go-git/go-git/v5/storage/memory"
    "github.com/go-git/go-git/v5/storage/transactional"
)

func main() {
    base := memory.NewStorage()
    storage := transactional.NewStorage(base)

    // Use transactional storage
    _ = storage
}

Object Caching

Improve performance with object caching.

import "github.com/go-git/go-git/v5/plumbing/cache"

type Object interface {
    Put(plumbing.EncodedObject)
    Get(plumbing.Hash) plumbing.EncodedObject
    Clear()
}

func NewObjectLRU(size int) Object
func NewObjectLRUDefault() Object

Example:

package main

import (
    "github.com/go-git/go-git/v5/storage/filesystem"
    "github.com/go-git/go-git/v5/plumbing/cache"
    "github.com/go-git/go-billy/v5/osfs"
)

func main() {
    fs := osfs.New("/tmp/repo/.git")

    // Create cache (256MB)
    cache := cache.NewObjectLRU(256 * 1024 * 1024)

    // Create storage with cache
    storage := filesystem.NewStorage(fs, cache)

    _ = storage
}

Best Practices

1. Use Caching for Large Repositories

package main

import (
    "github.com/go-git/go-git/v5/storage/filesystem"
    "github.com/go-git/go-git/v5/plumbing/cache"
    "github.com/go-git/go-billy/v5/osfs"
)

func main() {
    fs := osfs.New("/large/repo/.git")
    cache := cache.NewObjectLRU(512 * 1024 * 1024) // 512MB cache
    storage := filesystem.NewStorage(fs, cache)
    _ = storage
}

2. Use Memory Storage for Testing

package main

import (
    "testing"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/storage/memory"
    "github.com/go-git/go-billy/v5/memfs"
)

func TestGitOperations(t *testing.T) {
    storage := memory.NewStorage()
    fs := memfs.New()

    r, err := git.Init(storage, fs)
    if err != nil {
        t.Fatal(err)
    }

    // Test operations
    _ = r
}

3. Configure Large Object Threshold

package main

import (
    "github.com/go-git/go-git/v5/storage/filesystem"
    "github.com/go-git/go-billy/v5/osfs"
)

func main() {
    fs := osfs.New("/tmp/repo/.git")

    storage := filesystem.NewStorageWithOptions(fs, nil, filesystem.Options{
        LargeObjectThreshold: 10 * 1024 * 1024, // 10MB
    })

    _ = storage
}

See Also

  • Repository Operations - Using storage with repositories
  • Plumbing - Low-level storage operations
  • Objects - Working with stored objects