Skip to content

Exclude .git when a directory has no .gitignore - #48

Merged
sabbaticas merged 1 commit into
mainfrom
fix/exclude-git-dir-without-gitignore
Oct 11, 2026
Merged

sabbaticas merged 1 commit into
mainfrom
fix/exclude-git-dir-without-gitignore

Conversation

@sabbaticas

Copy link
Copy Markdown
Contributor

Closes #1.

Summary

  • A directory with no .gitignore no longer has its .git directory scanned.
  • The four built-in exclusions (.git, .jekyll-cache, .ruff_cache, .DS_Store) now apply whether or not a .gitignore exists.
  • -all-files and load_gitignore_patterns() are unchanged.

The cause

The built-in exclusions were appended to the patterns read from .gitignore. With no .gitignore there was no matcher at all, so nothing was excluded:

  • panopticas assess and panopticas urls listed Git's internal files.
  • panopticas ai could report a file inside .git as an AI artifact.
  • identify_files() returned those files to callers.

Decision

Issue #1 asked for a decision between three options:

  • Exclude .git by default — yes. It is never repository content.
  • A switch to turn filtering off — already exists. -all-files (all_files=True) disables all filtering and still shows .git.
  • Apply all four exclusions, not just .git. A directory with no .gitignore now behaves exactly like one with an empty .gitignore; the two differing was the bug.

Changes

  • ALWAYS_IGNORED holds the four built-in patterns.
  • _scan_spec(directory) returns the .gitignore matcher, or a matcher of ALWAYS_IGNORED alone when there is no .gitignore.
  • identify_files(), identify_files_with_metrics(), find_files() and find_ai_files() use it.
  • load_gitignore_patterns() is public and documented as returning None with no .gitignore. That contract is kept; the fallback lives in the private helper.

Effect

Across 167 cloned repositories, six have no root .gitignore. Files under .git/ scanned went from 308 to 0, with no other difference in the files selected.

kospex: no change to its file inventory. get_repo_files() already skips .git paths itself. Because kospex takes its file list from identify_files(), a committed .DS_Store in a repository without a .gitignore would previously have been inventoried and no longer is — the same as already happens in repositories that have a .gitignore.

Not changed

Testing

  • pytest: 774 passed. TestScanWithoutGitignore builds a repository with a .git directory and no .gitignore; five of its six tests failed before the change, and the sixth pins the unchanged all_files behaviour.
  • panopticas assess on a fresh git init directory lists only the working files.

🤖 Generated with Claude Code

The built-in exclusions (.git, .jekyll-cache, .ruff_cache, .DS_Store)
were appended to the patterns read from .gitignore, so a directory
without one got no filter at all and the contents of .git were scanned.
panopticas assess and urls listed Git's internal files, and panopticas
ai could report a file inside .git as an AI artifact.

The exclusions now apply whether or not a .gitignore exists, in all four
functions that walk a directory. A directory with no .gitignore behaves
exactly like one with an empty .gitignore.

all_files still turns all filtering off, and load_gitignore_patterns()
still returns None when there is no .gitignore.

Closes #1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sabbaticas
sabbaticas merged commit 40f77c7 into main Oct 11, 2026
5 checks passed
@sabbaticas
sabbaticas deleted the fix/exclude-git-dir-without-gitignore branch October 11, 2026 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.git files listed in assess function when there is no .gitignore

1 participant