Lesson 13 of 6815 min read

.gitignore: Patterns, Global Ignore, and Ignoring Already-Tracked Files

Learn how to use .gitignore to keep unwanted files — logs, dependencies, secrets, build output — out of your Git history entirely.

Author: CodersNexus

.gitignore: Patterns, Global Ignore, and Ignoring Already-Tracked Files

Not every file in a project belongs in version control. Dependency folders like node_modules, build output, log files, local environment secrets, and editor-specific settings files can bloat your repository, leak sensitive information, or cause unnecessary noise and conflicts. `.gitignore` is Git's mechanism for telling it, upfront, which files and patterns to simply never track — and this lesson covers exactly how to write these patterns correctly, at both the project and global level.

Learning Objectives

  • Create a .gitignore file with correct pattern syntax.
  • Distinguish between exact filenames, wildcards, and directory patterns.
  • Set up a global gitignore file that applies across all of your projects.
  • Stop tracking a file that was already committed before being added to .gitignore.

Key Terms to Know Before Learning .gitignore

  • .gitignore: A plain text file, placed in a repository, listing patterns of files and directories that Git should never track.
  • Wildcard pattern: A pattern using symbols like * to match multiple filenames at once (e.g., *.log matches every file ending in .log).
  • Global gitignore: A single .gitignore file configured to apply across every repository on your machine, typically for OS- or editor-specific files.
  • Tracked file: A file Git is already actively monitoring, because it has been added and/or committed at least once — adding it to .gitignore afterward does not automatically stop tracking it.
  • git rm --cached: A command that removes a file from Git's tracking (and the staging area) while leaving the actual file untouched on disk.

How .gitignore Actually Works

A `.gitignore` file is simply a plain text file, usually placed at the root of your repository, containing one pattern per line. Any file or folder matching those patterns will be completely ignored by Git — it won't show up as 'untracked' in `git status`, and running `git add .` will silently skip over it.

Common pattern types include:

- **Exact filenames**: `secrets.env` ignores that one specific file.
- **Wildcards**: `*.log` ignores every file ending in `.log`, anywhere in the repository.
- **Directories**: `node_modules/` (with a trailing slash) ignores an entire folder and everything inside it, recursively.
- **Negation**: A pattern starting with `!` re-includes a file that would otherwise be ignored by a broader pattern — for example, ignoring `*.log` but explicitly keeping `important.log` with `!important.log`.
- **Comments**: Lines starting with `#` are treated as comments and ignored by Git itself.

A typical Node.js project's `.gitignore` might look like:

```
# Dependencies
node_modules/

# Environment secrets
.env

# Build output
dist/
build/

# Logs
*.log

# OS-specific files
.DS_Store
```

Beyond project-specific ignore files, many patterns — like macOS's `.DS_Store` files or editor-specific folders like `.vscode/` — are personal to your machine or tools rather than relevant to any single project. For these, Git supports a **global gitignore file**, configured once per machine:

```
git config --global core.excludesfile ~/.gitignore_global
```

Any pattern placed inside `~/.gitignore_global` then applies automatically across every repository on that machine, without needing to repeat it in every project's own `.gitignore`.

A critical and commonly misunderstood point: **adding a pattern to `.gitignore` does not remove a file that Git is already tracking.** `.gitignore` only prevents *new, currently untracked* files from being added. If a file was accidentally committed before you added it to `.gitignore` (a classic example: an `.env` file with secrets), you must explicitly stop tracking it with:

```
git rm --cached .env
```

The `--cached` flag is essential here — it removes the file from Git's tracking and the staging area, but leaves the actual file untouched on your local disk. After running this and committing the change, the file will no longer be tracked going forward, and the `.gitignore` pattern will correctly prevent it from being re-added.

.gitignore: Visual Walkthrough

Show a project folder with files: index.js (green, tracked), node_modules/ (red, crossed out), .env (red, crossed out), app.log (red, crossed out). Draw an arrow from a '.gitignore' file box listing 'node_modules/', '.env', '*.log' pointing at the red crossed-out items, labeled 'these patterns tell Git to skip these files entirely'. Add a callout box: 'Warning: if a file was already committed BEFORE being added here, you must run git rm --cached <file> to actually stop tracking it.'

.gitignore: Quick Reference Table

PatternMatchesExample
filename.extOne exact file, anywhere it appears.env
*.extEvery file with that extension*.log
foldername/An entire folder and its contents, recursivelynode_modules/
!filename.extRe-includes a file otherwise excluded by a broader pattern!important.log
# commentIgnored entirely by Git; used for readability# Build artifacts

.gitignore: Command Syntax and Examples

# Create a .gitignore file at the project root
cat > .gitignore << 'EOF'
node_modules/
.env
dist/
*.log
.DS_Store
EOF

# Set up a global gitignore for OS/editor files across ALL your projects
git config --global core.excludesfile ~/.gitignore_global
echo ".vscode/" >> ~/.gitignore_global
echo ".DS_Store" >> ~/.gitignore_global

# Stop tracking a file that was accidentally committed BEFORE adding it to .gitignore
git rm --cached .env
git commit -m "chore: stop tracking .env file"

# Confirm it's no longer tracked, but still exists on disk
git status
ls .env    # file still physically present locally

Breaking Down the .gitignore Example

The `.gitignore` file created here ensures `node_modules/`, `.env`, `dist/`, any `.log` file, and `.DS_Store` are never staged or committed going forward. The global gitignore setup handles editor- and OS-specific files (like `.vscode/`) so this doesn't need to be repeated in every project's own `.gitignore`. The final block demonstrates the critical fix for a file that was mistakenly committed before being ignored: `git rm --cached .env` removes it from Git's tracking while leaving it physically on disk, and committing this change permanently stops that file from being part of future history.

How .gitignore Is Used on Real Engineering Teams

  • Nearly every real-world project uses services like gitignore.io or GitHub's official gitignore template repository to generate a comprehensive, language-specific .gitignore file (e.g., for Node.js, Python, Java) rather than writing one entirely from scratch.
  • Security incidents have repeatedly occurred at real companies when API keys or credentials were committed inside an .env file before .gitignore was configured — underscoring why the git rm --cached fix (combined with credential rotation) is a critical skill.
  • Large monorepos rely heavily on precise .gitignore patterns to exclude generated build artifacts (like dist/ or *.map source map files) that would otherwise dramatically bloat repository size and clone times.
  • Cross-platform teams commonly configure a shared global gitignore convention in onboarding docs so that OS-specific files (Windows' Thumbs.db, macOS's .DS_Store) never accidentally get committed by any team member regardless of their machine.

.gitignore Interview Questions and Answers

Q1. What is the purpose of a .gitignore file?

A .gitignore file lists patterns describing files and directories that Git should never track — such as dependency folders, build output, log files, and local secrets. Matching files won't appear as untracked in git status and won't be staged even by a broad git add .

Q2. If I add a file to .gitignore, will it stop appearing in my repository's history?

No, not automatically. .gitignore only prevents currently untracked files from being added going forward. If the file was already tracked (previously added or committed), you must explicitly run git rm --cached <file> and commit that change to actually stop tracking it.

Q3. What is a global gitignore file and why would you use one?

A global gitignore file, configured once via git config --global core.excludesfile, applies patterns across every repository on your machine. It's typically used for OS- or editor-specific files (like .DS_Store or .vscode/) that aren't relevant to any single project but should be ignored everywhere.

.gitignore Quiz: Test Your Understanding

1. What does the pattern node_modules/ in a .gitignore file do?

  1. Ignores only a file literally named node_modules
  2. Ignores the entire node_modules folder and everything inside it
  3. Deletes the node_modules folder
  4. Has no effect without a wildcard

Answer: B. Ignores the entire node_modules folder and everything inside it

Explanation: A trailing slash in a .gitignore pattern indicates a directory, causing Git to ignore that entire folder and its full contents recursively.

2. If a file was already committed before being added to .gitignore, what must you do to stop tracking it?

  1. Nothing — .gitignore automatically removes it from history
  2. Delete the file from disk entirely
  3. Run git rm --cached <file> and commit the change
  4. Rename the file

Answer: C. Run git rm --cached <file> and commit the change

Explanation: .gitignore only affects currently untracked files. To stop tracking an already-committed file while keeping it on disk, you must explicitly remove it from Git's index with git rm --cached and commit that change.

3. What command sets up a global .gitignore file across all your repositories?

  1. git config --global core.excludesfile ~/.gitignore_global
  2. git add --global .gitignore
  3. git ignore --all
  4. git config --local ignorefile

Answer: A. git config --global core.excludesfile ~/.gitignore_global

Explanation: This command tells Git to apply the patterns in the specified file across every repository for the current user, making it ideal for OS- or editor-specific ignore rules.

.gitignore: Common Mistakes Beginners Make

  • Adding a file to .gitignore and expecting it to disappear from history automatically, without running git rm --cached on an already-tracked file.
  • Committing sensitive files like .env before setting up .gitignore, exposing secrets in the repository's permanent history.
  • Forgetting the trailing slash when ignoring a directory (writing node_modules instead of node_modules/), which can behave unexpectedly in some edge cases.
  • Not using a global gitignore for personal OS/editor files, leading to repeatedly re-adding the same patterns (like .DS_Store) to every new project's .gitignore.

.gitignore: Exam-Ready Quick Notes

  • .gitignore lists patterns for files/folders Git should never track; one pattern per line.
  • Key syntax: exact filenames, *.ext wildcards, foldername/ for directories, !pattern for negation, # for comments.
  • Global gitignore: git config --global core.excludesfile ~/.gitignore_global — applies across all repos on the machine.
  • Already-tracked files need git rm --cached <file> plus a commit to actually stop being tracked.

.gitignore: Key Takeaways

  • .gitignore prevents unwanted files — dependencies, build output, secrets, logs — from ever being tracked by Git.
  • A global gitignore file avoids repeating personal OS/editor-specific patterns across every single project.
  • Adding a rule to .gitignore does not retroactively untrack a file already committed — git rm --cached is required for that.

Frequently Asked Questions About .gitignore

Q1. What is .gitignore used for?

It's a file listing patterns for files and folders that Git should never track — commonly used for dependency folders like node_modules, build output, log files, and secret configuration files like .env.

Q2. Why is my file still showing up in Git even after I added it to .gitignore?

If the file was already tracked (previously added or committed) before you added it to .gitignore, the ignore rule only applies going forward — it won't retroactively untrack it. You need to run git rm --cached <file> and commit that change to actually stop tracking it.

Q3. What is a global gitignore file?

It's a single .gitignore file configured to apply across every repository on your machine, typically used for personal, OS-, or editor-specific files (like .DS_Store or .vscode/) that don't need to be repeated in every project's own .gitignore.

Q4. How do I ignore an entire folder in .gitignore?

Add the folder name followed by a trailing slash, such as node_modules/ or dist/. This tells Git to ignore that entire directory and everything inside it, recursively.

Q5. Can I un-ignore a specific file inside an otherwise ignored pattern?

Yes, using a negation pattern with an exclamation mark, such as !important.log after a broader *.log rule. This re-includes that specific file even though the general pattern would otherwise exclude it.

Summary

`.gitignore` is a plain text file listing patterns — exact filenames, wildcards like `*.log`, or entire directories like `node_modules/` — that Git should never track, keeping dependency folders, build artifacts, logs, and sensitive files out of a repository's history. A global gitignore file, set via `git config --global core.excludesfile`, applies personal patterns like OS or editor files across every repository on a machine. Critically, `.gitignore` only affects files that are not yet tracked — a file already committed before being added to `.gitignore` must be explicitly untracked using `git rm --cached <file>`, followed by a commit, to actually stop Git from tracking it going forward.

Frequently Asked Questions

It's a file listing patterns for files and folders that Git should never track — commonly used for dependency folders like node_modules, build output, log files, and secret configuration files like .env.

If the file was already tracked (previously added or committed) before you added it to .gitignore, the ignore rule only applies going forward — it won't retroactively untrack it. You need to run git rm --cached <file> and commit that change to actually stop tracking it.

It's a single .gitignore file configured to apply across every repository on your machine, typically used for personal, OS-, or editor-specific files (like .DS_Store or .vscode/) that don't need to be repeated in every project's own .gitignore.

Add the folder name followed by a trailing slash, such as node_modules/ or dist/. This tells Git to ignore that entire directory and everything inside it, recursively.

Yes, using a negation pattern with an exclamation mark, such as !important.log after a broader *.log rule. This re-includes that specific file even though the general pattern would otherwise exclude it.