gogit v0.12.0 Release Notes
Release Date: 2026-09-26
Overview
This release adds exposure queries to Repo: four methods that answer
how far a commit or file has travelled. Finding a problem in a repository
(a leaked credential, a file that should never have been committed) is only
half the work — the next question is what that finding reaches. Has the
commit been pushed? Is it in a tagged release? Does the file still exist
anywhere in history, or only on this machine? Each of these previously took
several ad-hoc git commands; they are now single calls. Like gitgrep, the
queries are policy-free: they report facts about refs, trees, and history,
and leave judging severity to the caller. No breaking changes.
Highlights
Which refs contain a commit
Repo.RefsContaining lists the local branches, remote-tracking branches,
and tags whose history contains a commit:
refs, err := repo.RefsContaining(ctx, "a1b2c3d")
for _, ref := range refs {
fmt.Println(ref.Kind, ref.Name) // branch main / remote origin/main / tag v1.2.0
}
A remote ref means the commit had reached that remote as of the last
fetch; a tag ref means it is part of that release's history. Symbolic
refs such as origin/HEAD are omitted, since they duplicate the branch
they point to. An unknown commit is an error rather than an empty result,
so a typo can never read as "not pushed anywhere."
Which tagged releases shipped a path
Repo.TagsWithPath lists the tags whose tree contains a file or directory:
tags, err := repo.TagsWithPath(ctx, "config/local.env")
if len(tags) == 0 {
// in history only — never part of a tagged release tree
}
This separates two cases that RefsContaining alone cannot: a tag can sit
downstream of the commit that added a file without containing that file,
because a later commit deleted it before the tag was cut. For a Go module
the difference matters — the tagged tree is what proxy.golang.org
archives permanently, while content that only exists in commit history is
not part of any module zip. All tags are checked in one
git cat-file --batch-check call, so repositories with hundreds of tags
cost one process, not hundreds.
Every path ever added
Repo.FilesEverAdded lists every path added by any commit on any ref,
sorted and de-duplicated — including files since deleted from HEAD, and
files that only exist on unmerged branches. Renames are reported under the
new path as well. This surfaces content that is invisible in the current
tree but still retrievable from history.
Ignored local files
Repo.IgnoredFiles lists untracked paths excluded by .gitignore,
.git/info/exclude, or the global excludes file. A directory ignored in
full is reported once as dir/ rather than file by file. Ignored paths are
where local credentials and build output usually live, and they are what a
forced git add -f could still commit.
Upgrade Notes
The new methods are additive. The internal git() runner gained a
gitStdin variant for batch commands that read queries from standard
input; existing behavior is unchanged.
Installation
go get github.com/grokify/gogit@v0.12.0
go install github.com/grokify/gogit/cmd/gitscan@v0.12.0
See CHANGELOG.md for the categorized commit list.