From 04a0d5cb76579e96c0b7e5484639c6542cb44147 Mon Sep 17 00:00:00 2001 From: Andy Li <1450947+andy1li@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:19:44 +0900 Subject: [PATCH 1/3] Enhance GitIgnore functionality to ensure the .git directory is never skipped. This change improves the handling of ignored files by explicitly allowing the .git directory, even if specified in .gitignore files. --- internal/utils/git_ignore.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/utils/git_ignore.go b/internal/utils/git_ignore.go index 5eccd95..066bbdb 100644 --- a/internal/utils/git_ignore.go +++ b/internal/utils/git_ignore.go @@ -27,6 +27,11 @@ func NewGitIgnore(baseDir string) GitIgnore { } func (i GitIgnore) SkipFile(path string) (bool, error) { + // Never skip the .git directory, even if it's in the .gitignore files. + if path == ".git" { + return false, nil + } + for _, ignorer := range []*ignore.GitIgnore{i.localGitIgnore, i.globalGitIgnore, i.gitInfoExclude} { if ignorer != nil && ignorer.MatchesPath(path) { return true, nil From b7bb2e2771022004c52d17cfca8e5232ed935b66 Mon Sep 17 00:00:00 2001 From: Andy Li <1450947+andy1li@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:36:27 +0900 Subject: [PATCH 2/3] Enhance GitIgnore logic to prevent skipping the .git directory and its contents. This update ensures that any files within the .git directory are treated correctly, improving the handling of ignored files in version control. --- internal/utils/git_ignore.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/utils/git_ignore.go b/internal/utils/git_ignore.go index 066bbdb..0c5f2eb 100644 --- a/internal/utils/git_ignore.go +++ b/internal/utils/git_ignore.go @@ -27,8 +27,8 @@ func NewGitIgnore(baseDir string) GitIgnore { } func (i GitIgnore) SkipFile(path string) (bool, error) { - // Never skip the .git directory, even if it's in the .gitignore files. - if path == ".git" { + // Never skip the .git directory or files inside it, even if matched by .gitignore patterns. + if path == ".git" || strings.HasPrefix(path, ".git/") || strings.HasPrefix(path, ".git\\") { return false, nil } From c779eccef106d0e432553ed495583cbc6a487ce8 Mon Sep 17 00:00:00 2001 From: Andy Li <1450947+andy1li@users.noreply.github.com> Date: Fri, 20 Feb 2026 17:37:54 +0900 Subject: [PATCH 3/3] Enhance GitIgnore tests to verify that the .git directory and its contents are not skipped. Added new test cases to ensure proper handling of paths related to the .git directory, reinforcing the logic implemented in the GitIgnore functionality. --- internal/utils/git_ignore.go | 5 ++++- internal/utils/git_ignore_test.go | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/internal/utils/git_ignore.go b/internal/utils/git_ignore.go index 0c5f2eb..4902e86 100644 --- a/internal/utils/git_ignore.go +++ b/internal/utils/git_ignore.go @@ -28,7 +28,10 @@ func NewGitIgnore(baseDir string) GitIgnore { func (i GitIgnore) SkipFile(path string) (bool, error) { // Never skip the .git directory or files inside it, even if matched by .gitignore patterns. - if path == ".git" || strings.HasPrefix(path, ".git/") || strings.HasPrefix(path, ".git\\") { + if path == ".git" || + strings.HasPrefix(path, ".git/") || + strings.HasSuffix(path, "/.git") || + strings.Contains(path, "/.git/") { return false, nil } diff --git a/internal/utils/git_ignore_test.go b/internal/utils/git_ignore_test.go index febc8bc..a1f3635 100644 --- a/internal/utils/git_ignore_test.go +++ b/internal/utils/git_ignore_test.go @@ -47,6 +47,28 @@ func TestGitIgnore(t *testing.T) { assertFileSkipped(t, &gitIgnore, "ignore/this/file.txt") assertFileNotSkipped(t, &gitIgnore, "some/other/file.txt") }) + + t.Run("never skip .git directory or files inside it", func(t *testing.T) { + tmpRepoDir := t.TempDir() + writeFile(t, filepath.Join(tmpRepoDir, ".gitignore"), ".git\n.git/*\n") // would match .git if we didn't special-case it + gitIgnore := NewGitIgnore(tmpRepoDir) + + pathsThatMustNotBeSkipped := []string{ + ".git", + ".git/HEAD", + ".git/config", + ".git/refs/heads/main", + "/Users/example/repo/.git", + "repo/.git", + "subdir/repo/.git/refs", + } + for _, path := range pathsThatMustNotBeSkipped { + path := path + t.Run(path, func(t *testing.T) { + assertFileNotSkipped(t, &gitIgnore, path) + }) + } + }) } func assertFileSkipped(t *testing.T, gitIgnore *GitIgnore, path string) {