code-go-git
Installation
SKILL.md
code-go-git
Idiomatic review checklist for go-git v5 concurrent access patterns.
MUST FIX
- [SAFETY]
*git.Repositoryis NOT goroutine-safe — a per-reposync.Mutex(notsync.RWMutex) is required for all access. Issue #773 is open as of v5.18. - [SAFETY] The packfile
MemoryIndexhas a confirmed concurrent-map crash (fatal error: concurrent map read and map write) triggered by concurrentrepo.Log()/CommitObjecton the same repo. Issue #1121, June 2024, unfixed in v5.x. - [SAFETY]
repo.Log(),CommitObject(), and all iterator types are NOT safe to call concurrently on the same*git.Repository. - [CONCURRENCY]
repo.Worktree()/wt.Status()wraps the same underlying object storage — calling concurrently on the same repo is unsafe. - [CONCURRENCY] The per-repo mutex must cover the full iterator lifetime, not just the initial API call. Iterators lazily read from shared object storage on each
Next()— releasing the lock between obtaining an iterator and exhausting it is a data race. - [CONCURRENCY]
sync.RWMutexdoes NOT help — go-git "read" operations mutate internal maps (object cache, MemoryIndex). Usesync.Mutexonly. - [SAFETY] v5.17.0 added extension validation:
git.PlainOpennow returns errors for repos with unsupported extensions. Errors fromPlainOpenmust propagate; never store a nil repo. - [ANTI-PATTERN] Never cache a
CommitIterorObjectIteracross calls — iterators hold internal cursor state over shared storage. Create and fully drain within one mutex-protected window. - [ANTI-PATTERN] Never cache a
*Worktreein a long-lived struct — it holds a snapshot of the HEAD/filesystem state and becomes stale aftergit fetchor index changes. - [ANTI-PATTERN] Never call
git.PlainOpenwhile holding the per-repo mutex —PlainOpenreads.git/config,HEAD, and packed-refs from disk (I/O-bound). Open outside the lock, then store viasync.Map.LoadOrStore. - [CONCURRENCY] Concurrency fixes for
CommitObjects().Foreach()and related iterators are v6-exp only and NOT backported to v5. There is no "safe subset" of go-git v5 that is natively goroutine-safe for shared-repo reads.