-
-
Notifications
You must be signed in to change notification settings - Fork 9
fix: IsIgnored now loads global and system gitignore patterns #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Two issues fixed:
1. go-git's LoadGlobalPatterns() only reads core.excludesfile from
~/.gitconfig, but git also checks the default XDG location
(~/.config/git/ignore) even without core.excludesfile being set.
Added loadXDGGlobalPatterns() fallback for this case.
2. HasChangesOtherThan() had incorrect condition for detecting untracked
files. go-git sets BOTH Staging and Worktree to Untracked ('?') for
untracked files, but the code checked for Staging == Unmodified (' ').
Simplified condition to just check Worktree == Untracked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR improves gitignore handling to better match Git’s behavior and fixes detection of untracked files when checking for other changes before creating a feature branch.
Changes:
- Extend
IsIgnoredto consider local.gitignore, global gitignore (including XDG default~/.config/git/ignore), and system gitignore patterns. - Add an XDG-specific loader
loadXDGGlobalPatternsto compensate for go-git’s lack of default XDG support. - Fix
HasChangesOtherThanto correctly treat untracked files by checkingWorktree == git.Untrackedand consultingIsIgnoredfor them.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } else { | ||
| // fallback to default XDG location if core.excludesfile not set | ||
| // git uses $XDG_CONFIG_HOME/git/ignore (defaults to ~/.config/git/ignore) | ||
| patterns = append(patterns, loadXDGGlobalPatterns()...) |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback to XDG global gitignore currently triggers whenever LoadGlobalPatterns returns no patterns, even when a core.excludesfile may be explicitly configured but its file is empty. Git itself only consults $XDG_CONFIG_HOME/git/ignore when core.excludesfile is unset, so this behavior can cause divergence from git by additionally applying XDG patterns when a user has intentionally configured an empty global excludes file. Consider basing the fallback condition on whether core.excludesfile is present in the global config (e.g., via config.LoadConfig(config.GlobalScope)), and only calling loadXDGGlobalPatterns when no explicit excludes file is configured.
| } else { | |
| // fallback to default XDG location if core.excludesfile not set | |
| // git uses $XDG_CONFIG_HOME/git/ignore (defaults to ~/.config/git/ignore) | |
| patterns = append(patterns, loadXDGGlobalPatterns()...) | |
| } | |
| // fallback to default XDG location only when no explicit core.excludesfile | |
| // is configured in the global git config. Git uses $XDG_CONFIG_HOME/git/ignore | |
| // (defaults to ~/.config/git/ignore) when core.excludesfile is unset. | |
| if globalCfg, err := config.LoadConfig(config.GlobalScope); err != nil { | |
| // If the global config cannot be loaded, treat it as having no | |
| // explicit excludesfile and apply the XDG fallback. | |
| patterns = append(patterns, loadXDGGlobalPatterns()...) | |
| } else { | |
| coreSection := globalCfg.Raw.Section("core") | |
| if coreSection.Option("excludesfile") == "" { | |
| patterns = append(patterns, loadXDGGlobalPatterns()...) | |
| } |
| // loadXDGGlobalPatterns loads gitignore patterns from the default XDG location. | ||
| // Git checks $XDG_CONFIG_HOME/git/ignore, defaulting to ~/.config/git/ignore. | ||
| func loadXDGGlobalPatterns() []gitignore.Pattern { | ||
| // check XDG_CONFIG_HOME first, fall back to ~/.config | ||
| configHome := os.Getenv("XDG_CONFIG_HOME") | ||
| if configHome == "" { |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
loadXDGGlobalPatterns introduces new behavior that is not currently covered by tests, even though IsIgnored already has unit tests in pkg/git/git_test.go. To avoid regressions and environment-dependent behavior, consider adding tests that (1) set XDG_CONFIG_HOME to a temporary directory with a git/ignore file and verify that patterns are parsed correctly, and (2) exercise the XDG fallback path in IsIgnored so that globally-ignored files are validated under test rather than only manually.
|
lgtm, thx. clean fix for the XDG global gitignore fallback. one minor note: |
umputun
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Summary
LoadGlobalPatterns()only reads fromcore.excludesfilein~/.gitconfig, but git also checks~/.config/git/ignoreby defaultHasChangesOtherThan(): go-git sets bothStagingandWorktreetoUntrackedfor untracked files, but the code incorrectly checked forStaging == UnmodifiedProblem
Files ignored via global gitignore (
~/.config/git/ignore) were reported as uncommitted changes, causing "worktree has uncommitted changes" errors when trying to create branches.Test plan
.claude/settings.local.json(ignored via~/.config/git/ignore) is now correctly identified as ignoredHasChangesOtherThan()returnsfalsewhen only globally-gitignored files exist