gogit v0.11.0 Release Notes
Release Date: 2026-09-21
Overview
This release adds gitgrep, a new package for searching a repository's
content and history — the working tree, the staged index, a revision, or the
full commit history — by shelling out to native git (git grep, the pickaxe
-S/-G, and streamed git log -p patches). It is deliberately
policy-free: callers supply patterns and get matches back, with no built-in
notion of what a match means, so it is a general-purpose primitive rather
than a leak/secret scanner itself. The gitscan grep subcommand exposes it
directly from the CLI. No breaking changes.
Highlights
New gitgrep package
Three operations cover the common ways to search a repository:
GrepTree— search the working tree, the index (--staged), or a specific revision (--rev) for one or more patterns (fixed-string or extended regex, case-insensitive optional). Fast; only tracked content at the chosen tree is searched.HistoryPickaxe— find commits whose diff added or removed a pattern (git log -S/-G), attributed to the specific file. Answers "when was this introduced?" without walking full patches yourself.StreamPatches— streamgit log -pfile diffs with commit, author, and date context, so callers can run arbitrary detectors over diff text in a single git walk.
matches, err := gitgrep.GrepTree(ctx, repoPath, gitgrep.Options{
Patterns: []gitgrep.Pattern{{Value: "Acme Corp", IgnoreCase: true}},
})
All three shell out to native git — the fastest and most portable approach
for repository search, and consistent with how the rest of gogit works.
Match.Text and Patch.Hunk are returned verbatim; redacting them before
display or logging is the caller's responsibility.
New gitscan grep subcommand
gitscan grep -e "Acme Corp" -i ./ # working tree, case-insensitive
gitscan grep -e ExampleCo --staged # index (pre-commit surface)
gitscan grep -e "SECRET-[0-9]+" -E # extended regex
gitscan grep -e "Acme Corp" --history # which commit introduced it
gitscan grep -e ACME --json # machine-readable output
New file/content helpers on Repo
Repo.LsFiles, Repo.StagedFiles, Repo.ShowContent, and Repo.LsTree
enumerate tracked/untracked files, staged changes, and a revision's tree, and
read object content at a git spec (e.g. :path for the staged version of a
file, <rev>:path for a file at a revision) — the building blocks behind
gitgrep and available directly to library consumers.
pending/pushed now show the current branch
gitscan pending/pushed reported "no upstream configured; all local
commits unpushed" without saying which branch that referred to — easy to
misread as unpushed work on the repo's default branch when it was actually a
fresh feature branch. The repo header now includes it
(Repo: <path> (branch: <name>)), and JSON output gains a branch field.
Repo.PendingCommits and Repo.PushedCommits expose it as
PendingResult.Branch / PushedResult.Branch.
pending falls back to the remote's default branch
A branch that has never been pushed under its own name — the common case
right after git checkout -b — previously had no push baseline at all, so
gitscan pending reported every commit reachable from HEAD as pending,
including the entire history inherited from its parent branch. It now falls
back to the remote's default branch (e.g. origin/main) when there is no
upstream and no same-named remote-tracking branch, so only the commits
unique to this branch are reported:
Repo: /path/to/repo (branch: feat/x)
Pending commits (not yet pushed to origin/main): 2
The default branch is resolved via the remote's recorded HEAD
(refs/remotes/<remote>/HEAD, set by a full clone or git remote
set-head) or, failing that, by checking for main then master, since
git push -u does not set the symbolic HEAD ref locally. Repo.
PushedCommits is intentionally unchanged: it reports commits pushed under
this branch's own identity, and inheriting origin/main's history there
would misrepresent commits as "pushed" that this branch never pushed
itself.
Installation
go install github.com/grokify/gogit/cmd/gitscan@v0.11.0
See CHANGELOG.md for the categorized commit list.