Documentation
¶
Overview ¶
Package gogit provides generic, dependency-light Git ergonomics by shelling out to the git CLI: repository discovery, commit-log parsing with trailers and change stats, and repository metadata (branch, origin URL).
It is the base layer for higher-level tools — the gitscan CLI (cmd/gitscan) and domain collectors such as OmniDevX — in the same way github.com/grokify/gogithub underlies GitHub integrations.
Index ¶
- Variables
- func Discover(roots []string, maxDepth int) ([]string, error)
- func IsRepo(path string) bool
- func NormalizeRemoteURL(remote string) string
- type AIAttribution
- type AICoAuthor
- type AIModel
- type AIStats
- type AIToolPattern
- type CategoryStats
- type Commit
- func (c Commit) AICoAuthors() []AICoAuthor
- func (c Commit) AICoAuthorsWithTools(tools []AIToolPattern) []AICoAuthor
- func (c Commit) CoAuthors() []Signature
- func (c Commit) IsAIAssisted() bool
- func (c Commit) ParseConventional() *ConventionalCommit
- func (c Commit) TrailerValue(key string) string
- func (c Commit) TrailerValues(key string) []string
- type CommitStatsOptions
- type ConventionalCommit
- type LogOptions
- type ModelStats
- type MultiRepoCommitStats
- type PendingResult
- type ProgressFunc
- type PushedResult
- type Ref
- type RefKind
- type Repo
- func (r *Repo) Branch(ctx context.Context) (string, error)
- func (r *Repo) CollectCommitStats(ctx context.Context, opts CommitStatsOptions) (*RepoCommitStats, error)
- func (r *Repo) FilesEverAdded(ctx context.Context) ([]string, error)
- func (r *Repo) HasUpstream(ctx context.Context) (bool, error)
- func (r *Repo) IgnoredFiles(ctx context.Context) ([]string, error)
- func (r *Repo) LastCommitTouching(ctx context.Context, at, path string) (string, error)
- func (r *Repo) Log(ctx context.Context, opts LogOptions) ([]Commit, error)
- func (r *Repo) LsFiles(ctx context.Context, includeUntracked bool) ([]string, error)
- func (r *Repo) LsTree(ctx context.Context, rev string) ([]string, error)
- func (r *Repo) OriginURL(ctx context.Context) (string, error)
- func (r *Repo) Path() string
- func (r *Repo) PendingCommits(ctx context.Context, sinceCommit string) (PendingResult, error)
- func (r *Repo) PushedCommits(ctx context.Context, limit int) (PushedResult, error)
- func (r *Repo) RefsContaining(ctx context.Context, commit string) ([]Ref, error)
- func (r *Repo) ShowContent(ctx context.Context, spec string) (string, error)
- func (r *Repo) StagedFiles(ctx context.Context) ([]string, error)
- func (r *Repo) Tags(ctx context.Context) ([]string, error)
- func (r *Repo) TagsWithDates(ctx context.Context) (map[string]time.Time, error)
- func (r *Repo) TagsWithPath(ctx context.Context, path string) ([]string, error)
- type RepoCommitStats
- type RepoError
- type RepoResult
- type Signature
- type ToolStats
- type Trailer
Constants ¶
This section is empty.
Variables ¶
var DefaultAITools = []AIToolPattern{ { Name: "Claude Code", Provider: "anthropic", Emails: []string{"noreply@anthropic.com"}, ModelPattern: regexp.MustCompile(`(?i)^Claude\s+(\S+\s+[\d][\d.]*)$`), }, { Name: "GitHub Copilot", Provider: "github", Emails: []string{"noreply@github.com", "copilot@github.com"}, ModelPattern: nil, }, { Name: "Gemini CLI", Provider: "google", Emails: []string{ "218195315+gemini-cli@users.noreply.github.com", "176961590+gemini-code-assist[bot]@users.noreply.github.com", "gemini-cli-agent@google.com", "gemini@google.com", }, ModelPattern: regexp.MustCompile(`(?i)^gemini[-_]?cli\s+(.+)$`), }, { Name: "Cursor", Provider: "cursor", Emails: []string{"ai@cursor.sh", "cursor@cursor.sh"}, ModelPattern: regexp.MustCompile(`(?i)^Cursor\s+(.+)$`), }, { Name: "Aider", Provider: "aider", Emails: []string{"aider@aider.chat"}, ModelPattern: nil, }, }
DefaultAITools is the canonical, built-in registry of AI coding assistants and their co-author signatures. Consumers should use MatchAITool or Commit.AICoAuthors rather than maintaining separate lists.
Functions ¶
func Discover ¶
Discover walks each root up to maxDepth directory levels (1 = direct children) and returns paths that are git repositories. Discovery does not descend into repositories, so nested checkouts and vendored trees are not double-counted.
func NormalizeRemoteURL ¶
NormalizeRemoteURL converts a git remote URL to a canonical host/path repository identifier:
https://github.com/x/y.git → github.com/x/y git@github.com:x/y.git → github.com/x/y ssh://git@github.com/x/y → github.com/x/y ssh://git@github.com:2222/x/y → github.com/x/y
An empty input returns "".
Types ¶
type AIAttribution ¶ added in v0.6.0
type AIAttribution struct {
IsAIAuthored bool `json:"isAiAuthored"`
Tools []string `json:"tools,omitempty"`
Models []AIModel `json:"models,omitempty"`
HumanAuthors []Signature `json:"humanAuthors,omitempty"`
}
AIAttribution holds the result of analyzing a commit for AI authorship.
func AnalyzeAuthorship ¶ added in v0.6.0
func AnalyzeAuthorship(c Commit) AIAttribution
AnalyzeAuthorship examines a commit's co-author trailers and returns a complete attribution breakdown: which AI tools contributed, what models were used, and which human co-authors were present. AI tools and models are recognized via the canonical registry in DefaultAITools.
Examples:
"Claude Sonnet 5 <noreply@anthropic.com>" → Tools: ["Claude Code"], Models: [{Provider: "anthropic", Model: "Sonnet 5"}]
"Claude Code <noreply@anthropic.com>" → Tools: ["Claude Code"], Models: nil (no version in name)
"github-actions[bot] <noreply@github.com>" → Tools: ["GitHub Copilot"], Models: nil
type AICoAuthor ¶ added in v0.7.0
type AICoAuthor struct {
Signature Signature `json:"signature"`
Tool string `json:"tool"` // e.g., "Claude Code", "GitHub Copilot", "Gemini CLI"
Provider string `json:"provider,omitempty"` // canonical provider slug, e.g. "anthropic"
Model string `json:"model,omitempty"` // e.g., "Sonnet 4", "Opus 4", "gemini-2.5-pro"
}
AICoAuthor represents an AI coding assistant identified from a co-author trailer.
func MatchAITool ¶ added in v0.7.0
func MatchAITool(sig Signature, tools []AIToolPattern) *AICoAuthor
MatchAITool checks if the email matches a known AI tool and extracts the model from the name if a pattern is defined.
type AIModel ¶ added in v0.6.0
type AIModel struct {
Provider string `json:"provider"`
Model string `json:"model"`
Name string `json:"name"`
}
AIModel holds a parsed AI model identity from a co-author trailer.
type AIStats ¶ added in v0.7.0
type AIStats struct {
TotalCommits int `json:"totalCommits"`
AIAssistedCount int `json:"aiAssistedCount"`
AIAssistedPct float64 `json:"aiAssistedPct"`
ByTool map[string]ToolStats `json:"byTool,omitempty"`
ByModel map[string]ModelStats `json:"byModel,omitempty"`
}
AIStats holds AI-assisted commit statistics.
type AIToolPattern ¶ added in v0.7.0
type AIToolPattern struct {
Name string // Display name, e.g., "Claude Code"
Provider string // Canonical provider slug, e.g. "anthropic"
Emails []string // Known email addresses (lowercase)
ModelPattern *regexp.Regexp
}
AIToolPattern defines how to recognize an AI tool from co-author email and extract model version from the name.
type CategoryStats ¶ added in v0.7.0
type CategoryStats struct {
Category string `json:"category"`
Commits int `json:"commits"`
Insertions int `json:"insertions"`
Deletions int `json:"deletions"`
}
CategoryStats holds commit and LOC counts for one conventional-commit category.
func (CategoryStats) NetAdditions ¶ added in v0.7.0
func (s CategoryStats) NetAdditions() int
NetAdditions returns insertions minus deletions.
type Commit ¶
type Commit struct {
Hash string `json:"hash"`
Author Signature `json:"author"`
AuthorDate time.Time `json:"authorDate"`
Committer Signature `json:"committer"`
CommitDate time.Time `json:"commitDate"`
Subject string `json:"subject"`
Body string `json:"body,omitempty"`
Trailers []Trailer `json:"trailers,omitempty"`
Insertions int `json:"insertions"`
Deletions int `json:"deletions"`
FilesChanged int `json:"filesChanged"`
}
Commit is one parsed log entry. Body is only populated when LogOptions.IncludeBody is set; subjects and trailers alone cover attribution and classification needs for most callers.
func (Commit) AICoAuthors ¶ added in v0.7.0
func (c Commit) AICoAuthors() []AICoAuthor
AICoAuthors returns AI coding assistants identified from co-author trailers. Uses DefaultAITools for recognition.
func (Commit) AICoAuthorsWithTools ¶ added in v0.7.0
func (c Commit) AICoAuthorsWithTools(tools []AIToolPattern) []AICoAuthor
AICoAuthorsWithTools returns AI coding assistants using a custom tool registry.
func (Commit) IsAIAssisted ¶ added in v0.7.0
IsAIAssisted returns true if any co-author is a recognized AI tool.
func (Commit) ParseConventional ¶ added in v0.6.0
func (c Commit) ParseConventional() *ConventionalCommit
ParseConventional parses this commit's subject as a conventional commit. Returns nil if the subject does not match.
func (Commit) TrailerValue ¶ added in v0.6.0
TrailerValue returns the first trailer value matching the given key (case-insensitive), or "" if not found.
func (Commit) TrailerValues ¶ added in v0.6.0
TrailerValues returns all trailer values matching the given key (case-insensitive).
type CommitStatsOptions ¶ added in v0.7.0
type CommitStatsOptions struct {
// Since and Until bound the commit date range (inclusive).
Since time.Time
Until time.Time
// NoMerges excludes merge commits from statistics.
NoMerges bool
// Author filters commits by author (git regex).
Author string
}
CommitStatsOptions configures commit statistics collection.
type ConventionalCommit ¶ added in v0.6.0
type ConventionalCommit struct {
Type string `json:"type"`
Scope string `json:"scope,omitempty"`
Breaking bool `json:"breaking"`
Subject string `json:"subject"`
}
ConventionalCommit holds parsed conventional commit components.
func ParseConventionalCommit ¶ added in v0.6.0
func ParseConventionalCommit(subject string) *ConventionalCommit
ParseConventionalCommit parses the subject line of a conventional commit. Returns nil if the subject does not match the pattern.
type LogOptions ¶
type LogOptions struct {
// Since and Until bound the commit date (half-open in practice: git
// treats both bounds inclusively at second resolution).
Since time.Time
Until time.Time
// SinceCommit limits output to commits reachable from HEAD but not
// from the given commit SHA (i.e., "sha..HEAD"). Used for incremental
// ingestion with high-water marks.
SinceCommit string
// Rev logs commits reachable from this revision (e.g. "origin/main" or
// "@{upstream}") instead of the default HEAD. Ignored when SinceCommit
// is set, which already pins the range to HEAD.
Rev string
// Author filters by author name or email (git regex semantics).
Author string
// NoMerges excludes merge commits.
NoMerges bool
// MaxCount caps the number of commits returned (0 = unlimited).
MaxCount int
// IncludeStats adds per-commit insertions/deletions/files-changed via
// --numstat. Costs proportionally more; leave false when not needed.
IncludeStats bool
// Reverse returns commits in chronological order (oldest first)
// instead of the default newest-first.
Reverse bool
// IncludeBody adds each commit's message body (everything after the
// subject line, via `%b`) — costs proportionally more per commit, so
// leave false when only the subject/trailers are needed.
IncludeBody bool
}
LogOptions filters a commit-log query. Zero values leave a filter unset.
type ModelStats ¶ added in v0.7.0
type ModelStats struct {
Tool string `json:"tool"`
Model string `json:"model"`
Commits int `json:"commits"`
Insertions int `json:"insertions"`
Deletions int `json:"deletions"`
}
ModelStats holds per-model commit counts (tool + model).
type MultiRepoCommitStats ¶ added in v0.7.0
type MultiRepoCommitStats struct {
Since time.Time `json:"since"`
Until time.Time `json:"until"`
TotalStats CategoryStats `json:"total"`
ByCategory map[string]CategoryStats `json:"byCategory"`
AIStats AIStats `json:"aiStats"`
ByRepo []RepoCommitStats `json:"byRepo"`
Errors []RepoError `json:"errors,omitempty"`
}
MultiRepoCommitStats is the aggregated commit/LOC breakdown across multiple repositories.
func AggregateCommitStats ¶ added in v0.7.0
func AggregateCommitStats(ctx context.Context, paths []string, opts CommitStatsOptions, workers int) *MultiRepoCommitStats
AggregateCommitStats collects commit statistics across multiple repositories in parallel. Repositories that fail are recorded in Errors but don't stop the aggregation. Workers controls concurrency; 0 defaults to GOMAXPROCS.
func (*MultiRepoCommitStats) CategoryBreakdown ¶ added in v0.7.0
func (m *MultiRepoCommitStats) CategoryBreakdown() []CategoryStats
CategoryBreakdown returns categories sorted by commit count (descending).
func (*MultiRepoCommitStats) CategoryPercentages ¶ added in v0.7.0
func (m *MultiRepoCommitStats) CategoryPercentages() map[string]float64
CategoryPercentages returns categories with their percentage of total commits.
type PendingResult ¶ added in v0.10.0
type PendingResult struct {
// Commits are the pending commits, oldest first.
Commits []Commit
// Baseline is the ref the commits were computed as being ahead of: the
// configured upstream ("@{upstream}"), a remote-tracking branch (e.g.
// "origin/main"), the remote's default branch when this branch has never
// been pushed under its own name (e.g. a feature branch forked from
// "origin/main"), or an explicit since-commit hash. It is empty only
// when none of these resolve — the repository has no remote, or nothing
// has ever been pushed to it — in which case every commit reachable from
// HEAD is pending.
Baseline string
// Branch is the repository's current branch at query time (or "HEAD"
// when detached), so a caller reporting "no upstream configured" can
// also say which branch that refers to — easy to misread against the
// wrong checkout otherwise.
Branch string
}
PendingResult is the outcome of a PendingCommits query.
type ProgressFunc ¶ added in v0.6.0
ProgressFunc is called during parallel operations with progress updates.
type PushedResult ¶ added in v0.10.0
type PushedResult struct {
// Commits are the pushed commits, most recent first.
Commits []Commit
// Baseline is the ref the commits were read from: the configured
// upstream ("@{upstream}") or the matching remote-tracking branch (e.g.
// "origin/main"). It is empty when the branch has no push target, in
// which case nothing has been pushed and Commits is empty.
Baseline string
// Branch is the repository's current branch at query time (or "HEAD"
// when detached).
Branch string
}
PushedResult is the outcome of a PushedCommits query.
type Ref ¶ added in v0.12.0
type Ref struct {
// Name is the ref's short name, e.g. "main", "origin/main", or "v1.2.0".
Name string `json:"name"`
Kind RefKind `json:"kind"`
}
Ref is a branch, remote-tracking branch, or tag.
type Repo ¶
type Repo struct {
// contains filtered or unexported fields
}
Repo is a handle to a local git repository.
func (*Repo) CollectCommitStats ¶ added in v0.7.0
func (r *Repo) CollectCommitStats(ctx context.Context, opts CommitStatsOptions) (*RepoCommitStats, error)
CollectCommitStats aggregates commit counts and LOC by conventional-commit category for a single repository over the given time range. Non-conventional commits are grouped under "uncategorized". Returns an error if the repo cannot be read; an empty repo returns zero stats, not an error.
func (*Repo) FilesEverAdded ¶ added in v0.12.0
FilesEverAdded returns every path added by any commit reachable from any ref (git log --all --diff-filter=A), sorted and de-duplicated. It surfaces files that were committed and later deleted — and so are absent from HEAD — but remain retrievable from history. Renames are reported under their new path as well, since rename detection is disabled.
Files introduced only by a merge commit's conflict resolution are not reported, matching git log's default of not diffing merges.
func (*Repo) HasUpstream ¶ added in v0.9.0
HasUpstream reports whether the repository's current branch has an upstream (remote-tracking) branch configured that resolves to a commit. A detached HEAD, a branch with no upstream, or a configured-but-missing upstream ref all return (false, nil) rather than an error.
func (*Repo) IgnoredFiles ¶ added in v0.12.0
IgnoredFiles returns untracked paths excluded by .gitignore, .git/info/exclude, or the global excludes file (git ls-files --others --ignored --exclude-standard --directory). A directory that is ignored in full is reported once, with a trailing "/", rather than file by file.
Ignored files are where local secrets (credentials, .env files, keys) usually live; listing them shows what exists on disk that a forced `git add -f` could still commit.
func (*Repo) LastCommitTouching ¶ added in v0.13.0
LastCommitTouching returns the hash of the most recent commit at or before at (a revision, e.g. "HEAD") that modified path, or "" if no commit reachable from at ever touched it (e.g. the path doesn't exist there).
func (*Repo) Log ¶
Log returns commits matching opts, newest first (git log order) unless Reverse is set.
func (*Repo) LsFiles ¶ added in v0.11.0
LsFiles returns the repository's tracked files (git ls-files). When includeUntracked is true, untracked files not covered by .gitignore are included as well (git ls-files -o --exclude-standard), so callers can scan brand-new files before they are staged.
func (*Repo) LsTree ¶ added in v0.11.0
LsTree returns the paths of all files present at a revision (git ls-tree -r), i.e. the full file list of that commit's tree.
func (*Repo) OriginURL ¶
OriginURL returns the raw URL of the "origin" remote, or "" when no origin is configured.
func (*Repo) PendingCommits ¶ added in v0.9.0
PendingCommits returns commits that exist locally but have not yet been pushed, oldest first, along with the baseline they were computed against.
By default the baseline is the branch's push target: its configured upstream, or failing that the matching remote-tracking branch (e.g. origin/main). When the branch has no such baseline — most commonly a freshly created feature branch that has never been pushed under its own name — it falls back to the remote's default branch (e.g. origin/main), so only commits unique to this branch are reported as pending rather than its parent branch's entire history. Only when that also fails to resolve — no remote configured, or nothing has ever been pushed to it — is every commit reachable from HEAD treated as pending, with Baseline empty. A detached HEAD has no branch to compare and yields no baseline.
If sinceCommit is non-empty it overrides the baseline entirely ("sinceCommit..HEAD"), regardless of any upstream or default branch.
func (*Repo) PushedCommits ¶ added in v0.10.0
PushedCommits returns up to limit commits that have already been pushed on the current branch — those reachable from its push target (the configured upstream, or failing that the matching remote-tracking branch such as origin/main) — most recent first. A limit of zero or less returns all pushed commits.
When the branch has no push target (never pushed, no upstream), nothing is considered pushed: Commits is empty and Baseline is "". This is the mirror image of PendingCommits, which reports every commit as pending in the same situation.
func (*Repo) RefsContaining ¶ added in v0.12.0
RefsContaining returns the local branches, remote-tracking branches, and tags whose history contains commit (git for-each-ref --contains). It answers "has this commit been pushed, and has it been released?": a remote ref means the commit reached that remote as of the last fetch, and a tag means it is part of that tagged release's history.
Symbolic refs such as origin/HEAD are omitted, since they duplicate the branch they point to. Results are ordered branches, remotes, then tags, each sorted by name.
func (*Repo) ShowContent ¶ added in v0.11.0
ShowContent returns the content of a git object spec via git show, e.g. ":path" for the staged (index) version of a file or "<rev>:path" for a file at a revision.
func (*Repo) StagedFiles ¶ added in v0.11.0
StagedFiles returns files with staged additions, copies, or modifications (git diff --cached), i.e. the paths whose staged content a pre-commit check should inspect.
func (*Repo) TagsWithDates ¶
TagsWithDates returns tag names mapped to their creation dates (the tag object date for annotated tags, the commit date for lightweight tags).
func (*Repo) TagsWithPath ¶ added in v0.12.0
TagsWithPath returns the tags whose tree contains path (a file or directory, relative to the repository root), sorted by name. This distinguishes content that only ever existed in commit history from content that shipped in a tagged release — for a Go module, a tagged tree is what proxy.golang.org archives permanently.
All tags are checked in a single `git cat-file --batch-check` call, so cost does not grow with one process per tag.
type RepoCommitStats ¶ added in v0.7.0
type RepoCommitStats struct {
Path string `json:"path"`
Since time.Time `json:"since"`
Until time.Time `json:"until"`
TotalStats CategoryStats `json:"total"`
ByCategory map[string]CategoryStats `json:"byCategory"`
AIStats AIStats `json:"aiStats"`
}
RepoCommitStats is the commit/LOC breakdown for a single repository over a time range.
type RepoResult ¶ added in v0.6.0
RepoResult holds the outcome of a parallel operation on one repository.
func RunAll ¶ added in v0.6.0
func RunAll[T any](ctx context.Context, paths []string, fn func(ctx context.Context, repo *Repo) (T, error), workers int) []RepoResult[T]
RunAll executes fn on each repository path in parallel, returning results in the same order as paths. Workers controls concurrency; 0 defaults to GOMAXPROCS. If ctx is cancelled, in-flight operations finish but queued ones are skipped.
func RunAllPaths ¶ added in v0.6.0
func RunAllPaths[T any](ctx context.Context, paths []string, fn func(ctx context.Context, path string) (T, error), workers int) []RepoResult[T]
RunAllPaths executes fn on each path in parallel without requiring a git repository. This is the lower-level variant for operations that manage their own Repo lifecycle or work on non-repo directories.
func RunAllWithProgress ¶ added in v0.6.0
func RunAllWithProgress[T any](ctx context.Context, paths []string, fn func(ctx context.Context, repo *Repo) (T, error), workers int, progress ProgressFunc) []RepoResult[T]
RunAllWithProgress is like RunAll but reports progress via a callback.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
gitscan
command
|
|
|
Package gitgrep provides fast, reusable search over a git repository's working tree, index, a single revision, or history.
|
Package gitgrep provides fast, reusable search over a git repository's working tree, index, a single revision, or history. |
|
internal
|
|
|
cliutil
Package cliutil provides small CLI-input-normalization helpers shared across gitscan's subcommands.
|
Package cliutil provides small CLI-input-normalization helpers shared across gitscan's subcommands. |
|
render
Package render formats gitscan command results for output.
|
Package render formats gitscan command results for output. |