Repository navigation
Releases: linkwithjoydeep/go-dotignore
Release list
v2.3.0
v2.3.0 - 2026-08-30
Added
- Feature:
RepositoryMatcher.Walk(fn WalkFunc) error, an ignore-aware directory traversal.- Mirrors
filepath.WalkDir's callback shape (fs.SkipDir/fs.SkipAllcontrol flow, filesystem errors delivered via theerrparameter). - Adds an
ignored boolreporting whether each entry is excluded by.gitignorerules orRepositoryConfig.SkipFolders. - A directory excluded either way is reported once with
ignored=trueand never descended into. - Honors the same
MaxDepthandFollowSymlinkssettings theRepositoryMatcherwas constructed with.
- Mirrors
Performance
- Removed all hot-path allocations from
PatternMatchermatching: 34184 ns/op, 3762 B/op, 148 allocs/op → 25317 ns/op, 0 B/op, 0 allocs/op. - Removed hot-path allocations from
RepositoryMatcher.Matches: 48 allocs/op, 3065 B/op → 21 allocs/op, 2044 B/op.
Changed
- Corrected
doc.go's Performance section, which claimed "no allocations during regex matching" before that was actually true.
Source
- Commits:
618c474..7493de0
v2.2.0
v2.2.0 - 2026-05-03
Added
- Feature (#6):
RepositoryConfig.SkipFoldersto skip selected directories while discovering nested ignore files. - Internal
Contains()helper used by repository traversal skip checks. - Godoc coverage for
Contains().
Changed
- Dropped
slicesdependency usage for skip-folder checks in repository scanning path.
Credits
- Thanks to @Marcel2603 for PR #6.
Source
- Commit:
fe7feef51cd11cd936088946265aeee8d7230c49 - Title:
feat(repository-matcher): Add skipfolders, to skip scanning these folders (#6)
v2.1.0 - Hierarchical .gitignore Support
Release v2.1.0 - Hierarchical .gitignore Support
Release Date: 2026-02-09
🎉 What's New
Nested .gitignore Support (Issue #4)
The most requested feature is finally here! go-dotignore now supports hierarchical .gitignore matching for real-world repositories with nested .gitignore files - just like Git does!
The Problem
Previously, go-dotignore (like go-gitignore) could only process a single .gitignore file. This made it impractical for real-world repositories, especially monorepos, where different subdirectories have their own .gitignore files.
The Solution
New RepositoryMatcher API that:
- ✅ Automatically discovers all .gitignore files in your repository
- ✅ Applies patterns hierarchically (parent → child)
- ✅ Supports pattern overrides via negation
- ✅ Mirrors Git's exact behavior
Quick Example
// Before: Only single file support
matcher, err := dotignore.NewPatternMatcherFromFile(".gitignore")
// After: Full repository support with nested .gitignore files
matcher, err := dotignore.NewRepositoryMatcher("/path/to/repo")
// Automatically handles:
// - .gitignore (root)
// - frontend/.gitignore
// - backend/.gitignore
// - docs/.gitignore
// And applies them correctly, just like Git!
ignored, err := matcher.Matches("frontend/node_modules/package.json")📦 New API
RepositoryMatcher
type RepositoryMatcher struct { ... }
// Create a new repository matcher
func NewRepositoryMatcher(rootDir string) (*RepositoryMatcher, error)
// Create with custom configuration
func NewRepositoryMatcherWithConfig(rootDir string, config *RepositoryConfig) (*RepositoryMatcher, error)
// Check if a file should be ignored
func (rm *RepositoryMatcher) Matches(path string) (bool, error)
// Helper methods
func (rm *RepositoryMatcher) RootDir() string
func (rm *RepositoryMatcher) IgnoreFileCount() int
func (rm *RepositoryMatcher) IgnoreFilePaths() []stringRepositoryConfig
type RepositoryConfig struct {
IgnoreFileName string // Default: ".gitignore"
MaxDepth int // Default: 0 (unlimited)
FollowSymlinks bool // Default: false
}🏗️ Use Cases
Perfect for:
- Monorepo projects with multiple subprojects
- Build tools that need to respect .gitignore rules
- File walkers and code analyzers
- Git-aware tools and utilities
- Migration from go-gitignore (drop-in replacement + more features)
📊 Real-World Example: Monorepo
// Repository structure:
// project/
// .gitignore # Global: *.log, .env, .DS_Store
// frontend/
// .gitignore # Frontend: node_modules/, dist/, .cache/
// node_modules/ # ← Ignored by frontend/.gitignore
// src/ # ← Not ignored
// backend/
// .gitignore # Backend: target/, *.class, logs/
// target/ # ← Ignored by backend/.gitignore
// src/ # ← Not ignored
// docs/
// .gitignore # Docs: _build/, *.pyc
// _build/ # ← Ignored by docs/.gitignore
matcher, err := dotignore.NewRepositoryMatcher("/path/to/project")
// Global patterns apply everywhere
matcher.Matches("app.log") // true (root .gitignore)
matcher.Matches("frontend/debug.log") // true (root .gitignore)
matcher.Matches(".DS_Store") // true (root .gitignore)
// Subproject-specific patterns
matcher.Matches("frontend/node_modules/...") // true (frontend/.gitignore)
matcher.Matches("backend/target/...") // true (backend/.gitignore)
matcher.Matches("docs/_build/...") // true (docs/.gitignore)
// Source files are NOT ignored
matcher.Matches("frontend/src/App.js") // false
matcher.Matches("backend/src/Main.java") // false
matcher.Matches("docs/index.rst") // false🔄 Pattern Override Example
Child .gitignore files can override parent patterns:
// project/
// .gitignore # *.txt (ignore all .txt files)
// important/
// .gitignore # !critical.txt (but keep this one)
matcher.Matches("file.txt") // true (ignored by root)
matcher.Matches("important/file.txt") // true (still ignored)
matcher.Matches("important/critical.txt") // false (un-ignored by child!)⚙️ Configuration
config := &dotignore.RepositoryConfig{
IgnoreFileName: ".ignore", // Use custom ignore file names
MaxDepth: 5, // Only search 5 levels deep
FollowSymlinks: false, // Don't follow symbolic links
}
matcher, err := dotignore.NewRepositoryMatcherWithConfig("/path/to/repo", config)
fmt.Printf("Found %d ignore files\n", matcher.IgnoreFileCount())
// Get list of all loaded ignore files
for _, path := range matcher.IgnoreFilePaths() {
fmt.Printf("Loaded: %s\n", path)
}📈 Comparison with Other Libraries
vs. go-gitignore
| Feature | go-dotignore v2.1+ | go-gitignore |
|---|---|---|
| Nested .gitignore support | ✅ Yes | ❌ No |
| Root-relative patterns | ✅ Fully compliant | |
| Negation patterns | ✅ Full support | |
| Escaped negation | ✅ Yes | ❌ No |
| Active maintenance | ✅ Yes | |
| Full gitignore spec | ✅ v2.0+ compliant |
go-dotignore is now a complete, drop-in replacement for go-gitignore with significantly more features!
🧪 Testing
Comprehensive test suite with 15+ new test cases:
- ✅ Simple hierarchy matching
- ✅ Pattern negation across levels
- ✅ Monorepo scenarios (frontend/backend/docs)
- ✅ Pattern override with negation
- ✅ Root-relative patterns in nested files
- ✅ Absolute path handling
- ✅ Configuration options (MaxDepth, custom file names)
- ✅ Edge cases and error handling
All tests passing!
📚 Documentation
- ✅ Updated README with nested .gitignore section
- ✅ Comparison table with go-gitignore
- ✅ Migration guide from go-gitignore
- ✅ Example code and usage patterns
- ✅ Detailed API documentation
🚀 Installation
go get github.com/codeglyph/go-dotignore/v2@v2.1.0Or update your go.mod:
require github.com/codeglyph/go-dotignore/v2 v2.1.0🔧 Migration from go-gitignore
// Old (go-gitignore) - single file only
gitignore, err := ignore.CompileIgnoreFile(".gitignore")
if gitignore.MatchesPath("file.txt") {
// file is ignored
}
// New (go-dotignore) - single file
matcher, err := dotignore.NewPatternMatcherFromFile(".gitignore")
if ignored, _ := matcher.Matches("file.txt"); ignored {
// file is ignored
}
// New (go-dotignore) - nested files (NEW!)
matcher, err := dotignore.NewRepositoryMatcher("/path/to/repo")
if ignored, _ := matcher.Matches("frontend/node_modules/pkg.json"); ignored {
// file is ignored
}⚡ Performance
- No performance regression for single-file usage (
PatternMatcher) - Efficient pattern caching per directory level
- Lazy evaluation of patterns
- Minimal memory overhead
🎯 What's Next?
This release completes the core feature set for hierarchical gitignore support. Future releases will focus on:
- Performance optimizations
- Additional pattern syntax features
- Community-requested enhancements
📝 Full Changelog
See CHANGELOG.md for complete details.
🙏 Acknowledgments
Thanks to the community for requesting this feature and providing valuable feedback!
Special mention to the Reddit discussion that highlighted the need for nested .gitignore support in Go libraries.
Upgrading? This is a minor version bump with no breaking changes. Simply update your dependency and start using RepositoryMatcher for repositories with nested .gitignore files!
v2.0.1 - Correct Module Path for Go v2+
v2.0.1 - Correct Module Path for Go v2+
🎯 Important Update
This release corrects the module path to include the /v2 suffix as required by Go's semantic import versioning specification.
📦 Installation
go get github.com/codeglyph/go-dotignore/v2@latest📝 Import Statement
import "github.com/codeglyph/go-dotignore/v2"✨ Features (from v2.0.0)
All v2.0.0 features and bug fixes are included:
- ✅ Root-relative patterns work correctly (Issue #5)
- ✅ Fixed substring matching bug
- ✅ Added escaped negation support
- ✅ Full gitignore specification compliance
🔄 Migration from v1.x
Update import path:
// Before:
import "github.com/codeglyph/go-dotignore"
// After:
import "github.com/codeglyph/go-dotignore/v2"Update go.mod:
go get github.com/codeglyph/go-dotignore/v2@latest📖 Documentation
🙏 Thank You
Thanks to all users for adopting this library! Your feedback has been invaluable.
v2.0.0 - Full gitignore Specification Support
v2.0.0 - Full gitignore Specification Support
🎉 Major Update
This release fixes three critical bugs and adds full support for root-relative patterns, achieving complete gitignore specification compliance!
🐛 Critical Bug Fixes
1. Root-Relative Patterns Now Work! (Issue #5) ⭐
Finally! Patterns starting with / now correctly match only at the repository root.
// Pattern: /build/
matcher.Matches("build/") // ✅ true (root level)
matcher.Matches("src/build/") // ✅ false (not at root)
// Pattern: logs/ (no slash - matches anywhere)
matcher.Matches("logs/") // ✅ true
matcher.Matches("src/logs/") // ✅ trueBefore: /build/ didn't match anything ❌
After: /build/ matches only root-level build/ ✅
2. Fixed Substring Matching Bug
Pattern src/test no longer incorrectly matches mysrc/test or src/test2.
3. Added Escaped Negation Support
Pattern \!important.txt now matches files literally named !important.txt.
✨ What's New
- Root-relative patterns:
/patternmatches only at root - Full gitignore spec compliance: All standard gitignore features now work
- 14 new tests: Unicode, deep paths, wildcards, and edge cases
- 61 total tests (was 47) - all passing ✅
📊 Testing Improvements
- ✅ Unicode support: Japanese, Russian, Emoji filenames
- ✅ Deep paths: 100+ directory levels tested
- ✅ Long patterns: 1000+ characters tested
- ✅ No race conditions detected
- ✅ No performance regressions (~34µs per match)
🔄 Migration
Most users: No changes needed! The bugs are fixed and features now work correctly.
If you worked around Issue #5:
// BEFORE (workaround):
patterns := []string{
"mydir/",
"!example/mydir/", // Had to manually exclude
}
// AFTER (proper solution):
patterns := []string{
"/mydir/", // Automatically matches only at root
}📦 Installation
go get github.com/codeglyph/go-dotignore@v2.0.0🎯 Why v2.0.0?
- Major new feature: root-relative pattern support
- Three critical bug fixes that change behavior
- Full gitignore specification compliance
- Users with workarounds may need minor updates
⚡ Performance
No regressions:
- ~34µs per match operation
- Thread-safe, production-ready
- Same memory footprint
📋 Full Details
See RELEASE_NOTES_v2.0.0.md for complete changelog, migration guide, and test script.
Closes: #5
v1.1.1
Summary
Comprehensive overhaul of the go-dotignore library with significant bug fixes,
performance improvements, and enhanced cross-platform compatibility.
Key Changes
🐛 Bug Fixes
- Fix inefficient pattern matching logic that was calling both filepath.Match and regex
- Fix Windows path handling - backslashes now properly converted to forward slashes
- Fix directory pattern matching (patterns ending with /)
- Fix regex building for character classes and escaped characters
- Fix parent directory matching logic that was overly complex and buggy
- Fix UTF-8 BOM handling in file reading
⚡ Performance Improvements
- Pre-compile regex patterns during initialization instead of repeated compilation
- Optimize pattern matching from O(n*m) to O(n) complexity in many cases
- Streamline matching logic with clear separation of concerns
🔧 Architecture Improvements
- Restructure matching logic with focused, single-purpose functions
- Add comprehensive input validation with descriptive error messages
- Enhance error handling throughout with proper error wrapping
- Improve path normalization for consistent cross-platform behavior
✅ Testing Enhancements
- Expand test coverage from 11 to 25+ test functions
- Add edge case testing (empty patterns, nil readers, malformed paths)
- Add performance benchmarks
- Add cross-platform path testing
- Add comprehensive error condition testing
- Fix all existing test issues and add new test scenarios
📚 Documentation
- Improve README with better examples and comprehensive usage patterns
- Add detailed godoc comments throughout
- Add real-world usage examples in tests
- Document performance characteristics and best practices
API Compatibility
- ✅ Maintains full backward compatibility
- ✅ No breaking changes to public API
- ✅ Enhanced error messages provide better debugging information
Platform Support
- ✅ Windows: Full support for backslash path separators
- ✅ macOS/Linux: Consistent forward slash handling
- ✅ Cross-platform: Automatic path normalization
Pattern Support Improvements
- ✅ Enhanced wildcard support (
*,?,**) - ✅ Proper character class handling (
[a-z]) - ✅ Correct escaped character handling (
\*,\?) - ✅ Robust directory pattern support (
dir/) - ✅ Complex negation pattern handling (
!pattern)
Breaking Changes
None - all changes are backward compatible.
Migration Guide
No migration required. Existing code will work unchanged with improved reliability.
v1.0.2
v1.0.1
Full Changelog: v1.0.0...v1.0.1
fix: negation patterns not working
doc: add examples and go docs
v1.0.0
Full Changelog: https://github.com/codeglyph/go-dotignore/commits/v1.0.0