# .cbmignore Precedence Over .gitignore in DeusData: 5-Layer Indexing Hierarchy Explained

> Understand .cbmignore precedence over .gitignore in DeusData. Discover the 5-layer indexing hierarchy and how ignore rules apply to your codebase memory.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: how-to-guide
- Published: 2026-07-24

---

**In DeusData, `.cbmignore` is evaluated after the repository `.gitignore`, meaning repository ignore rules always take priority over project-specific patterns, with negations only able to rescue files from global Git excludes.**

The DeusData indexing engine, implemented in the `DeusData/codebase-memory-mcp` repository, uses a layered ignore system to determine which files enter the codebase memory. Understanding the exact precedence of `.cbmignore` over `.gitignore` is critical for configuring what gets indexed without accidentally overriding your version control rules.

## The Five-Layer Ignore Hierarchy

DeusData evaluates ignore rules in a strict sequence from highest to lowest priority. When a path matches multiple patterns, the first layer to reject it wins.

The precedence order is:

1. **Built-in skip list** – Hard-coded directories such as `.git`, `node_modules`, `dist`, and `target` that cannot be overridden by any configuration file.
2. **Repository-wide `.gitignore`** – The file at the repository root (`<repo>/.gitignore`) combined with Git’s `info/exclude`. Later patterns in this file override earlier ones on conflict.
3. **Nested `.gitignore` files** – Any `.gitignore` found in subdirectories, applied relative to their containing directory.
4. **`.cbmignore`** – The project-specific ignore file at the repository root (`<repo>/.cbmignore`). Positive matches skip paths, while negated patterns (`!`) can only rescue paths from the next layer (global Git excludes).
5. **Git global excludes** – The file referenced by `core.excludesfile` (typically `~/.config/git/ignore`).

In the implementation at [`src/discover/discover.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/discover/discover.c), the discovery walker applies each layer sequentially during the tree traversal [lines 64-84]. According to the `.cbmignore` documentation in [`docs/cbmignore.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/cbmignore.md), this ordering ensures repository-wide `.gitignore` rules maintain higher authority than `.cbmignore` rules [lines 66-84].

## How .cbmignore Interacts with .gitignore

Because `.cbmignore` occupies layer 4 while repository `.gitignore` sits at layer 2, **you cannot use `.cbmignore` to override a file ignored by `.gitignore`**.

Positive patterns in `.cbmignore` (e.g., `*.pb.go`) add exclusions beyond what `.gitignore` defines. However, negated patterns (`!pattern`) function differently depending on what excluded the file:

- **Rescuing from global excludes**: A negation like `!important.sql` can re-include a file that would otherwise be excluded by the global Git excludes (layer 5).
- **No effect on repository ignores**: The same negation cannot rescue a file excluded by the root `.gitignore` or nested `.gitignore` files (layers 2 and 3).

This behavior is documented in the README under the "Ignoring Files" section, which describes the layered evaluation strategy [lines 16-20].

## Practical Configuration Examples

### Example 1: Repository .gitignore Rules

```text

# .gitignore at repository root

/build/
*.log

```

Files under `build/` and any `*.log` file are ignored during indexing before `.cbmignore` is even evaluated.

### Example 2: Project-Specific .cbmignore

```text

# .cbmignore at repository root

# Skip generated protobuf files

*.pb.go

# Re-include only if excluded by global Git excludes

!important.sql

```

Here, `*.pb.go` adds an extra exclusion not present in `.gitignore`, while `!important.sql` only takes effect if the file matches your global Git exclude patterns.

### Example 3: Interaction Matrix

Consider this repository structure:

```

/build/output.bin          (matches .gitignore)
src/generated/client.pb.go (matches .cbmignore)
docs/config.sql            (matches global Git exclude)

```

| File                         | Ignored by `.gitignore`? | Ignored by `.cbmignore`? | Final Outcome |
|------------------------------|--------------------------|--------------------------|---------------|
| `build/output.bin`           | **Yes** (layer 2)        | No effect (layer 4)      | **Skipped**   |
| [`src/generated/client.pb.go`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/generated/client.pb.go) | No                       | **Yes** (positive match) | **Skipped**   |
| [`docs/config.sql`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/config.sql)            | No                       | **Yes** (negation rescues) | **Indexed** |

### Example 4: CLI Verification

```bash

# Initialize a test repository

mkdir test-repo && cd test-repo
git init -q

# Create .gitignore

cat > .gitignore <<'EOF'
build/
*.log
EOF

# Create .cbmignore

cat > .cbmignore <<'EOF'
*.pb.go
!secret.sql
EOF

# Generate test files

mkdir -p build src docs
touch build/output.bin src/generated.pb.go docs/secret.sql

# Index with exclusion reporting

codebase-memory-mcp index . --report excluded

```

This command reports `build/output.bin` and [`src/generated.pb.go`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/generated.pb.go) as excluded. The [`docs/secret.sql`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/secret.sql) file remains indexed only if it matches a pattern in your global Git excludes that the `.cbmignore` negation then overrides.

## Implementation Details

The discovery logic resides in [`src/discover/discover.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/discover/discover.c), where the discovery function walks the repository tree and tests each path against the five ignore layers in sequence. The code explicitly checks built-in skips first, then Git ignore layers, and finally applies `.cbmignore` patterns before checking global excludes.

Key source files:
- [`docs/cbmignore.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/cbmignore.md) – Complete syntax documentation and precedence rules [lines 66-84].
- [`src/discover/discover.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/discover/discover.c) – Core discovery implementation where the layered evaluation occurs [lines 64-84].
- [`README.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/README.md) – High-level overview of the layered ignore strategy [lines 16-20].

## Summary

- **`.cbmignore` evaluates after `.gitignore`**, meaning repository Git ignore rules always take precedence.
- **Built-in skips** (`.git`, `node_modules`, `dist`, etc.) are hard-coded at layer 1 and cannot be overridden by any ignore file.
- **Positive patterns** in `.cbmignore` add new exclusions beyond what Git ignores define.
- **Negated patterns** (`!`) only rescue files from global Git excludes (layer 5), not from repository `.gitignore` rules (layers 2-3).
- The hierarchy is implemented in [`src/discover/discover.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/discover/discover.c) and documented in [`docs/cbmignore.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/cbmignore.md).

## Frequently Asked Questions

### Can .cbmignore override .gitignore rules?

No. Because `.cbmignore` is evaluated at layer 4 while repository `.gitignore` is layer 2, any file excluded by `.gitignore` will be skipped regardless of what appears in `.cbmignore`. The `.cbmignore` file is designed to supplement ignore rules, not override version control decisions.

### What can .cbmignore negation patterns (!) actually do?

Negation patterns in `.cbmignore` can only re-include files that would be excluded by the global Git excludes file (layer 5), typically configured via `core.excludesfile` in your Git configuration. If a file is excluded by the repository `.gitignore` or nested `.gitignore` files, negation in `.cbmignore` has no effect.

### Where should I place my .cbmignore file?

The `.cbmignore` file must reside at the repository root (`<repo>/.cbmignore`). Unlike `.gitignore`, it does not support nested configuration in subdirectories. All project-specific indexing rules should be defined in this single root-level file.

### Which directories are in the built-in skip list?

The built-in skip list includes hard-coded directories such as `.git`, `node_modules`, `dist`, `target`, and other common build artifact directories. These are evaluated at layer 1 and cannot be overridden by any ignore file pattern, including negations in `.cbmignore` or `.gitignore`.