Skip to content

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.