.gitignore
Not every file in a project folder belongs in git history. Some are generated automatically and can be recreated anytime; some are specific to your own machine; some are actively dangerous to publish. A .gitignore file tells git which files and folders to never even consider — they won't show up in git status, won't get staged by git add ., and won't accidentally end up in a commit.
What Should Never Be Tracked
.env files. The single most important category — covered in detail below.
node_modules/, Python's venv/, vendor folders. Huge, regenerable from a lockfile (package-lock.json, requirements.txt) — tracking them bloats the repo for no benefit.
dist/, build/, compiled .class or .pyc files. Generated from source you already have tracked — committing the output as well just creates redundant, conflict-prone noise.
.DS_Store (macOS), Thumbs.db (Windows), .vscode/ or .idea/ personal editor settings. Specific to your machine, meaningless to anyone else cloning the repo.
*.log, *.tmp, cache directories. Generated during normal operation, churn constantly, and add no value to history.
Creating a .gitignore File
A .gitignore file is plain text, placed at the root of your repository, with one pattern per line. Git reads it automatically — no command needed to "enable" it.
node_modules/
.env
dist/
*.log
.DS_Store
Pattern syntax
| Pattern | Matches |
|---|---|
| node_modules/ | The folder named node_modules, anywhere in the project (trailing slash = directory only) |
| *.log | Any file ending in .log, anywhere in the project |
| .env | A file named exactly .env in the root (and in any subfolder, since no leading slash) |
| /build | A folder named build, but only at the project root — leading slash anchors it |
| temp/* | Everything directly inside temp/, but not the temp/ folder itself |
| !important.log | An exception — un-ignores a file that an earlier pattern would otherwise have matched |
.gitignore for your exact stack (Node, Python, Java, VS Code, macOS, etc.) — paste in your tools and it builds the file for you. GitHub also offers starter templates when creating a new repository. Hand-writing one from memory is rarely necessary.
The .env File — Special Attention Required
Almost every modern project stores secrets (database passwords, API keys) in a .env file that gets loaded into environment variables at runtime. This file should always be in .gitignore — but the project still needs to communicate what variables are expected. The standard pattern:
.env ← ignored: contains your actual secrets
DATABASE_URL=postgres://user:password@localhost/dbname
API_KEY=your-api-key-here
# .env — never committed, real secrets, listed in .gitignore
DATABASE_URL=postgres://admin:Tr0ub4dor&3@prod-db.example.com/myapp
API_KEY=sk-live-a1b2c3d4e5f6g7h8i9j0
Anyone cloning the repo copies .env.example to .env and fills in their own real values — the structure is shared, the secrets never are.
.gitignore Only Works on Untracked Files
This catches almost everyone out at least once: adding a pattern to .gitignore does nothing for a file git is already tracking. If a file was committed before it was added to .gitignore, git keeps tracking it regardless.
$ git rm --cached config.json
rm 'config.json'
# Now it's untracked — .gitignore will take effect from here on
$ git commit -m "Stop tracking config.json"
git rm --cached removes the file from git's tracking without deleting it from your disk — exactly what you want when un-tracking a file you still need locally.
git rm --cached stops tracking a file going forward, but every previous commit that included it still has it, fully recoverable by anyone with access to the repository's history — including a public repo that was briefly public, even if made private again later. If a real secret was ever committed, the correct response is to treat it as compromised: rotate/revoke the credential immediately. Rewriting history to remove it (covered in Course 3, Chapter 2) is good hygiene but does not undo the exposure on its own — assume it's been seen.
Command Reference
| Command | What it does |
|---|---|
| .gitignore | A file listing patterns git should never track, untracked files only |
| git rm --cached <file> | Stop tracking a file without deleting it from disk |
| git check-ignore -v <file> | Debug which .gitignore rule is (or isn't) matching a specific file |
Chapter 6 Quick Reference
- Never track: secrets/.env, dependencies (node_modules), build output, OS/editor junk, logs, large binaries
- .gitignore — plain text, one pattern per line, at the repo root, no command needed to enable it
- Generate, don't hand-write — use gitignore.io or GitHub's templates for your stack
- .env pattern: commit .env.example (no real values), ignore .env (real secrets)
- .gitignore only affects untracked files — use git rm --cached to stop tracking something already committed
- A committed secret is compromised the moment it's pushed — rotate the credential; don't rely on deleting it later to undo the exposure
- Next chapter: pull requests 101 — making your first PR, getting reviewed, and merging on GitHub itself