Free Ebook cover Git for Programmers: Version Control for Small Projects

Git for Programmers: Version Control for Small Projects

New course

7 pages

Ignoring the Right Things: .gitignore Rules and Tracking Decisions in Git

Capítulo 3

Estimated reading time: 7 minutes

+ Exercise

What Belongs in Version Control vs What Should Never Be Committed

A clean repository contains the source and configuration needed to build and run the project, plus documentation that helps others understand it. It should not contain files that are generated, machine-specific, or sensitive. The goal of .gitignore is to prevent accidental commits of “noise” and secrets.

Good candidates to commit

  • Source code: src/, lib/, application modules, scripts.
  • Build configuration: package.json, pyproject.toml, pom.xml, build.gradle, tool configs.
  • Lockfiles (usually): package-lock.json, poetry.lock, requirements.txt (depending on your workflow).
  • Documentation: README.md, docs/, examples.
  • Small, deterministic assets needed at runtime: templates, migrations, small static files (not large generated bundles).

Should be ignored (typical)

  • Build artifacts: dist/, build/, compiled binaries, minified bundles produced by your build.
  • Dependencies installed locally: node_modules/, Python virtual environments (.venv/), Gradle caches.
  • Logs and runtime output: *.log, coverage/, temp files.
  • OS and editor files: .DS_Store, Thumbs.db, .idea/, .vscode/ (often), swap files.
  • Secrets: .env, API keys, private certificates, tokens, credentials JSON.

Never commit (even “temporarily”)

  • Credentials: passwords, tokens, API keys, cloud credentials, SSH private keys.
  • Private keys and certificates: *.pem, id_rsa, signing keys.
  • Production data dumps: database exports, user data, proprietary datasets.

If a secret is committed, removing it from the working tree is not enough; it remains in history. The best strategy is prevention: ignore it and use safe patterns like .env.example (covered below).

Creating and Testing .gitignore Patterns

.gitignore is a plain text file placed at the repository root (and optionally in subdirectories). Each line is a pattern that tells Git which untracked files to ignore. Ignoring affects what shows up as “untracked” and what can be accidentally added.

Step-by-step: create a baseline .gitignore

1) Create the file at the repo root:

touch .gitignore

2) Add common entries for your project. Example for a small web app:

Continue in our app.

You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.

Or continue reading below...
Download App

Download the app

# Dependencies and environments
node_modules/
.venv/

# Build output
dist/
build/

# Logs
*.log

# OS files
.DS_Store
Thumbs.db

# Editor caches
.vscode/
.idea/

# Secrets
.env

3) Verify what is currently untracked and whether it is now ignored:

git status

Wildcards and common pattern rules

  • Match by extension: *.log ignores any file ending in .log.
  • Match anywhere: __pycache__/ ignores directories named __pycache__ wherever they appear.
  • Root-only patterns: prefix with / to match only at the repository root. Example: /dist/ ignores only root dist, not src/dist/.
  • Directory rules: a trailing slash means “directory”. Example: build/ ignores the directory and everything under it.
  • Single-character wildcard: file?.txt matches file1.txt but not file10.txt.
  • Character ranges: file[0-9].txt matches file7.txt.

Negation with ! (ignore everything except…)

Negation lets you re-include a file that would otherwise be ignored. This is useful when you want to ignore a whole directory but keep a placeholder or a specific config file.

Example: ignore all files in logs/ but keep a .gitkeep placeholder:

logs/
!logs/.gitkeep

Example: ignore all .env files but keep an example template:

.env
!.env.example

Important: if you ignore a directory (e.g., logs/), Git may not “see” files inside it to re-include unless the parent path is not fully excluded. A common workaround is to ignore contents instead of the directory itself:

logs/*
!logs/.gitkeep

Testing patterns before you add files

Use Git’s pattern debugging to confirm whether a specific path is ignored and which rule caused it:

git check-ignore -v path/to/file

If the file is ignored, the output shows the matching .gitignore line and file location. If there is no output, the file is not ignored.

Ignored vs Already-Tracked Files: The Key Difference

.gitignore only prevents untracked files from being added accidentally. If a file is already tracked (it has been committed before), adding it to .gitignore does not stop Git from tracking changes to it.

How to tell which case you are in

  • If git status shows a file under “Untracked files”, it can be ignored by .gitignore.
  • If git status shows it under “Changes not staged for commit” or “Changes to be committed”, it is already tracked.

Practical example: you accidentally committed dist/ once. Later you add dist/ to .gitignore, but changes in dist/ still appear. That’s because the directory is tracked in history.

Removing Tracked Artifacts Safely with git rm --cached

To stop tracking a file while keeping it on disk, remove it from the index (staging area) using --cached. This is the standard fix for “I committed build output or a secret file by mistake, and now I want Git to stop tracking it.”

Step-by-step: stop tracking a file but keep it locally

1) Add the correct ignore rule first (so it won’t come back as untracked):

# .gitignore
.env

2) Remove it from tracking (but keep the file in your working directory):

git rm --cached .env

3) Confirm the change:

git status

4) Commit the removal and the ignore rule together:

git add .gitignore
git commit -m "Stop tracking .env and ignore it"

Step-by-step: remove a tracked directory of artifacts

Example: dist/ is tracked but should be ignored.

# 1) Add ignore rule
printf "/dist/\n" >> .gitignore

# 2) Remove from index recursively
git rm -r --cached dist/

# 3) Commit
git add .gitignore
git commit -m "Remove dist from tracking and ignore build output"

Note: if the artifacts include sensitive data that has already been committed, git rm --cached prevents future commits but does not erase history. Treat that as a security incident: rotate credentials and consider history rewriting only if you fully understand the impact on collaborators.

Repository Hygiene: Secrets, .env.example, and Verifying What Will Be Committed

Use .env.example to document required environment variables

A common small-project pattern is:

  • .env: real secrets and machine-specific values (ignored).
  • .env.example: a committed template showing required keys without real values.

Example .gitignore rules:

.env
!.env.example

Example .env.example content:

# Copy to .env and fill in real values
DATABASE_URL=
API_KEY=
PORT=3000

This keeps onboarding simple while preventing accidental credential commits.

Avoid committing credentials in any form

  • Do not hardcode tokens in source files.
  • Do not commit “temporary” JSON credentials (cloud service accounts, OAuth client secrets).
  • Do not commit private keys, even in test folders.

If you need non-secret defaults, keep them in a committed config file (for example config/default.json) and load secrets from environment variables or an ignored local override file (for example config/local.json ignored).

Verify what will be committed: git status and git diff --staged

Before every commit, check two things: what is staged, and what content is staged.

1) See what is staged vs unstaged:

git status

2) Inspect the exact staged changes (this is where secrets often get caught):

git diff --staged

Practical habit: if you ever see a token-like string, a private key header, or a password in git diff --staged, unstage it immediately and fix the source (move it to .env, config override, or secret manager).

Checklist: Common Ignore Rules for Small-Project Stacks

Node.js (npm/yarn/pnpm)

  • node_modules/
  • dist/, build/, framework outputs (for example .next/, .nuxt/)
  • .env and related: .env.* (keep .env.example)
  • Logs: npm-debug.log*, yarn-debug.log*, yarn-error.log*, *.log
  • Coverage: coverage/

Python

  • Virtual environments: .venv/, venv/
  • Bytecode and caches: __pycache__/, *.pyc
  • Build artifacts: build/, dist/, *.egg-info/
  • Test/coverage: .pytest_cache/, .coverage, htmlcov/
  • Environment files: .env (keep .env.example)

Java (Maven/Gradle)

  • Maven: target/
  • Gradle: build/, .gradle/
  • IDEs: .idea/, *.iml, .classpath, .project, .settings/
  • Logs: *.log
  • Environment files: .env (keep .env.example)

Validate Ignore Rules Before the First Commit

Step-by-step pre-commit validation routine

1) Create .gitignore early, before installing dependencies or running builds.

2) Generate typical local artifacts once (install dependencies, run tests/build) so you can see what appears.

3) Check what Git thinks is untracked:

git status

4) For any suspicious file or directory, confirm whether it is ignored and why:

git check-ignore -v path/to/suspicious-file

5) Stage intentionally, then inspect staged content:

git add -A
git status
git diff --staged

6) If something should not be committed, fix it now:

  • Add/adjust .gitignore patterns.
  • If it was accidentally staged, unstage it (for example git restore --staged path).
  • If it was already tracked, remove it safely with git rm --cached (file) or git rm -r --cached (directory), then commit the change.

Now answer the exercise about the content:

You accidentally committed a .env file in the past, then added .env to .gitignore, but Git still shows changes to .env. What is the correct way to stop tracking the file while keeping it on disk?

You are right! Congratulations, now go to the next page

You missed! Try again.

.gitignore only affects untracked files. If .env was already committed, you must remove it from the index with git rm --cached (while keeping it locally) and commit that change together with the ignore rule.

Next chapter

Branching in Git for Small Features: Isolated Changes and Faster Reviews

Arrow Right Icon
Download the app to earn free Certification and listen to the courses in the background, even with the screen off.