Documentation
¶
Overview ¶
Package git provides branch management operations for git repositories. This file contains all branch-related operations including creation, checkout, deletion, and remote branch handling.
Package git provides high-level Git operations through a clean facade. This file contains diff-related operations for comparing revisions.
Package git provides a high-level, idiomatic Go wrapper for git operations.
This package offers a clean facade over go-git, exposing task-oriented operations for common git workflows while enforcing the use of the project's native filesystem abstraction. All operations work with both on-disk and in-memory repositories.
Design Principles ¶
The package follows these core principles:
- Minimal surface area - easy to learn and extend
- Testability by construction - in-memory FS, controlled side effects
- Security & performance - context timeouts, auth integration, object caching
- Go idioms - accepts interfaces, returns concrete types
Basic Usage ¶
Initialize or open a repository:
import (
"context"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
// Create filesystem (can be OS-backed or in-memory)
fs := billyfs.NewOSFS("/path/to/repo")
// Open existing repository
repo, err := git.Open(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
// Or initialize new repository
repo, err := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
Working with Branches ¶
Create and switch branches:
// Create new branch from current HEAD err = repo.CreateBranch(ctx, "feature/new", "HEAD", false, false) // Checkout the branch err = repo.CheckoutBranch(ctx, "feature/new", false, false) // Get current branch branch, err := repo.CurrentBranch(ctx)
Making Commits ¶
Stage files and create commits:
// Stage files
err = repo.Add(ctx, "file1.go", "file2.go")
// Or stage everything
err = repo.Add(ctx, ".")
// Create commit
sha, err := repo.Commit(ctx, "feat: add new feature", git.Signature{
Name: "John Doe",
Email: "john@example.com",
}, git.CommitOpts{})
Synchronization ¶
Fetch, pull, and push changes:
// Fetch from remote err = repo.Fetch(ctx, "origin", true, 0) // Pull with fast-forward only err = repo.PullFFOnly(ctx, "origin") // Push current branch err = repo.Push(ctx, "origin", false)
Working with Tags ¶
Create and manage tags:
// Create annotated tag
err = repo.CreateTag(ctx, "v1.0.0", "HEAD", "Release v1.0.0", true)
// List tags matching pattern
tags, err := repo.Tags(ctx, git.TagPatternFilter("v*"))
// Delete tag
err = repo.DeleteTag(ctx, "v1.0.0")
History and Diffs ¶
Query commit history and compute diffs:
// Get commit history with filters
iter, err := repo.Log(ctx, git.LogFilter{
Author: "John",
MaxCount: 10,
})
defer iter.Close()
// Iterate through commits
err = iter.ForEach(func(c *object.Commit) error {
fmt.Printf("%s: %s\n", c.Hash, c.Message)
return nil
})
// Compute diff between revisions
diff, err := repo.Diff(ctx, "HEAD~1", "HEAD", git.ExtensionFilter(".go"))
fmt.Println(diff.Text)
Authentication ¶
The package supports authentication through the AuthProvider interface. Implementations for HTTPS (token/password) and SSH (key file, agent) are available in the internal/auth package. Users can implement their own AuthProvider for custom authentication needs:
type MyAuthProvider struct {
token string
}
func (a *MyAuthProvider) Method(ctx context.Context, url string) (transport.AuthMethod, error) {
// Return appropriate auth method based on URL
return &http.BasicAuth{Username: "token", Password: a.token}, nil
}
// Use in options
opts := &git.Options{
FS: fs,
Auth: &MyAuthProvider{token: "github_pat_..."},
}
In-Memory Operations ¶
All operations can run entirely in memory for testing:
// Create in-memory filesystem
memFS := billyfs.NewInMemoryFS()
// Initialize in-memory repository
repo, err := git.Init(ctx, &git.Options{
FS: memFS,
Workdir: "/",
})
// All operations work the same
err = memFS.WriteFile("test.txt", []byte("content"), 0644)
err = repo.Add(ctx, "test.txt")
sha, err := repo.Commit(ctx, "test commit", sig, git.CommitOpts{})
Error Handling ¶
The package provides sentinel errors for common conditions:
err := repo.Push(ctx, "origin", false)
if errors.Is(err, git.ErrNotFastForward) {
// Handle non-fast-forward push
}
if errors.Is(err, git.ErrAuthRequired) {
// Handle missing authentication
}
Context Support ¶
All operations accept a context for timeout and cancellation:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err = repo.Clone(ctx, "https://github.com/example/repo.git", opts)
if err != nil {
// Operation was cancelled or timed out
}
Thread Safety ¶
A Repo instance is NOT safe for concurrent writes. Read operations (Log, Diff, Refs, CurrentBranch, etc.) can be called concurrently. Write operations (Add, Commit, Push, etc.) must be serialized.
Performance Considerations ¶
The package includes several performance optimizations:
- LRU object cache (configurable via StorerCacheSize)
- Shallow clone/fetch support (via ShallowDepth option)
- Path filtering for diffs to reduce computation
- Efficient ref iteration without loading full objects
Limitations ¶
This package intentionally does not support:
- Interactive operations (rebase -i, add -i)
- Complex merge conflict resolution
- Submodule management (may be added later)
- Direct git CLI invocation
For advanced use cases not covered by this facade, the underlying go-git repository object can be accessed if needed (though this is discouraged for maintainability).
Package git provides sentinel errors for common git operations. All errors can be checked using errors.Is() for programmatic handling.
Package git provides a high-level Go wrapper for go-git operations. It exposes task-oriented operations for repository management while operating exclusively through the project's native filesystem abstraction.
Package git provides high-level Git operations through a clean facade. This file contains history-related operations including commit logging and iteration.
Package git provides high-level Git operations through a clean facade. This file contains reference-related operations for listing and resolving refs.
Package git provides a high-level Go wrapper for go-git operations. This file contains synchronization operations (fetch, pull, merge, push).
Package git provides a high-level Go wrapper for go-git operations. This file contains tag-related operations for repository management.
Package git provides a high-level Go wrapper for go-git operations. This file contains worktree operations (add, remove, unstage, commit).
Index ¶
- Constants
- Variables
- func WrapError(err error, msg string) error
- func WrapErrorf(err error, format string, args ...interface{}) error
- type AuthProvider
- type ChangeFilter
- func AddedFilter() ChangeFilter
- func AndFilter(filters ...ChangeFilter) ChangeFilter
- func ChangeExcludePathFilter(path string) ChangeFilter
- func ChangeExtensionFilter(ext string) ChangeFilter
- func ChangePathFilter(path string) ChangeFilter
- func CustomFilter(predicate func(*object.Change) bool) ChangeFilter
- func DeletedFilter() ChangeFilter
- func ExtensionFilter(extensions ...string) ChangeFilter
- func MaxSizeFilter(maxBytes int64) ChangeFilter
- func ModifiedFilter() ChangeFilter
- func NonBinaryFilter() ChangeFilter
- func NotFilter(filter ChangeFilter) ChangeFilter
- func OrFilter(filters ...ChangeFilter) ChangeFilter
- func PathFilter(pattern string) ChangeFilter
- func PathPrefixFilter(prefix string) ChangeFilter
- func RenamedFilter() ChangeFilter
- type CommitIter
- type CommitOpts
- type LogFilter
- type MergeStrategy
- type Options
- type PatchText
- type RefKind
- type Repo
- func (r *Repo) Add(ctx context.Context, paths ...string) error
- func (r *Repo) CheckoutBranch(ctx context.Context, name string, createIfMissing, force bool) error
- func (r *Repo) CheckoutRemoteBranch(ctx context.Context, remote, remoteBranch, localName string, track bool) error
- func (r *Repo) Commit(ctx context.Context, msg string, who Signature, opts CommitOpts) (string, error)
- func (r *Repo) CreateBranch(ctx context.Context, name, startRev string, trackRemote, force bool) error
- func (r *Repo) CreateTag(ctx context.Context, name, target, message string, annotated bool) error
- func (r *Repo) CurrentBranch(ctx context.Context) (string, error)
- func (r *Repo) DeleteBranch(ctx context.Context, name string) error
- func (r *Repo) DeleteTag(ctx context.Context, name string) error
- func (r *Repo) Diff(ctx context.Context, a, b string, filters ...ChangeFilter) (*PatchText, error)
- func (r *Repo) Fetch(ctx context.Context, remote string, prune bool, depth int) error
- func (r *Repo) FetchAndMerge(ctx context.Context, remote, fromRef string, strategy MergeStrategy) error
- func (r *Repo) Log(ctx context.Context, f LogFilter) (*CommitIter, error)
- func (r *Repo) PullFFOnly(ctx context.Context, remote string) error
- func (r *Repo) Push(ctx context.Context, remote string, force bool) error
- func (r *Repo) Refs(ctx context.Context, kind RefKind, pattern string) ([]string, error)
- func (r *Repo) Remove(ctx context.Context, paths ...string) error
- func (r *Repo) Resolve(ctx context.Context, rev string) (*ResolvedRef, error)
- func (r *Repo) Tags(ctx context.Context, filters ...TagFilter) ([]string, error)
- func (r *Repo) Unstage(ctx context.Context, paths ...string) error
- type ResolvedRef
- type Signature
- type TagFilter
Examples ¶
Constants ¶
const ( // DefaultStorerCacheSize is the default size for the LRU object cache. DefaultStorerCacheSize = 1000 // DefaultWorkdir is the default worktree directory name. DefaultWorkdir = "." // DefaultRemoteName is the default remote name used for operations. DefaultRemoteName = "origin" )
Variables ¶
var ErrAlreadyUpToDate = errors.New("already up to date")
ErrAlreadyUpToDate is returned when fetch, pull, or push operations result in no changes because the local and remote states are already synchronized.
var ErrAuthFailed = errors.New("authentication failed")
ErrAuthFailed is returned when authentication was attempted but failed (invalid credentials, expired tokens, etc.).
var ErrAuthRequired = errors.New("authentication required")
ErrAuthRequired is returned when an operation requires authentication but no credentials were provided or available.
var ErrBranchExists = errors.New("branch already exists")
ErrBranchExists is returned when attempting to create a branch that already exists and force creation was not requested.
var ErrBranchMissing = errors.New("branch does not exist")
ErrBranchMissing is returned when attempting to operate on a branch that does not exist.
var ErrEmptyCommit = errors.New("cannot create empty commit")
ErrEmptyCommit is returned when attempting to create a commit with no changes and AllowEmpty is false.
var ErrInvalidRef = errors.New("invalid reference")
ErrInvalidRef is returned when a reference name or revision specification is malformed or invalid according to git's reference naming rules.
var ErrMergeConflict = errors.New("merge conflict")
ErrMergeConflict is returned when a merge operation encounters conflicts that cannot be automatically resolved.
var ErrNotFastForward = errors.New("not a fast-forward")
ErrNotFastForward is returned when a push or pull operation cannot be performed as a fast-forward merge and requires manual conflict resolution.
var ErrResolveFailed = errors.New("cannot resolve revision")
ErrResolveFailed is returned when a revision specification cannot be resolved to a valid commit hash (e.g., branch/tag doesn't exist, invalid SHA).
var ErrTagExists = errors.New("tag already exists")
ErrTagExists is returned when attempting to create a tag that already exists and force creation was not requested.
var ErrTagMissing = errors.New("tag does not exist")
ErrTagMissing is returned when attempting to operate on a tag that does not exist.
Functions ¶
func WrapError ¶
WrapError wraps an error with additional context while preserving the ability to check against sentinel errors using errors.Is().
func WrapErrorf ¶
WrapErrorf wraps an error with formatted additional context while preserving the ability to check against sentinel errors using errors.Is().
Types ¶
type AuthProvider ¶
type AuthProvider interface {
// Method returns the appropriate transport.AuthMethod for the given remote URL.
// Returns nil if no authentication is needed/available for this URL.
// Returns an error if authentication cannot be resolved for the URL.
Method(remoteURL string) (transport.AuthMethod, error)
}
AuthProvider resolves authentication methods for git operations. Implementations should handle different URL schemes and credential sources.
type ChangeFilter ¶
ChangeFilter is a predicate function for filtering changes in diffs. It returns true if the change should be included in the diff output. Filters are applied progressively - if any filter returns false, the change is excluded.
func AddedFilter ¶
func AddedFilter() ChangeFilter
AddedFilter creates a filter that only includes newly added files.
func AndFilter ¶
func AndFilter(filters ...ChangeFilter) ChangeFilter
AndFilter combines multiple filters with AND logic - all must pass.
func ChangeExcludePathFilter ¶
func ChangeExcludePathFilter(path string) ChangeFilter
ChangeExcludePathFilter returns a filter that excludes changes affecting the specified path. This is useful for filtering out certain paths while keeping all others.
func ChangeExtensionFilter ¶
func ChangeExtensionFilter(ext string) ChangeFilter
ChangeExtensionFilter returns a filter that includes changes to files with the specified extension. The extension should include the dot (e.g., ".go", ".md").
func ChangePathFilter ¶
func ChangePathFilter(path string) ChangeFilter
ChangePathFilter returns a filter that includes changes affecting the specified path. The path can be a file or directory. For directories, all files within are matched.
func CustomFilter ¶
func CustomFilter(predicate func(*object.Change) bool) ChangeFilter
CustomFilter allows creating a filter with a custom predicate function. This is useful for one-off filtering logic.
func DeletedFilter ¶
func DeletedFilter() ChangeFilter
DeletedFilter creates a filter that only includes deleted files.
func ExtensionFilter ¶
func ExtensionFilter(extensions ...string) ChangeFilter
ExtensionFilter creates a filter that includes changes for files with the given extensions. Extensions should include the dot (e.g., ".go", ".js").
func MaxSizeFilter ¶
func MaxSizeFilter(maxBytes int64) ChangeFilter
MaxSizeFilter creates a filter that excludes files larger than the specified size in bytes. Note: This requires fetching the blob objects to check their size, which may impact performance.
func ModifiedFilter ¶
func ModifiedFilter() ChangeFilter
ModifiedFilter creates a filter that only includes modified files (not added or deleted).
func NonBinaryFilter ¶
func NonBinaryFilter() ChangeFilter
NonBinaryFilter creates a filter that excludes binary files. It uses file extension heuristics to identify binary files.
func NotFilter ¶
func NotFilter(filter ChangeFilter) ChangeFilter
NotFilter creates a filter that inverts the result of another filter.
func OrFilter ¶
func OrFilter(filters ...ChangeFilter) ChangeFilter
OrFilter combines multiple filters with OR logic - at least one must pass.
func PathFilter ¶
func PathFilter(pattern string) ChangeFilter
PathFilter creates a filter that includes changes matching the given path pattern. The pattern can include wildcards (* and ?) and is matched against both the old and new file names (to handle renames).
func PathPrefixFilter ¶
func PathPrefixFilter(prefix string) ChangeFilter
PathPrefixFilter creates a filter that includes changes with paths starting with the given prefix. This is useful for filtering by directory.
func RenamedFilter ¶
func RenamedFilter() ChangeFilter
RenamedFilter creates a filter that only includes renamed/moved files.
type CommitIter ¶
type CommitIter struct {
// contains filtered or unexported fields
}
CommitIter represents an iterator over commits returned by Log operations. It provides methods to iterate through commits efficiently without loading all commits into memory at once.
func (*CommitIter) Close ¶
func (ci *CommitIter) Close()
Close closes the iterator and releases any associated resources.
type CommitOpts ¶
type CommitOpts struct {
// AllowEmpty allows creating commits with no changes.
// By default, empty commits are not allowed.
AllowEmpty bool
// All adds all modified and untracked files to the index before committing.
// Equivalent to running 'git add .' before commit.
All bool
// Amend amends the tip of the current branch with this commit.
// This replaces the current commit rather than creating a new one.
Amend bool
}
CommitOpts configures commit creation behavior. These options control how commits are created and what files are included.
type LogFilter ¶
type LogFilter struct {
// Since limits the log to commits after the specified time.
// Only commits with timestamps after this time will be included.
Since *time.Time
// Until limits the log to commits before the specified time.
// Only commits with timestamps before this time will be included.
Until *time.Time
// Author filters commits by author name/email pattern.
// Supports glob patterns for partial matching.
Author string
// Path filters commits that modified the specified path(s).
// Only commits that touched these paths will be included.
Path []string
// MaxCount limits the number of commits returned.
// If 0, all matching commits are returned.
MaxCount int
}
LogFilter configures which commits to include in log operations. Use this to filter commits by time range, author, paths, or limit the result count.
type MergeStrategy ¶
type MergeStrategy int8
MergeStrategy represents the different types of merge strategies. Currently, only FastForwardOnly is supported by go-git.
const ( // FastForwardOnly represents a merge strategy that only allows fast-forward merges. // This will fail if a merge commit would be required. FastForwardOnly MergeStrategy = iota )
func (MergeStrategy) String ¶
func (s MergeStrategy) String() string
String returns a human-readable string representation of the MergeStrategy.
type Options ¶
type Options struct {
// FS is the REQUIRED native filesystem root (OS or in-memory).
// All repository state lives within this filesystem.
FS fs.Filesystem
// Workdir is the path within FS for the worktree root.
// Defaults to "." (current directory in FS).
Workdir string
// Bare indicates if this should be a bare repository (.git only, no worktree).
// Defaults to false (non-bare repository with worktree).
Bare bool
// StorerCacheSize sets the LRU objects cache entries.
// Higher values improve performance but use more memory.
// Defaults to DefaultStorerCacheSize.
StorerCacheSize int
// Auth is an optional provider that resolves per-URL AuthMethod.
// If nil, no authentication will be available.
Auth AuthProvider
// HTTPClient is an optional custom transport for network operations.
// If nil, a default client with reasonable timeouts is used.
HTTPClient *http.Client
// ShallowDepth sets the depth for shallow clone/fetch operations.
// If > 0, operations will be shallow with the specified depth.
// If 0, full clone/fetch operations are performed.
ShallowDepth int
}
Options configures repository discovery/creation and performance.
type PatchText ¶
type PatchText struct {
// Text contains the unified diff in string format.
Text string
// IsBinary indicates whether the diff contains binary files.
// When true, the diff text may be truncated or contain binary markers.
IsBinary bool
// FileCount indicates the number of files that have changes.
FileCount int
}
PatchText represents unified diff text between two revisions. It contains the formatted diff output that can be displayed to users or processed by other tools.
type RefKind ¶
type RefKind int
RefKind represents the type of git reference. This is used to classify references when listing or resolving them.
const ( // RefBranch indicates a local branch reference (refs/heads/*). RefBranch RefKind = iota // RefRemoteBranch indicates a remote branch reference (refs/remotes/*/*). RefRemoteBranch // RefTag indicates a tag reference (refs/tags/*). RefTag // RefRemote indicates a generic remote reference. RefRemote // RefCommit indicates a commit hash (not a symbolic reference). RefCommit // RefOther indicates any other type of reference. RefOther )
type Repo ¶
type Repo struct {
// contains filtered or unexported fields
}
Repo represents a git repository and provides high-level operations. It wraps a go-git Repository and Worktree, operating exclusively through the project's native filesystem abstraction.
func Clone ¶
Clone creates a new repository by cloning from a remote URL. It supports both bare and non-bare repositories, shallow cloning, and authentication.
The remoteURL should be a valid git URL (https://, ssh://, or file:// for local repos). For shallow clones, set ShallowDepth > 0 to limit the clone depth. Authentication is handled via the AuthProvider if credentials are required.
Context timeout/cancellation is honored during the clone operation.
Example ¶
ExampleClone demonstrates how to clone a remote repository.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
fs := billyfs.NewOSFS("/tmp/cloned-repo")
// Clone repository (authentication can be provided via Auth field)
repo, err := git.Clone(context.Background(), "https://github.com/example/repo.git", &git.Options{
FS: fs,
Workdir: ".",
ShallowDepth: 1, // Shallow clone for faster operation
// Auth: myAuthProvider, // Provide AuthProvider implementation
})
if err != nil {
log.Fatal(err)
}
// List files in the cloned repo
files, err := fs.ReadDir(".")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Cloned %d files\n", len(files))
_ = repo // Use repo for further operations
}
Output:
func Init ¶
Init creates a new git repository at the specified location. It initializes both bare and non-bare repositories with proper storage and worktree setup.
Example ¶
ExampleInit demonstrates how to initialize a new git repository.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Create filesystem
fs := billyfs.NewInMemoryFS()
// Initialize repository
repo, err := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
if err != nil {
log.Fatal(err)
}
// Create a file
err = fs.WriteFile("README.md", []byte("# My Project\n"), 0o644)
if err != nil {
log.Fatal(err)
}
// Stage and commit
err = repo.Add(context.Background(), "README.md")
if err != nil {
log.Fatal(err)
}
sha, err := repo.Commit(context.Background(), "Initial commit", git.Signature{
Name: "Example User",
Email: "user@example.com",
}, git.CommitOpts{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created commit: %s\n", sha[:7])
}
Output:
func Open ¶
Open discovers and opens an existing git repository. The repository must already exist at the specified workdir within the filesystem. For non-bare repositories, both .git directory and worktree must be present. For bare repositories, only the .git directory structure is expected.
Context timeout/cancellation is honored during repository validation.
Example ¶
ExampleOpen demonstrates how to open an existing repository.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Open repository from filesystem
fs := billyfs.NewOSFS("/path/to/repo")
repo, err := git.Open(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
if err != nil {
log.Fatal(err)
}
// Get current branch
branch, err := repo.CurrentBranch(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("Current branch: %s\n", branch)
}
Output:
func (*Repo) Add ¶
Add stages files in the worktree for the next commit. It supports glob patterns and handles missing files appropriately. Files that don't exist are silently ignored (matching git add behavior).
Context timeout/cancellation is honored during the operation.
func (*Repo) CheckoutBranch ¶
CheckoutBranch switches to the specified branch. If createIfMissing is true, it creates the branch if it doesn't exist. If force is true, it discards any uncommitted changes in the working tree.
Context timeout/cancellation is honored during the operation.
func (*Repo) CheckoutRemoteBranch ¶
func (r *Repo) CheckoutRemoteBranch(ctx context.Context, remote, remoteBranch, localName string, track bool) error
CheckoutRemoteBranch creates a local branch from a remote branch and optionally sets up tracking. If localName is empty, it uses the same name as the remote branch.
Context timeout/cancellation is honored during the operation.
func (*Repo) Commit ¶
func (r *Repo) Commit(ctx context.Context, msg string, who Signature, opts CommitOpts) (string, error)
Commit creates a new commit with the specified message and author/committer. It returns the SHA of the new commit. The CommitOpts can be used to control commit behavior such as allowing empty commits.
Context timeout/cancellation is honored during the operation.
Example ¶
ExampleRepo_Commit demonstrates staging files and creating commits.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Setup repository
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
ctx := context.Background()
// Create some files
_ = fs.WriteFile("main.go", []byte("package main\n"), 0o644)
_ = fs.WriteFile("README.md", []byte("# Project\n"), 0o644)
// Stage specific files
err := repo.Add(ctx, "main.go", "README.md")
if err != nil {
log.Fatal(err)
}
// Create commit with signature
sha, err := repo.Commit(ctx, "feat: initial implementation", git.Signature{
Name: "Jane Doe",
Email: "jane@example.com",
}, git.CommitOpts{
// Options like AllowEmpty can be set here
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Commit created: %s\n", sha[:7])
}
Output:
func (*Repo) CreateBranch ¶
func (r *Repo) CreateBranch(ctx context.Context, name, startRev string, trackRemote, force bool) error
CreateBranch creates a new branch from the specified revision. It supports creating branches from any valid revision (commit hash, branch name, tag, etc.). If trackRemote is true, it sets up remote tracking configuration. If force is true, it overwrites any existing branch with the same name.
Context timeout/cancellation is honored during the operation.
Example ¶
ExampleRepo_CreateBranch demonstrates branch creation and checkout.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Assume repo is already initialized
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
ctx := context.Background()
// Create an initial commit so HEAD resolves
_ = fs.WriteFile("init.txt", []byte("init"), 0o644)
_ = repo.Add(ctx, "init.txt")
_, _ = repo.Commit(ctx, "Initial", git.Signature{Name: "Example", Email: "ex@example.com"}, git.CommitOpts{})
// Create a new branch from HEAD
err := repo.CreateBranch(ctx, "feature/new-feature", "HEAD", false, false)
if err != nil {
log.Fatal(err)
}
// Checkout the new branch
err = repo.CheckoutBranch(ctx, "feature/new-feature", false, false)
if err != nil {
log.Fatal(err)
}
// Verify current branch
branch, err := repo.CurrentBranch(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Switched to branch: %s\n", branch)
}
Output: Switched to branch: feature/new-feature
func (*Repo) CreateTag ¶
CreateTag creates a new tag at the specified target revision. If message is provided and annotated is true, an annotated tag is created. If message is empty or annotated is false, a lightweight tag is created. The target can be any valid revision specifier (commit hash, branch name, etc.).
Context timeout/cancellation is honored during the operation.
func (*Repo) CurrentBranch ¶
CurrentBranch returns the name of the currently checked out branch. It returns an error if HEAD is in a detached state.
Context timeout/cancellation is honored during the operation.
func (*Repo) DeleteBranch ¶
DeleteBranch deletes the specified local branch. It prevents deletion of the currently checked out branch.
Context timeout/cancellation is honored during the operation.
func (*Repo) DeleteTag ¶
DeleteTag deletes the specified tag from the repository. Returns ErrTagMissing if the tag does not exist.
Context timeout/cancellation is honored during the operation.
func (*Repo) Diff ¶
Diff computes the diff between two revisions and returns unified diff text. The revisions 'a' and 'b' can be any valid git revision specifiers (commit hashes, branch names, tags, etc.).
Filters are applied progressively - a change must pass ALL filters to be included. If no filters are provided, all changes are included.
The method handles binary files appropriately by detecting them and marking the result accordingly. The returned PatchText contains the unified diff text that can be displayed to users or processed by other tools.
Context timeout/cancellation is honored during the operation.
Example ¶
ExampleRepo_Diff demonstrates computing diffs between revisions.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Setup repository with changes
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
ctx := context.Background()
// Initial commit
_ = fs.WriteFile("file.txt", []byte("Line 1\n"), 0o644)
_ = repo.Add(ctx, "file.txt")
_, _ = repo.Commit(ctx, "Initial", git.Signature{
Name: "Test",
Email: "test@example.com",
}, git.CommitOpts{})
// Make changes
_ = fs.WriteFile("file.txt", []byte("Line 1\nLine 2\n"), 0o644)
_ = repo.Add(ctx, "file.txt")
_, _ = repo.Commit(ctx, "Add line", git.Signature{
Name: "Test",
Email: "test@example.com",
}, git.CommitOpts{})
// Compute diff
diff, err := repo.Diff(ctx, "HEAD~1", "HEAD", nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Files changed: %d\n", diff.FileCount)
fmt.Printf("Contains binary: %v\n", diff.IsBinary)
// The diff text contains the unified diff output
// fmt.Println(diff.Text)
Output:
func (*Repo) Fetch ¶
Fetch fetches changes from the specified remote. It supports pruning stale remote branches and shallow fetching when depth > 0. Returns ErrAlreadyUpToDate if there are no changes to fetch.
Context timeout/cancellation is honored during the fetch operation.
Example ¶
ExampleRepo_Fetch demonstrates fetching from a remote repository.
package main
import (
"context"
"errors"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Assume repo with remote configured
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
ctx := context.Background()
// Fetch from remote with pruning
err := repo.Fetch(ctx, "origin", true, 0)
if err != nil {
if errors.Is(err, git.ErrAlreadyUpToDate) {
fmt.Println("Already up to date")
} else {
log.Fatal(err)
}
}
// Fetch with shallow depth for large repos
err = repo.Fetch(ctx, "origin", false, 10)
if err != nil {
log.Fatal(err)
}
fmt.Println("Fetch completed")
}
Output:
func (*Repo) FetchAndMerge ¶
func (r *Repo) FetchAndMerge(ctx context.Context, remote, fromRef string, strategy MergeStrategy) error
FetchAndMerge fetches changes from the specified remote and merges the fromRef. It supports different merge strategies as specified by the strategy parameter. Currently, only FastForwardOnly is supported by go-git.
Context timeout/cancellation is honored during the operation.
func (*Repo) Log ¶
Log returns a commit iterator for the repository with the specified filters applied. The LogFilter can be used to limit results by time range, author, paths, or maximum count. The returned CommitIter should be closed when no longer needed to free resources.
Context timeout/cancellation is honored during the operation.
Example ¶
ExampleRepo_Log demonstrates querying commit history.
package main
import (
"context"
"fmt"
"log"
"github.com/go-git/go-git/v5/plumbing/object"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Assume repo with history exists
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
// Create some commits for the example
for i := 0; i < 5; i++ {
_ = fs.WriteFile(fmt.Sprintf("file%d.txt", i), []byte("content"), 0o644)
_ = repo.Add(context.Background(), ".")
_, _ = repo.Commit(context.Background(), fmt.Sprintf("Commit %d", i), git.Signature{
Name: "Test",
Email: "test@example.com",
}, git.CommitOpts{})
}
ctx := context.Background()
// Query commit history with filters
iter, err := repo.Log(ctx, git.LogFilter{
MaxCount: 3, // Limit to 3 commits
Author: "Test", // Filter by author
})
if err != nil {
log.Fatal(err)
}
defer iter.Close()
// Iterate through commits
count := 0
_ = iter.ForEach(func(c *object.Commit) error {
fmt.Printf("%d. %s\n", count+1, c.Message)
count++
return nil
})
}
Output: 1. Commit 4 2. Commit 3 3. Commit 2
func (*Repo) PullFFOnly ¶
PullFFOnly performs a fast-forward only pull from the specified remote. It fetches changes and updates the current branch only if it's a fast-forward merge. Returns ErrNotFastForward if a merge commit would be required. Returns ErrAlreadyUpToDate if there are no changes to pull.
Context timeout/cancellation is honored during the pull operation.
func (*Repo) Push ¶
Push pushes the current branch to the specified remote. It supports force pushing when force is true. Returns ErrNotFastForward if the push would overwrite remote changes and force is false. Returns ErrAlreadyUpToDate if there are no changes to push.
Context timeout/cancellation is honored during the push operation.
Example ¶
ExampleRepo_Push demonstrates pushing changes to a remote.
package main
import (
"context"
"errors"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Assume repo with commits and remote configured
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
// Auth: myAuthProvider, // Provide AuthProvider implementation
})
ctx := context.Background()
// Push current branch to origin
err := repo.Push(ctx, "origin", false)
if err != nil {
switch {
case errors.Is(err, git.ErrNotFastForward):
fmt.Println("Push rejected: not a fast-forward")
// Could try with force: repo.Push(ctx, "origin", true)
case errors.Is(err, git.ErrAuthRequired):
fmt.Println("Authentication required")
default:
log.Fatal(err)
}
}
fmt.Println("Push successful")
}
Output:
func (*Repo) Refs ¶
Refs returns a list of references that match the specified kind and pattern. The kind parameter filters references by type (branch, remote branch, tag, etc.). The pattern parameter supports glob-style matching with * and ? wildcards. Results are sorted alphabetically.
Context timeout/cancellation is honored during the operation.
func (*Repo) Remove ¶
Remove removes files from the index and worktree. It handles already-deleted files appropriately and supports glob patterns. Files that don't exist in the index are silently ignored.
Context timeout/cancellation is honored during the operation.
func (*Repo) Resolve ¶
Resolve resolves a revision specification to a ResolvedRef containing the kind and hash. The revision can be any valid git revision syntax (commit hash, branch name, tag, HEAD, etc.). Returns a ResolvedRef with the reference kind, resolved hash, and canonical name.
Context timeout/cancellation is honored during the operation.
func (*Repo) Tags ¶
Tags returns a list of tags that pass all the provided filters. If no filters are provided, all tags are returned. Filters are applied progressively - a tag must pass ALL filters to be included. Results are sorted alphabetically.
Context timeout/cancellation is honored during the operation.
Example ¶
ExampleRepo_Tags demonstrates tag management.
package main
import (
"context"
"fmt"
"log"
billyfs "github.com/input-output-hk/catalyst-forge-libs/fs/billy"
"github.com/input-output-hk/catalyst-forge-libs/git"
)
func main() {
// Setup repository
fs := billyfs.NewInMemoryFS()
repo, _ := git.Init(context.Background(), &git.Options{
FS: fs,
Workdir: ".",
})
ctx := context.Background()
// Create initial commit
_ = fs.WriteFile("version", []byte("1.0.0"), 0o644)
_ = repo.Add(ctx, "version")
sha, _ := repo.Commit(ctx, "Initial version", git.Signature{
Name: "Test",
Email: "test@example.com",
}, git.CommitOpts{})
// Create annotated tag
err := repo.CreateTag(ctx, "v1.0.0", sha, "Release version 1.0.0", true)
if err != nil {
log.Fatal(err)
}
// Create lightweight tag
err = repo.CreateTag(ctx, "latest", "HEAD", "", false)
if err != nil {
log.Fatal(err)
}
// List all tags
tags, err := repo.Tags(ctx)
if err != nil {
log.Fatal(err)
}
for _, tag := range tags {
fmt.Printf("Tag: %s\n", tag)
}
}
Output: Tag: latest Tag: v1.0.0
type ResolvedRef ¶
type ResolvedRef struct {
// Kind indicates the type of reference (branch, tag, commit, etc.).
Kind RefKind
// Hash is the resolved commit hash in full SHA-1 format.
Hash string
// CanonicalName is the canonical reference name (e.g., "refs/heads/main").
// For commit hashes, this may be the same as Hash.
CanonicalName string
}
ResolvedRef represents a resolved reference with its kind and hash. This is returned when resolving revision specifiers like branch names, tags, or commit SHAs.
type Signature ¶
type Signature struct {
// Name is the author's or committer's name.
Name string
// Email is the author's or committer's email address.
Email string
// When is the timestamp for the signature.
When time.Time
}
Signature represents an author/committer signature for commits and tags. This is used when creating commits and annotated tags to identify the author.
type TagFilter ¶
TagFilter is a predicate function for filtering tags. It returns true if the tag should be included in the results. Filters are applied progressively - if any filter returns false, the tag is excluded.
func TagExcludeFilter ¶
TagExcludeFilter returns a filter that excludes tags matching the given pattern. This is useful for filtering out certain tags while keeping all others. For example: TagExcludeFilter("*-rc") excludes all release candidates.
func TagPatternFilter ¶
TagPatternFilter returns a filter that matches tags against a glob pattern. Supports * (matches any number of characters) and ? (matches single character). For example: "v1.*" matches "v1.0", "v1.1", etc.
func TagPrefixFilter ¶
TagPrefixFilter returns a filter that matches tags with the given prefix. For example: "v" matches "v1.0", "v2.0", etc.
func TagSuffixFilter ¶
TagSuffixFilter returns a filter that matches tags with the given suffix. For example: "-rc" matches "v1.0-rc", "v2.0-rc", etc.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
auth
Package auth provides composite authentication provider implementation.
|
Package auth provides composite authentication provider implementation. |
|
diff
Package diff provides utilities for analyzing diff output.
|
Package diff provides utilities for analyzing diff output. |
|
fsbridge
Package fsbridge provides adapters between fs.Filesystem and billy.Filesystem.
|
Package fsbridge provides adapters between fs.Filesystem and billy.Filesystem. |
|
refs
Package refs provides reference normalization and filtering utilities.
|
Package refs provides reference normalization and filtering utilities. |