git

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package git provides Git operations for managing worktrees, branches, merges, and PRs.

The package is organized into focused modules:

  • service.go: GitService struct and constructor
  • status.go: Worktree status, diff stats, file diffs
  • commit.go: Commit operations, message generation
  • merge.go: Merge and PR operations
  • branch.go: Branch management, divergence checking
  • github.go: GitHub issue/PR integration

Index

Constants

View Source
const (
	// MaxBranchNameLength is the maximum length for auto-generated branch names.
	// User-provided branch names can be longer (up to MaxBranchNameValidation).
	MaxBranchNameLength = 50
)

Configuration constants for branch operations

View Source
const (
	// MaxDiffSize is the maximum number of characters to include in a diff.
	// This prevents excessive memory usage when Claude is analyzing changes.
	// Claude's context window can handle much more, but large diffs slow down
	// commit message generation and rarely provide additional value.
	// 50KB is enough to capture meaningful changes while staying responsive.
	MaxDiffSize = 50000
)

Configuration constants for commit operations

Variables

This section is empty.

Functions

func ExtractOwnerRepo

func ExtractOwnerRepo(remoteURL string) string

ExtractOwnerRepo extracts "owner/repo" from a git remote URL. Supports SSH (git@github.com:owner/repo.git) and HTTPS (https://github.com/owner/repo.git) formats. Returns empty string if the URL cannot be parsed.

func GetPRLinkText

func GetPRLinkText(issueRef *config.IssueRef) string

GetPRLinkText returns the appropriate text to add to a PR body based on the issue source. For GitHub issues: returns "\n\nFixes #123" For Asana tasks: returns "" (no auto-close support) For unknown sources: returns ""

Types

type BranchDivergence

type BranchDivergence struct {
	Behind int // Number of commits local is behind remote
	Ahead  int // Number of commits local is ahead of remote
}

BranchDivergence represents the divergence between local and remote branches.

func (*BranchDivergence) CanFastForward

func (d *BranchDivergence) CanFastForward() bool

CanFastForward returns true if local can fast-forward to remote (not ahead).

func (*BranchDivergence) IsDiverged

func (d *BranchDivergence) IsDiverged() bool

IsDiverged returns true if the branches have diverged (both ahead and behind).

type CIStatus

type CIStatus string

CIStatus represents the overall CI check status for a PR.

const (
	CIStatusPassing CIStatus = "passing"
	CIStatusFailing CIStatus = "failing"
	CIStatusPending CIStatus = "pending"
	CIStatusNone    CIStatus = "none" // No checks configured
)

type DiffStats

type DiffStats struct {
	FilesChanged int // Number of files changed
	Additions    int // Number of lines added
	Deletions    int // Number of lines deleted
}

DiffStats represents the statistics of changes in a worktree

type FileDiff

type FileDiff struct {
	Filename string // File path relative to repo root
	Status   string // Status code: M (modified), A (added), D (deleted), etc.
	Diff     string // Diff content for this file only
}

FileDiff represents a single file's diff with its status

type GitHubIssue

type GitHubIssue struct {
	Number int    `json:"number"`
	Title  string `json:"title"`
	Body   string `json:"body"`
	URL    string `json:"url"`
}

GitHubIssue represents a GitHub issue fetched via the gh CLI

type GitService

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

GitService provides git operations with explicit dependency injection. Instead of using a package-level executor variable, each GitService instance holds its own executor, enabling proper testing and avoiding global state.

func NewGitService

func NewGitService() *GitService

NewGitService creates a new GitService with the default real executor.

func NewGitServiceWithExecutor

func NewGitServiceWithExecutor(exec pexec.CommandExecutor) *GitService

NewGitServiceWithExecutor creates a new GitService with a custom executor. This is primarily used for testing where a mock executor is needed.

func (*GitService) AbortMerge

func (s *GitService) AbortMerge(ctx context.Context, repoPath string) error

AbortMerge aborts an in-progress merge

func (*GitService) AddIssueLabel

func (s *GitService) AddIssueLabel(ctx context.Context, repoPath string, issueNumber int, label string) error

AddIssueLabel adds a label to a GitHub issue using the gh CLI.

func (*GitService) CheckPRChecks

func (s *GitService) CheckPRChecks(ctx context.Context, repoPath, branch string) (CIStatus, error)

CheckPRChecks checks the CI status of a PR for the given branch. Uses `gh pr checks` which returns exit code 0 if all checks pass.

func (*GitService) CheckPRReviewDecision

func (s *GitService) CheckPRReviewDecision(ctx context.Context, repoPath, branch string) (ReviewDecision, error)

CheckPRReviewDecision returns the review decision for a PR by inspecting individual reviews. GitHub's reviewDecision field only works with branch protection rules, so we derive the decision ourselves by looking at each reviewer's most recent actionable review state.

func (*GitService) CheckoutBranch

func (s *GitService) CheckoutBranch(ctx context.Context, repoPath, branch string) error

CheckoutBranch checks out the specified branch in the given repo. Returns an error if the checkout fails (e.g., uncommitted changes would be overwritten).

func (*GitService) CheckoutBranchIgnoreWorktrees

func (s *GitService) CheckoutBranchIgnoreWorktrees(ctx context.Context, repoPath, branch string) error

CheckoutBranchIgnoreWorktrees checks out the specified branch, even if it's already checked out in another worktree. This is useful for the preview feature where we want to temporarily view a worktree's branch in the main repo.

func (*GitService) CommentOnIssue

func (s *GitService) CommentOnIssue(ctx context.Context, repoPath string, issueNumber int, body string) error

CommentOnIssue leaves a comment on a GitHub issue using the gh CLI.

func (*GitService) CommitAll

func (s *GitService) CommitAll(ctx context.Context, worktreePath, message string) error

CommitAll stages all changes and commits them with the given message

func (*GitService) CommitConflictResolution

func (s *GitService) CommitConflictResolution(ctx context.Context, repoPath, message string) error

CommitConflictResolution stages all changes and commits with the given message. This is used after resolving merge conflicts to complete the merge.

func (*GitService) CreatePR

func (s *GitService) CreatePR(ctx context.Context, repoPath, worktreePath, branch, baseBranch, commitMsg string, issueRef *config.IssueRef, sessionID string) <-chan Result

CreatePR pushes the branch and creates a pull request using gh CLI worktreePath is where Claude made changes - we commit any uncommitted changes first If commitMsg is provided and non-empty, it will be used directly instead of generating one If issueRef is provided, appropriate link text will be added to the PR body based on the source. baseBranch is the branch this PR should be compared against (typically the session's BaseBranch). sessionID is used to load and upload the session transcript as a PR comment; pass "" to skip.

func (*GitService) EnsureCommitted

func (s *GitService) EnsureCommitted(ctx context.Context, ch chan<- Result, worktreePath, commitMsg string) bool

EnsureCommitted checks for uncommitted changes and commits them if present. If commitMsg is empty, it generates a commit message using Claude (with fallback). Returns true if the operation succeeded (either committed or no changes needed), false if there was an error (error is sent to the result channel).

func (*GitService) FetchGitHubIssues

func (s *GitService) FetchGitHubIssues(ctx context.Context, repoPath string) ([]GitHubIssue, error)

FetchGitHubIssues fetches open issues from a GitHub repository using the gh CLI. The repoPath is used as the working directory to determine which repo to query.

func (*GitService) FetchGitHubIssuesWithLabel

func (s *GitService) FetchGitHubIssuesWithLabel(ctx context.Context, repoPath, label string) ([]GitHubIssue, error)

FetchGitHubIssuesWithLabel fetches open issues with a specific label from a GitHub repository.

func (*GitService) FetchPRReviewComments

func (s *GitService) FetchPRReviewComments(ctx context.Context, repoPath, branch string) ([]PRReviewComment, error)

FetchPRReviewComments fetches review comments from a pull request using the gh CLI. Returns top-level PR comments, review body comments, and inline code review comments as a flattened slice. The repoPath is used as the working directory.

func (*GitService) GenerateBranchNamesFromOptions

func (s *GitService) GenerateBranchNamesFromOptions(ctx context.Context, options []struct {
	Number int
	Text   string
}) (map[int]string, error)

GenerateBranchNamesFromOptions uses Claude to generate short, descriptive git branch names from a list of option texts. Returns a map from option number to branch name. This batches all options into a single Claude call for efficiency.

func (*GitService) GenerateCommitMessage

func (s *GitService) GenerateCommitMessage(ctx context.Context, worktreePath string) (string, error)

GenerateCommitMessage creates a commit message based on the changes (simple fallback)

func (*GitService) GenerateCommitMessageWithClaude

func (s *GitService) GenerateCommitMessageWithClaude(ctx context.Context, worktreePath string) (string, error)

GenerateCommitMessageWithClaude uses Claude to generate a commit message from the diff

func (*GitService) GeneratePRTitleAndBodyWithIssueRef

func (s *GitService) GeneratePRTitleAndBodyWithIssueRef(ctx context.Context, repoPath, branch, baseBranch string, issueRef *config.IssueRef) (title, body string, err error)

GeneratePRTitleAndBodyWithIssueRef uses Claude to generate a PR title and body from the branch changes. If issueRef is provided, it will add appropriate link text based on the source:

  • GitHub: adds "Fixes #{number}" to auto-close the issue
  • Asana: no auto-close support (Asana doesn't use commit message keywords)

baseBranch is the branch this PR will be compared against (typically the session's BaseBranch or main).

func (*GitService) GetBatchPRStates

func (s *GitService) GetBatchPRStates(ctx context.Context, repoPath string, branches []string) (map[string]PRState, error)

GetBatchPRStates returns the PR states for multiple branches in a single gh CLI call. It uses `gh pr list --state all` to fetch all PRs for the repo, then matches by branch name. Branches without a matching PR are omitted from the result map.

func (*GitService) GetBatchPRStatesWithComments

func (s *GitService) GetBatchPRStatesWithComments(ctx context.Context, repoPath string, branches []string) (map[string]PRBatchResult, error)

GetBatchPRStatesWithComments returns PR states and comment counts for multiple branches. Uses a single `gh pr list` call per repo. The comment count is len(comments) + len(reviews), which captures top-level PR comments and review submissions.

func (*GitService) GetBranchDivergence

func (s *GitService) GetBranchDivergence(ctx context.Context, repoPath, localBranch, remoteBranch string) (*BranchDivergence, error)

GetBranchDivergence returns how many commits the local branch is behind and ahead of the remote branch. Uses git rev-list --count --left-right which outputs "behind\tahead". Returns an error if either branch doesn't exist or comparison fails.

func (*GitService) GetConflictedFiles

func (s *GitService) GetConflictedFiles(ctx context.Context, repoPath string) ([]string, error)

GetConflictedFiles returns the list of files with merge conflicts in a repo

func (*GitService) GetCurrentBranch

func (s *GitService) GetCurrentBranch(ctx context.Context, repoPath string) (string, error)

GetCurrentBranch returns the name of the currently checked out branch in the given repo/worktree. Returns an error if HEAD is detached or the command fails.

func (*GitService) GetDefaultBranch

func (s *GitService) GetDefaultBranch(ctx context.Context, repoPath string) string

GetDefaultBranch returns the default branch name (main or master)

func (*GitService) GetDiffStats

func (s *GitService) GetDiffStats(ctx context.Context, worktreePath string) (*DiffStats, error)

GetDiffStats returns the diff statistics (files changed, additions, deletions) for uncommitted changes in the given worktree.

func (*GitService) GetPRState

func (s *GitService) GetPRState(ctx context.Context, repoPath, branch string) (PRState, error)

GetPRState returns the state of a PR for the given branch using the gh CLI. Returns PRStateUnknown and an error if the PR cannot be found or gh fails.

func (*GitService) GetRemoteOriginURL

func (s *GitService) GetRemoteOriginURL(ctx context.Context, repoPath string) (string, error)

GetRemoteOriginURL returns the URL of the "origin" remote.

func (*GitService) GetWorktreeStatus

func (s *GitService) GetWorktreeStatus(ctx context.Context, worktreePath string) (*WorktreeStatus, error)

GetWorktreeStatus returns the status of uncommitted changes in a worktree

func (*GitService) HasRemoteOrigin

func (s *GitService) HasRemoteOrigin(ctx context.Context, repoPath string) bool

HasRemoteOrigin checks if the repository has a remote named "origin"

func (*GitService) HasTrackingBranch

func (s *GitService) HasTrackingBranch(ctx context.Context, repoPath, branch string) bool

HasTrackingBranch checks if the given branch has an upstream tracking branch configured. Uses git config to check for branch.<name>.remote which is set when tracking is configured.

func (*GitService) IsMergeInProgress

func (s *GitService) IsMergeInProgress(ctx context.Context, repoPath string) (bool, error)

IsMergeInProgress checks if a merge is currently in progress in the repo. It returns true if MERGE_HEAD exists (meaning there's an ongoing merge).

func (*GitService) MergePR

func (s *GitService) MergePR(ctx context.Context, repoPath, branch string, deleteBranch bool, method string) error

MergePR merges a PR for the given branch using the specified merge method. Valid methods: "rebase" (default), "squash", "merge". If method is empty, defaults to "rebase". The deleteBranch parameter controls whether to delete the branch after merging. For autonomous sessions, pass false since the branch is deleted during session cleanup.

func (*GitService) MergeToMain

func (s *GitService) MergeToMain(ctx context.Context, repoPath, worktreePath, branch, commitMsg string) <-chan Result

MergeToMain merges a branch into the default branch worktreePath is where Claude made changes - we commit any uncommitted changes first If commitMsg is provided and non-empty, it will be used directly instead of generating one

func (*GitService) MergeToParent

func (s *GitService) MergeToParent(ctx context.Context, childWorktreePath, childBranch, parentWorktreePath, parentBranch, commitMsg string) <-chan Result

MergeToParent merges a child session's branch into its parent session's branch. This operates on the parent's worktree, merging the child's changes into it. childWorktreePath is where the child's changes are - we commit uncommitted changes first parentWorktreePath is where we perform the merge If commitMsg is provided and non-empty, it will be used directly instead of generating one

func (*GitService) PushUpdates

func (s *GitService) PushUpdates(ctx context.Context, repoPath, worktreePath, branch, commitMsg string) <-chan Result

PushUpdates commits any uncommitted changes and pushes to the remote branch. This is used after a PR has been created to push additional commits based on feedback. If commitMsg is provided and non-empty, it will be used directly instead of generating one.

func (*GitService) RemoteBranchExists

func (s *GitService) RemoteBranchExists(ctx context.Context, repoPath, remoteBranch string) bool

RemoteBranchExists checks if a remote branch reference exists (e.g., "origin/main"). Uses git rev-parse --verify which exits 0 if the ref exists, non-zero otherwise.

func (*GitService) RemoveIssueLabel

func (s *GitService) RemoveIssueLabel(ctx context.Context, repoPath string, issueNumber int, label string) error

RemoveIssueLabel removes a label from a GitHub issue using the gh CLI.

func (*GitService) RenameBranch

func (s *GitService) RenameBranch(ctx context.Context, worktreePath, oldName, newName string) error

RenameBranch renames a git branch in the given worktree. The worktree must have the branch checked out.

func (*GitService) SquashMergeToMain

func (s *GitService) SquashMergeToMain(ctx context.Context, repoPath, worktreePath, branch, commitMsg string) <-chan Result

SquashMergeToMain squashes all commits from a branch into a single commit when merging to main. worktreePath is where Claude made changes - we commit any uncommitted changes first. commitMsg is required and will be used as the commit message for the squashed commit.

func (*GitService) UploadTranscriptToPR

func (s *GitService) UploadTranscriptToPR(ctx context.Context, repoPath, branch, transcript string) error

UploadTranscriptToPR posts a session transcript as a comment on the PR for the given branch. The transcript is formatted as a collapsed <details> block so it does not clutter the PR.

type PRBatchResult

type PRBatchResult struct {
	State        PRState
	CommentCount int // len(comments) + len(actionable reviews) — excludes APPROVED/DISMISSED reviews
}

PRBatchResult holds the state and comment count for a PR from a batch query.

type PRReviewComment

type PRReviewComment struct {
	Author string // GitHub username
	Body   string // Comment text
	Path   string // File path (empty for top-level/review body comments)
	Line   int    // Line number (0 for top-level/review body comments)
	URL    string // Permalink
}

PRReviewComment represents a single review comment from a GitHub pull request. This can be a top-level PR comment, a review body, or an inline code review comment.

type PRState

type PRState string

PRState represents the state of a GitHub pull request

const (
	PRStateOpen    PRState = "OPEN"
	PRStateMerged  PRState = "MERGED"
	PRStateClosed  PRState = "CLOSED"
	PRStateUnknown PRState = ""
)

type Result

type Result struct {
	Output          string
	Error           error
	Done            bool
	ConflictedFiles []string // Files with merge conflicts (only set on conflict)
	RepoPath        string   // Path to the repo where conflict occurred
}

Result represents output from a git operation

type ReviewDecision

type ReviewDecision string

ReviewDecision represents the GitHub PR review decision.

const (
	ReviewApproved         ReviewDecision = "APPROVED"
	ReviewChangesRequested ReviewDecision = "CHANGES_REQUESTED"
	ReviewNone             ReviewDecision = "" // No actionable reviews yet
)

type WorktreeStatus

type WorktreeStatus struct {
	HasChanges bool
	Summary    string     // Short summary like "3 files changed"
	Files      []string   // List of changed files
	Diff       string     // Full diff output
	FileDiffs  []FileDiff // Per-file diffs for detailed viewing
}

WorktreeStatus represents the status of changes in a worktree

Jump to

Keyboard shortcuts

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