Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/context/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ uvx dirsql "SELECT path FROM './**'" --format json
### Empty `[]` for files you can see

- **You named a directory**, which lists one level only. `'./**'` and `'./docs/**'` are the recursive forms.
- **The files are gitignored.** `--no-ignore` scans them:
- **The files are gitignored**, inside a git repo (outside one, no `.gitignore` applies). `--no-ignore` scans them:

```sh
uvx dirsql "SELECT path FROM './**'" --format json --no-ignore
Expand Down
2 changes: 1 addition & 1 deletion docs/context/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Every row has `path`, `basename`, `dir`, `ext` (no dot, `NULL` when absent), `si

### What a scan skips

- **`.gitignore` is respected.** Pass `--no-ignore` to scan gitignored files too, or name the ignored directory outright: `'./build'` scans `build/`.
- **`.gitignore` is respected inside a git repo**, as git does; outside one (no enclosing `.git`) no `.gitignore` applies. Pass `--no-ignore` to scan gitignored files too, or name the ignored directory outright: `'./build'` scans `build/`.
- **`node_modules` is skipped** unless the path names it: `'./node_modules/**'`.
- **`'./**'` does not enter `.git`.** Naming it scans it: `'./.git/**'`.
- **To match dotfiles, spell the dot:** `'./.github/**'`, `'./**/.env'`.
Expand Down
20 changes: 13 additions & 7 deletions docs/reference/path-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,21 @@ skipped just like one at the top.

### `.gitignore`

Path-table scans also respect `.gitignore` files by default, the way fd and
ripgrep do: a `.gitignore` anywhere in the tree applies below its own
Path-table scans also respect `.gitignore` files by default, inside a git
repo, the way git, fd and ripgrep do: a `.gitignore` applies below its own
directory, deeper files override shallower ones, `!pattern` re-includes, and
an ignored directory is pruned rather than walked. In a typical repo this
excludes build output, virtualenvs, and caches with zero ceremony. No `.git`
directory is required — a `.gitignore` in any scanned directory counts — and
the built-in defaults above remain as a floor for directories with no
excludes build output, virtualenvs, and caches with zero ceremony. The
built-in defaults above remain as a floor for directories with no
`.gitignore` at all.

A `.gitignore` is in force only when a directory holding `.git` encloses it.
Outside a repo none applies, at the scan's start, above it or below it: a
`~/.claude` whose `.gitignore` is `*` still lists its files when `~/.claude`
is not a repo. Inside one, every `.gitignore` from the repo root down
applies, including those above the directory a scan starts in, so
`'./docs/*.log'` and `'./**/*.log'` agree about `docs/`.

Pass [`--no-ignore`](./cli.md#flags) to restore the full walk — the
determinism switch for scripted use, since results otherwise depend on
`.gitignore` state. It disables only the `.gitignore` respect; the built-in
Expand All @@ -285,8 +291,8 @@ SELECT path FROM './node_modules/*/package.json'; -- scans it anyway
SELECT path FROM './dist'; -- scans dist/ even when gitignored
```

A `.gitignore` at or below the directory the scan starts in still filters
beneath it; one above it is never read.
The `.gitignore` files in force there, including those above it, still
filter what lies beneath it.

### Hidden files

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**Changed** A `.gitignore` applies to path-table scans only inside a git
repo, as in git, fd and ripgrep: one is in force only when a directory
holding `.git` encloses it. Outside a repo none applies, at the scan's start,
above it or below it, so a `~/.claude` whose `.gitignore` is `*` lists its
files. Inside a repo nothing changes. `--no-ignore` is unchanged.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"command": "just test-e2e",
"ran_at": 1791218987,
"exit_code": 0,
"commit": "a433cc9c0cf5c32e3d731625dd63ecd040d9f235",
"branch": "claude/1272-ancestor-gitignore"
}
36 changes: 36 additions & 0 deletions packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### Python SDK: `.gitignore` applies only inside a git repo

#### Summary

Path-tables used to apply `.gitignore` files with no git repo present. Now a
`.gitignore` is in force only when a directory holding `.git` encloses it,
as in git, fd and ripgrep. Every surface that resolves a path-table is
affected: the CLI, the REPL, the HTTP server, the SDKs, and the `--on-file`
form. No call changes. Outside a repo a query can return more rows; inside
one nothing changes.

#### Required changes

_None._

#### Deprecations removed

_None._

#### Behavior changes without code changes

- Outside a git repo, files a `.gitignore` names are listed. To hide them,
add `ignore` patterns in a config file, or run `git init`.

#### Verification

```bash
cd "$(mktemp -d)"
printf '*.log\n' > .gitignore
touch a.md z.log
dirsql query "SELECT path FROM './*' ORDER BY path"
# expected: [{"path":"a.md"},{"path":"z.log"}]
git init -q
dirsql query "SELECT path FROM './*' ORDER BY path"
# expected: [{"path":"a.md"}]
```
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

@pytest.fixture
def gitignored_dir(tmp_path):
(tmp_path / ".git").mkdir()
(tmp_path / ".gitignore").write_text("ignored.md\n", encoding="utf-8")
(tmp_path / "kept.md").write_text("kept", encoding="utf-8")
(tmp_path / "ignored.md").write_text("ignored", encoding="utf-8")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**Changed** A `.gitignore` applies to path-table scans only inside a git
repo, as in git, fd and ripgrep: one is in force only when a directory
holding `.git` encloses it. Outside a repo none applies, at the scan's start,
above it or below it, so a `~/.claude` whose `.gitignore` is `*` lists its
files. Inside a repo nothing changes. `--no-ignore` is unchanged.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
**Fixed** Inside a git repo, a path-table scan applies the `.gitignore` files
above the directory it starts in, as git does: every one from the repo root
(the nearest directory holding `.git`) down. `'./docs/*.log'` now hides what a
root `*.log` rule ignores, as `'./**'` already did, and an index root inside a
repo honors the repo root's `.gitignore`. Naming a gitignored directory
(`'./dist'`) still scans it.
36 changes: 36 additions & 0 deletions packages/rust/migrations.d/2026-10-05-gitignore-requires-repo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### Core: `.gitignore` applies only inside a git repo

#### Summary

Path-tables used to apply `.gitignore` files with no git repo present. Now a
`.gitignore` is in force only when a directory holding `.git` encloses it,
as in git, fd and ripgrep. Every surface that resolves a path-table is
affected: the CLI, the REPL, the HTTP server, the SDKs, and the `--on-file`
form. No call changes. Outside a repo a query can return more rows; inside
one nothing changes.

#### Required changes

_None._

#### Deprecations removed

_None._

#### Behavior changes without code changes

- Outside a git repo, files a `.gitignore` names are listed. To hide them,
add `ignore` patterns in a config file, or run `git init`.

#### Verification

```bash
cd "$(mktemp -d)"
printf '*.log\n' > .gitignore
touch a.md z.log
dirsql query "SELECT path FROM './*' ORDER BY path"
# expected: [{"path":"a.md"},{"path":"z.log"}]
git init -q
dirsql query "SELECT path FROM './*' ORDER BY path"
# expected: [{"path":"a.md"}]
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
### Core: path-tables apply `.gitignore` files above the scan start

#### Summary

A path-table scan used to read only the `.gitignore` files at or below the
directory it starts in, so `'./docs/*.log'` listed files a root `*.log` rule
hides from `'./**'`. Inside a git repo it now reads every `.gitignore` from the
repo root (the nearest directory holding `.git`) down to that directory. Every
surface that resolves a path-table is affected: the CLI, the REPL, the HTTP
server, the SDKs, and the `--on-file` form. No call changes; a query can return fewer rows. `--no-ignore` restores
the old listing.

#### Required changes

_None._

#### Deprecations removed

_None._

#### Behavior changes without code changes

- `'./docs/*.log'` no longer lists `docs/z.log` when a root `.gitignore`
ignores `*.log`.
- Run from a subdirectory of a repo, path-tables honor the `.gitignore` files
between the repo root and that subdirectory.

#### Verification

```bash
cd "$(mktemp -d)"
git init -q
mkdir docs
printf '*.log\n' > .gitignore
touch docs/a.md docs/z.log
dirsql query "SELECT path FROM './docs/*' ORDER BY path"
# expected: [{"path":"docs/a.md"}]
```
Loading
Loading