A .gitignore file tells Git which files and folders to leave out of version control, so build output, dependencies, and secrets never get committed. You list patterns, one per line, and Git skips anything that matches. Here is how the syntax works, what to ignore, and the one gotcha that trips up almost everyone.
What a .gitignore file does
When you run git add, Git checks every new path against your .gitignore patterns and silently skips the matches. This keeps your repository clean and small, avoids noisy diffs from generated files, and keeps credentials out of your history.
Put the file at the root of your repository, named exactly .gitignore. You can also place additional .gitignore files in subfolders, and their rules apply to that folder and below.
Pattern syntax
The rules are simple once you know the symbols:
- A plain name like
node_modulesmatches that file or folder anywhere in the repo. - A trailing slash like
dist/matches directories only, not a file nameddist. - A leading slash like
/buildanchors the pattern to the repo root, so a nestedbuildfolder is not affected. *matches anything except a slash, so*.logignores all log files in a directory.**matches across nested directories, sologs/**/*.tmpreaches temp files at any depth.!negates a pattern, re-including something an earlier rule excluded, for example!important.log.#starts a comment, and blank lines are ignored, so you can group and label your rules.
Order matters with negation: a ! rule only works if the file was excluded by an earlier pattern, and you cannot re-include a file if its parent directory is ignored.
What to ignore (and what never to commit)
Most projects share the same suspects:
- Dependencies:
node_modules/,vendor/,__pycache__/ - Build output:
dist/,build/,*.min.js, compiled binaries - Environment and secrets:
.env,.env.local, API keys, credential files - OS cruft:
.DS_Store,Thumbs.db - Editor and IDE folders:
.vscode/,.idea/,*.swp
Never commit your .env file or anything holding secrets. Once a secret lands in your history, removing it later is painful and you should rotate the credential anyway. Add .env to .gitignore before your first commit.
The fastest way to a solid starting point is the .gitignore Generator, which builds a tuned file from your stack so you are not copying patterns by hand.
Generate a .gitignore file in three steps
- Open the .gitignore Generator and pick your languages, frameworks, and tools.
- Review the generated patterns and add anything specific to your project.
- Copy the result into a
.gitignorefile at the root of your repo, then commit it.
It runs entirely in your browser, so nothing about your project is sent anywhere.
The gotcha: .gitignore does not untrack committed files
This is the part everyone misses. A .gitignore file only affects untracked files. If you already committed node_modules or .env, adding it to .gitignore changes nothing, Git keeps tracking it.
To stop tracking a file that is already committed, remove it from the index while keeping it on disk:
git rm --cached .env
git rm -r --cached node_modules
Then commit. Git stops tracking those paths going forward, and your .gitignore rules finally take effect. Remember that the file still exists in your history, so for a leaked secret, rotate it.
Related tools
- EditorConfig Generator keeps formatting consistent across editors and teammates.
- JSON Formatter cleans up the config files your repo is full of.
- Diff Checker compares two versions of a file before you commit.
Set up your .gitignore before the first commit, and you will never have to chase a stray secret out of your history.