# How to Use Wildcards and Glob Patterns in .gitignore Files

> Master wildcards and glob patterns in gitignore files. Learn to use *, **, ?, and [] effectively to ignore files and directories, optimizing your Git workflow. Avoid accidental commits with expert tips.

- Repository: [GitHub/gitignore](https://github.com/github/gitignore)
- Tags: how-to-guide
- Published: 2026-02-24

---

**Wildcards and glob patterns in .gitignore files use `*` to match zero or more characters (excluding `/`), `**` to match across directory boundaries, `?` for single characters, and `[]` for character classes, with patterns evaluated top-to-bottom where the first match wins unless negated by `!`.**

Gitignore files tell Git which files and directories to exclude from version control using a glob-style pattern matching syntax. The github/gitignore repository contains thousands of production-ready templates that demonstrate how to use these wildcards effectively across different programming languages and development environments. Understanding these pattern rules allows you to write concise, maintainable ignore rules that scale with your project structure without listing every file explicitly.

## Understanding Wildcard Syntax in .gitignore

Git interprets patterns using its own glob-matching engine, which shares similarities with shell globbing but includes specific rules for path handling. The following symbols control pattern matching behavior:

- **`*`** – Matches zero or more characters within a single directory level, but stops at path separators (`/`).
- **`**`** – Matches zero or more complete directory paths, spanning across `/` boundaries to match at any depth.
- **`?`** – Matches exactly one character, excluding `/`.
- **`[]`** – Defines a character class that matches any single character inside the brackets (e.g., `[aeiou]` matches any vowel, `[0-9]` matches any digit).
- **`!`** – Negates a pattern, re-including files that would otherwise be ignored by previous rules.
- **`/`** – When placed at the start of a pattern, anchors it to the repository root; when placed at the end, indicates the pattern applies only to directories.

These rules are implemented by Git's pattern matching system and demonstrated throughout the github/gitignore templates.

## How Git Evaluates Ignore Patterns

Git processes `.gitignore` files following a strict evaluation order that determines whether a file is tracked or excluded:

1. **Read top-to-bottom** – Git processes the file line by line in the order patterns appear.
2. **First match wins** – Once a path matches a pattern, it is ignored unless a later negated pattern (`!`) re-includes it.
3. **Directory-only patterns** – A trailing slash indicates the pattern matches only directories, affecting the directory and all contents recursively.
4. **Double asterisk flexibility** – The `**` wildcard can appear anywhere in a pattern to match across multiple directory levels, making rules future-proof as new subdirectories are added.

## Real-World Wildcard Patterns from github/gitignore

The following examples demonstrate how wildcards operate in production templates from the github/gitignore repository.

### Match Files Across Directory Levels with `**`

The double asterisk wildcard matches any number of directories, including none, allowing patterns to apply recursively at any depth. In `Flutter.gitignore` at line 71, the pattern `**/ios/**/Icon?` matches any file starting with `Icon` followed by exactly one character, located anywhere within an `ios` directory at any level of the project hierarchy.

```gitignore

# Ignore any Icon file inside any iOS bundle, regardless of depth

**/ios/**/Icon?

```

### Directory-Specific Rules Using Trailing Slashes

Appending a slash to a pattern restricts it to matching only directories. In `C++.gitignore` at lines 42-45, the pattern `build/` ignores any directory named `build` and all its contents, but does not ignore a file named `build` if one exists at the root.

```gitignore

# Ignore any "build" directory recursively

build/

```

### Character Classes and Single-Character Wildcards

Character classes defined with square brackets match any single character within the set. In `VisualStudio.gitignore` at line 259, the pattern `!?*.[Cc]ache/` uses a negated character class to re-include cache directories that match either `.cache` or `.Cache`, regardless of what character precedes them.

```gitignore

# Keep the cache folder that matches "?cache" (e.g., .cache, XCache)

!?*.[Cc]ache/

```

The `?` wildcard matches exactly one character. In `TwinCAT3.gitignore` at line 25, the pattern `*.tsproj.b?k` matches backup files where the extension starts with `b`, followed by any single character, followed by `k` (such as `.bak` or `.bck`).

```gitignore

# Match specific placeholder in generated names

*.tsproj.b?k

```

Similarly, `TeX.gitignore` at line 99 uses `*.?end` to match files ending with any single character followed by `end`, demonstrating how `?` combines with literal text for precise matching. For basic extension matching, `Java.gitignore` at line 5 uses `*.log` to ignore all log files throughout the repository.

### Negation and Re-inclusion with `!`

The exclamation mark negates a pattern, forcing Git to include files that previous rules excluded. This is useful when you want to ignore a broad category but keep specific exceptions. Place negated patterns after the broader rules they should override:

```gitignore

# Ignore all class files but re-include a specific generated file

*.class
!Generated/Important.class

```

## Summary

- **`*`** matches any characters except `/`, while `**` matches across directory boundaries including the current directory.
- **`?`** matches exactly one character, useful for patterns with single-character variations like backup extensions.
- **`[]`** creates character classes for case-sensitive or range-based matching (e.g., `[0-9]` or `[Cc]`).
- **Trailing `/`** restricts patterns to directories only, ensuring you ignore folders like `build/` but not files named `build`.
- **`!`** negates previous patterns, allowing specific file re-inclusion after broad ignore rules.
- Git evaluates patterns sequentially from top to bottom, stopping at the first match unless negated.

## Frequently Asked Questions

### What is the difference between `*` and `**` in .gitignore?

The single asterisk `*` matches zero or more characters within a single directory level, stopping at path separators. The double asterisk `**` matches zero or more complete directory paths, allowing it to span across `/` boundaries. For example, `*.log` matches only in the current directory, while `**/*.log` matches in any subdirectory at any depth.

### How do I ignore a directory at any depth in my repository?

Use the double asterisk wildcard combined with a trailing slash to match directories at any level. The pattern `**/build/` ignores any directory named `build` regardless of where it appears in the hierarchy, as demonstrated in templates like `C++.gitignore` at lines 42-45.

### Can I re-include files after they have been ignored by a previous pattern?

Yes, use the negation operator `!` before a pattern to re-include files that match previous ignore rules. Git processes patterns sequentially, so place negated patterns after the broader ignore rules they should override. For example, `*.cache` followed by `!important.cache` ignores all cache files except `important.cache`.

### Do .gitignore patterns support regular expressions?

No, `.gitignore` patterns use glob syntax, not regular expressions. While similar in concept, glob patterns have simpler rules: `*` matches any sequence of characters (except `/`), `?` matches exactly one character, and `[]` defines character classes. This differs from regex metacharacters like `.` or `+`, which have no special meaning in `.gitignore` files unless used literally inside character classes.