git

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 26, 2025 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package git provides Git operations including repository management, worktree creation, branch operations, commits, and command execution.

Core types:

  • Context: Git repository context with worktree and branch operations
  • CommandRunner: Interface for executing git commands (with mock for testing)
  • BranchNamer: Generates branch names from tickets/descriptions
  • CommitMessage: Conventional commit message builder

Example usage:

ctx := git.NewContext("/path/to/repo")
worktree, err := ctx.CreateWorktree("feature/my-branch")
defer ctx.CleanupWorktree(worktree)

err = ctx.Commit("Add feature", "file1.go", "file2.go")

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotGitRepo indicates the path is not a git repository.
	ErrNotGitRepo = errors.New("not a git repository")

	// ErrWorktreeExists indicates a worktree already exists for the branch.
	ErrWorktreeExists = errors.New("worktree already exists for this branch")

	// ErrWorktreeNotFound indicates the worktree does not exist.
	ErrWorktreeNotFound = errors.New("worktree not found")

	// ErrBranchExists indicates the branch already exists.
	ErrBranchExists = errors.New("branch already exists")

	// ErrBranchNotFound indicates the branch does not exist.
	ErrBranchNotFound = errors.New("branch not found")

	// ErrGitDirty indicates the working directory has uncommitted changes.
	ErrGitDirty = errors.New("working directory has uncommitted changes")

	// ErrNothingToCommit indicates there are no staged changes to commit.
	ErrNothingToCommit = errors.New("nothing to commit")

	// ErrPushFailed indicates a push operation failed.
	ErrPushFailed = errors.New("push failed")

	// ErrMergeConflict indicates a merge conflict occurred.
	ErrMergeConflict = errors.New("merge conflict")
)

Git operation errors.

Functions

func CleanBranch

func CleanBranch(s string) string

CleanBranch ensures a branch name is valid.

func ContextWithGit

func ContextWithGit(ctx context.Context, gc *Context) context.Context

ContextWithGit adds a git Context to a context.Context. Use GitFromContext to retrieve it.

Example:

gitCtx, _ := git.NewContext(".")
ctx := git.ContextWithGit(context.Background(), gitCtx)
// Pass ctx to functions that need git access

func ParseBranch

func ParseBranch(branch string) (branchType, identifier, extra string)

ParseBranch extracts components from a branch name. Returns (type, identifier, extra) where extra is any additional suffix.

func SanitizeBranchName

func SanitizeBranchName(branch string) string

SanitizeBranchName converts a branch name to a safe directory name.

func Slugify

func Slugify(s string) string

Slugify converts a string to a URL-safe slug.

Types

type BranchNamer

type BranchNamer struct {
	TypePrefix   string // Branch type prefix (e.g., "feature", "bugfix", "devflow")
	IncludeTitle bool   // Whether to include title slug in branch name
	MaxLength    int    // Maximum branch name length
}

BranchNamer generates branch names following conventions.

func DefaultBranchNamer

func DefaultBranchNamer() *BranchNamer

DefaultBranchNamer returns a namer with default settings.

func (*BranchNamer) ForBugfix

func (n *BranchNamer) ForBugfix(ticketID, description string) string

ForBugfix generates a bugfix branch name. Example: "TK-422", "auth-crash" -> "bugfix/tk-422-auth-crash"

func (*BranchNamer) ForFeature

func (n *BranchNamer) ForFeature(name string) string

ForFeature generates a simple feature branch name. Example: "add-caching" -> "feature/add-caching"

func (*BranchNamer) ForTicket

func (n *BranchNamer) ForTicket(ticketID, title string) string

ForTicket generates a branch name from a ticket ID and title. Example: "TK-421", "Add User Authentication" -> "feature/tk-421-add-user-authentication"

func (*BranchNamer) ForWorkflow

func (n *BranchNamer) ForWorkflow(workflowID, identifier string) string

ForWorkflow generates a branch name for automated workflow runs. Example: "ticket-to-pr", "TK-421" -> "devflow/ticket-to-pr-tk-421-1734567890"

type CommandError

type CommandError struct {
	Command string
	Args    []string
	WorkDir string
	Output  string
	Err     error
}

CommandError represents a command execution error.

func (*CommandError) Error

func (e *CommandError) Error() string

func (*CommandError) Unwrap

func (e *CommandError) Unwrap() error

type CommandRunner

type CommandRunner interface {
	// Run executes a command and returns the trimmed stdout.
	// workDir is the working directory for the command.
	// If the command fails, it returns the stderr/stdout as the error message.
	Run(workDir string, name string, args ...string) (stdout string, err error)
}

CommandRunner executes shell commands. This interface allows mocking command execution in tests.

type CommitAndPushResult

type CommitAndPushResult struct {
	Commit *CommitResult
	Push   *PushResult
}

CommitAndPushResult contains the result of a commit and push operation.

type CommitConfig

type CommitConfig struct {
	IncludeGeneratedBy bool   // Include "Generated-By: devflow" footer
	TicketRefPrefix    string // Prefix for ticket refs ("Refs:", "Fixes:", "Closes:")
	RequireTicketRef   bool   // Require at least one ticket reference
}

CommitConfig configures commit message formatting.

func DefaultCommitConfig

func DefaultCommitConfig() CommitConfig

DefaultCommitConfig returns the default commit configuration.

type CommitMessage

type CommitMessage struct {
	Type        CommitType // Required: type of change (feat, fix, etc.)
	Scope       string     // Optional: area of codebase affected
	Subject     string     // Required: short description (imperative mood)
	Body        string     // Optional: detailed explanation
	TicketRefs  []string   // Optional: ticket references (TK-421, ISSUE-123)
	CoAuthors   []string   // Optional: co-author emails
	GeneratedBy string     // Optional: tool that generated the commit
	Breaking    bool       // Whether this is a breaking change
}

CommitMessage represents a structured commit message following conventional commits.

func NewCommitMessage

func NewCommitMessage(typ CommitType, subject string) *CommitMessage

NewCommitMessage creates a commit message with the devflow marker.

func (*CommitMessage) String

func (c *CommitMessage) String() string

String formats the commit message following conventional commit format.

func (*CommitMessage) Validate

func (c *CommitMessage) Validate() error

Validate checks if the commit message is valid.

func (*CommitMessage) WithBody

func (c *CommitMessage) WithBody(body string) *CommitMessage

WithBody adds a body to the commit message.

func (*CommitMessage) WithBreaking

func (c *CommitMessage) WithBreaking() *CommitMessage

WithBreaking marks this as a breaking change.

func (*CommitMessage) WithCoAuthor

func (c *CommitMessage) WithCoAuthor(email string) *CommitMessage

WithCoAuthor adds a co-author.

func (*CommitMessage) WithScope

func (c *CommitMessage) WithScope(scope string) *CommitMessage

WithScope adds a scope to the commit message.

func (*CommitMessage) WithTicketRef

func (c *CommitMessage) WithTicketRef(ref string) *CommitMessage

WithTicketRef adds a ticket reference.

func (*CommitMessage) WithTicketRefs

func (c *CommitMessage) WithTicketRefs(refs ...string) *CommitMessage

WithTicketRefs adds multiple ticket references.

func (*CommitMessage) WithoutGeneratedBy

func (c *CommitMessage) WithoutGeneratedBy() *CommitMessage

WithoutGeneratedBy removes the Generated-By footer.

type CommitResult

type CommitResult struct {
	SHA     string    // Full commit SHA
	Branch  string    // Branch name
	Message string    // Commit message
	Date    time.Time // Commit timestamp
}

CommitResult contains the result of a commit operation.

type CommitType

type CommitType string

CommitType represents the type of change in a commit.

const (
	CommitTypeFeat     CommitType = "feat"
	CommitTypeFix      CommitType = "fix"
	CommitTypeDocs     CommitType = "docs"
	CommitTypeStyle    CommitType = "style"
	CommitTypeRefactor CommitType = "refactor"
	CommitTypePerf     CommitType = "perf"
	CommitTypeTest     CommitType = "test"
	CommitTypeBuild    CommitType = "build"
	CommitTypeCI       CommitType = "ci"
	CommitTypeChore    CommitType = "chore"
	CommitTypeRevert   CommitType = "revert"
)

type Context

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

Context manages git operations for a repository.

func GitFromContext

func GitFromContext(ctx context.Context) *Context

GitFromContext retrieves a git Context from a context.Context. Returns nil if no git Context is present.

Example:

func doWork(ctx context.Context) error {
    gitCtx := git.GitFromContext(ctx)
    if gitCtx == nil {
        return errors.New("git context required")
    }
    return gitCtx.CommitAll("message")
}

func MustGitFromContext

func MustGitFromContext(ctx context.Context) *Context

MustGitFromContext retrieves a git Context or panics. Use in code where git context is required and missing is a programming error.

func NewContext

func NewContext(repoPath string, opts ...Option) (*Context, error)

NewContext creates a new git context for the repository. It validates that the path is a git repository and applies any options.

func (*Context) BranchExists

func (g *Context) BranchExists(name string) bool

BranchExists checks if a branch exists.

func (*Context) Checkout

func (g *Context) Checkout(ref string) error

Checkout switches to the specified ref (branch, tag, or commit).

func (*Context) CheckoutNew

func (g *Context) CheckoutNew(name string) error

CheckoutNew creates and checks out a new branch at the current HEAD. This is a convenience method combining CreateBranch + Checkout.

func (*Context) CheckoutNewAt

func (g *Context) CheckoutNewAt(name, ref string) error

CheckoutNewAt creates and checks out a new branch at the specified ref.

func (*Context) CleanupWorktree

func (g *Context) CleanupWorktree(worktreePath string) error

CleanupWorktree removes a worktree and its registration. If force is true, removes even with uncommitted changes.

func (*Context) Commit

func (g *Context) Commit(message string) error

Commit creates a commit with the given message. Returns ErrNothingToCommit if there are no staged changes.

func (*Context) CommitAll

func (g *Context) CommitAll(message string) (*CommitResult, error)

CommitAll stages all changes and commits with the given message. Returns ErrNothingToCommit if there are no changes to commit. This is a convenience method combining StageAll + Commit + HeadCommit + CurrentBranch.

func (*Context) CommitAllAndPush

func (g *Context) CommitAllAndPush(message string) (*CommitAndPushResult, error)

CommitAllAndPush stages all changes, commits, and pushes to origin. This is the most common workflow: save work and push it. If push fails, returns partial result with the commit info.

func (*Context) CommitAndPushTo

func (g *Context) CommitAndPushTo(message, remote string) (*CommitAndPushResult, error)

CommitAndPushTo stages all changes, commits, and pushes to the specified remote.

func (*Context) CreateBranch

func (g *Context) CreateBranch(name string) error

CreateBranch creates a new branch at HEAD.

func (*Context) CreateWorktree

func (g *Context) CreateWorktree(branch string) (string, error)

CreateWorktree creates an isolated worktree for the branch. If the branch doesn't exist, it will be created. Returns the path to the worktree directory.

func (*Context) CurrentBranch

func (g *Context) CurrentBranch() (string, error)

CurrentBranch returns the current branch name.

func (*Context) DeleteBranch

func (g *Context) DeleteBranch(name string, force bool) error

DeleteBranch deletes a branch. If force is true, uses -D instead of -d.

func (*Context) Diff

func (g *Context) Diff(base, head string) (string, error)

Diff returns the diff between two refs.

func (*Context) DiffStaged

func (g *Context) DiffStaged() (string, error)

DiffStaged returns the diff of staged changes.

func (*Context) Fetch

func (g *Context) Fetch(remote string) error

Fetch fetches updates from the remote.

func (*Context) GetRemoteURL

func (g *Context) GetRemoteURL(remote string) (string, error)

GetRemoteURL returns the URL of the specified remote.

func (*Context) GetWorktree

func (g *Context) GetWorktree(branch string) (*WorktreeInfo, error)

GetWorktree returns information about a specific worktree by branch name.

func (*Context) GetWorktreeByPath

func (g *Context) GetWorktreeByPath(path string) (*WorktreeInfo, error)

GetWorktreeByPath returns information about a specific worktree by path.

func (*Context) HeadCommit

func (g *Context) HeadCommit() (string, error)

HeadCommit returns the current HEAD commit SHA.

func (*Context) InWorktree

func (g *Context) InWorktree(worktreePath string) *Context

InWorktree returns a new Context that operates in the specified worktree.

func (*Context) IsBranchPushed

func (g *Context) IsBranchPushed(branch string) bool

IsBranchPushed checks if the branch exists on the remote.

func (*Context) IsClean

func (g *Context) IsClean() (bool, error)

IsClean returns true if the working tree has no uncommitted changes.

func (*Context) ListWorktrees

func (g *Context) ListWorktrees() ([]WorktreeInfo, error)

ListWorktrees returns all active worktrees.

func (*Context) PruneWorktrees

func (g *Context) PruneWorktrees() error

PruneWorktrees removes stale worktree administrative files.

func (*Context) Pull

func (g *Context) Pull(remote, branch string) error

Pull pulls changes from the remote.

func (*Context) Push

func (g *Context) Push(remote, branch string, setUpstream bool) error

Push pushes the branch to the remote. If setUpstream is true, uses -u to set upstream tracking.

func (*Context) PushCurrent

func (g *Context) PushCurrent() (*PushResult, error)

PushCurrent pushes the current branch to origin. Automatically sets upstream tracking if the branch hasn't been pushed before. This is a convenience method that handles the common case of pushing work.

func (*Context) PushCurrentTo

func (g *Context) PushCurrentTo(remote string) (*PushResult, error)

PushCurrentTo pushes the current branch to the specified remote. Automatically sets upstream tracking if needed.

func (*Context) RepoPath

func (g *Context) RepoPath() string

RepoPath returns the path to the main repository.

func (*Context) RunGit

func (g *Context) RunGit(args ...string) (string, error)

RunGit executes a git command and returns stdout. This is the public version of runGit for use by external packages.

func (*Context) Stage

func (g *Context) Stage(files ...string) error

Stage adds files to the staging area.

func (*Context) StageAll

func (g *Context) StageAll() error

StageAll stages all changes (git add -A).

func (*Context) Status

func (g *Context) Status() (string, error)

Status returns the working tree status in short format.

func (*Context) WorkDir

func (g *Context) WorkDir() string

WorkDir returns the current working directory for git commands. This is the repo path unless working in a worktree.

func (*Context) WorktreeDir

func (g *Context) WorktreeDir() string

WorktreeDir returns the path to the worktrees directory.

type Error

type Error struct {
	Op     string // Operation that failed (e.g., "commit", "push")
	Cmd    string // Git command that was run
	Output string // Combined stdout/stderr output
	Err    error  // Underlying error
}

Error wraps a git command error with context.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type ExecRunner

type ExecRunner struct{}

ExecRunner is the default CommandRunner using exec.Command.

func NewExecRunner

func NewExecRunner() *ExecRunner

NewExecRunner creates a new ExecRunner.

func (*ExecRunner) Run

func (r *ExecRunner) Run(workDir, name string, args ...string) (string, error)

Run executes the command using exec.Command.

type MockCall

type MockCall struct {
	WorkDir string
	Command string
	Args    []string
}

MockCall records a single command invocation.

type MockResponse

type MockResponse struct {
	Stdout string
	Err    error
}

MockResponse represents a mock command response.

type MockResponseBuilder

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

MockResponseBuilder builds mock responses.

func (*MockResponseBuilder) Return

func (b *MockResponseBuilder) Return(stdout string, err error) *MockRunner

Return sets the response for this command.

type MockRunner

type MockRunner struct {
	// Responses maps "command args..." to predefined responses.
	// Use "*" as a wildcard for any command.
	Responses map[string]MockResponse

	// Calls records all commands that were executed.
	Calls []MockCall

	// DefaultResponse is returned when no specific response is configured.
	DefaultResponse MockResponse
}

MockRunner is a test double for CommandRunner. It allows configuring responses for specific commands.

func NewMockRunner

func NewMockRunner() *MockRunner

NewMockRunner creates a new MockRunner with empty responses.

func (*MockRunner) CallCount

func (m *MockRunner) CallCount(name string) int

CallCount returns the number of times a command was called.

func (*MockRunner) OnAnyCommand

func (m *MockRunner) OnAnyCommand() *MockResponseBuilder

OnAnyCommand configures a response for any command.

func (*MockRunner) OnCommand

func (m *MockRunner) OnCommand(name string, args ...string) *MockResponseBuilder

OnCommand configures a response for a specific command. Example: runner.OnCommand("git", "status", "--short").Return("M file.go", nil)

func (*MockRunner) Run

func (m *MockRunner) Run(workDir, name string, args ...string) (string, error)

Run implements CommandRunner for MockRunner.

func (*MockRunner) WasCalled

func (m *MockRunner) WasCalled(name string, args ...string) bool

WasCalled returns true if the command was called.

type Option

type Option func(*Context)

Option configures Context.

func WithRunner

func WithRunner(runner CommandRunner) Option

WithRunner sets a custom command runner for git operations. This is primarily used for testing to inject mock command execution.

func WithWorktreeDir

func WithWorktreeDir(dir string) Option

WithWorktreeDir sets the directory where worktrees are created. Default is ".worktrees" relative to the repository root.

type PushResult

type PushResult struct {
	Remote      string // Remote name (e.g., "origin")
	Branch      string // Branch that was pushed
	SHA         string // Commit SHA that was pushed
	SetUpstream bool   // Whether upstream tracking was set
	URL         string // Remote URL (for reference)
}

PushResult contains the result of a push operation.

type SequentialMockRunner

type SequentialMockRunner struct {
	Calls []MockCall
	// contains filtered or unexported fields
}

SequentialMockRunner is a mock runner that returns responses in order.

func NewSequentialMockRunner

func NewSequentialMockRunner() *SequentialMockRunner

NewSequentialMockRunner creates a new SequentialMockRunner.

func (*SequentialMockRunner) AddOutput

func (m *SequentialMockRunner) AddOutput(stdout string, err error) *SequentialMockRunner

AddOutput adds a response to the queue.

func (*SequentialMockRunner) AddOutputError

func (m *SequentialMockRunner) AddOutputError(stdout, errOutput string, err error) *SequentialMockRunner

AddOutputError adds a response with custom error output.

func (*SequentialMockRunner) Run

func (m *SequentialMockRunner) Run(workDir, name string, args ...string) (string, error)

Run implements CommandRunner for SequentialMockRunner.

type WorktreeInfo

type WorktreeInfo struct {
	Path   string // Filesystem path to the worktree
	Branch string // Branch checked out in the worktree
	Commit string // HEAD commit SHA
}

WorktreeInfo represents an active git worktree.

Directories

Path Synopsis
Package parallel provides multi-worktree orchestration for parallel branch execution.
Package parallel provides multi-worktree orchestration for parallel branch execution.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL