Skip to content

Tree view hides files re-included by ! negation when a parent glob in a global gitignore excludes them #1606

Description

@smithtim

Thanks in advance for your bug report!

  • Have you reproduced issue in safe mode?
  • Have you used the debugging guide to try to resolve the issue?
  • Have you checked our FAQs to make sure your question isn't answered there?
  • Have you checked to make sure your issue does not already exist?
  • Have you checked you are on the latest release of Pulsar?

What happened?

Pulsar's tree view hides files that are re-included by a ! negation in .gitignore when a parent glob in the global gitignore (~/.config/git/ignore) excludes them. Git itself honors the negation correctly (git check-ignore and git status --ignored both report the re-included path as not ignored), but the tree view treats it as ignored anyway and hides it.

Expected: the un-ignored directory appears in the tree.

Actual: the parent directory shows as empty. Enabling Tree View → Toggle VCS Ignored Files reveals it, but that also reveals every other truly-ignored file in the repo, which defeats the purpose.

This blocks a common pattern: globally ignoring a per-user tooling directory (.claude/, .vscode/, .idea/) while re-including a subset (skills/, settings.json, etc.) via a repo-local negation.

Related archived Atom issues (same bug, never fixed, never migrated):

Pulsar version

1.132.1

Which OS does this happen on?

🍎 macOS

OS details

Tahoe 26.5.1

Which CPU architecture are you running this on?

None

What steps are needed to reproduce this?

  1. Add this to your global gitignore (~/.config/git/ignore or wherever git config --global core.excludesfile points):

    /.claude/*
    
  2. In a git repo, create .gitignore with:

    .DS_Store
    !.claude/skills/
    
  3. Create the following contents in the repo:

    .claude/
    ├── .DS_Store
    ├── scheduled_tasks.json
    ├── scheduled_tasks.lock
    └── skills/
        ├── skill-a/
        │   └── SKILL.md
        └── skill-b/
            └── SKILL.md
    
  4. Confirm git honors the negation:

    $ git check-ignore -v .claude/skills
    (exits 1 with no output — not ignored)
    
    $ git status --ignored --short
    !! .DS_Store
    !! .claude/.DS_Store
    !! .claude/scheduled_tasks.json
    !! .claude/scheduled_tasks.lock
    

    Note that .claude/skills/ is absent from the ignored list.

  5. Open the repo in Pulsar. Look at the tree view.

Observed: .claude/ appears in the tree but its skills/ child (and everything else under .claude/) is hidden.

Workaround: Command Palette → Tree View: Toggle VCS Ignored Files — this reveals skills/, but also every other truly-ignored file.

Additional Information:

Impact

Users can't see re-included subdirectories in the tree view without also revealing everything else that's git-ignored. This is a common pattern for tooling directories (.claude/, .vscode/, .idea/, etc.) where users globally ignore per-user cruft but want to share a subset of tracked files. The workaround (toggling Hide VCS Ignored Files) is not a real fix because it defeats the whole point of hiding ignored files.

Likely cause

Pulsar (like Atom before it) appears to walk .gitignore files itself rather than delegating to git check-ignore, and its own parser doesn't correctly implement the "negation re-includes a path even if a parent glob excluded it" semantics that git uses. This same bug affected the Atom fuzzy-finder for the same reason (atom/fuzzy-finder#65).

Suggested fix

Ideally, use git check-ignore (or libgit2's equivalent) as the source of truth for "is this path ignored?", rather than reimplementing gitignore semantics. That way any git-compatibility bugs get fixed once, upstream.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions