Ignoring Files with .gitignore
Some files are required on a developer’s computer but should not become part of the repository. Examples include:
- Dependency directories that can be recreated.
- Local environment configuration.
- Files containing passwords, API keys, or tokens.
- Generated build output.
- Logs and temporary files.
Tracking these files can expose secrets, increase repository size, create conflicts between developers, and add unnecessary changes to project history.
Git uses a special file named:
.gitignoreThis file contains patterns describing paths that Git should normally ignore while they are untracked.
Creating .gitignore
Section titled “Creating .gitignore”Create .gitignore in the repository root:
laravel-shop/├── .git/├── .gitignore├── app/└── composer.jsonExample:
.env/vendor//node_modules//public/build/*.log| Pattern | Meaning |
|---|---|
.env |
Ignore .env |
/vendor/ |
Ignore the root Composer dependency directory |
/node_modules/ |
Ignore the root JavaScript dependency directory |
/public/build/ |
Ignore generated frontend build output |
*.log |
Ignore files ending in .log |
.gitignore itself should normally be tracked and committed, so the team
receives the same ignore rules:
git add .gitignoregit commit -m "build: add Git ignore rules"Conventional Commit formatting is optional and is not required by Git.
Dependencies versus dependency definitions
Section titled “Dependencies versus dependency definitions”These generated or installed directories are normally ignored:
vendor/node_modules/These dependency definition and lock files are normally committed:
composer.jsoncomposer.lockpackage.jsonpackage-lock.jsonThe directories can be recreated from the tracked dependency files.
Environment files
Section titled “Environment files”A Laravel .env may contain sensitive values:
APP_ENV=localDB_DATABASE=laravel_shopDB_USERNAME=rootDB_PASSWORD=secret-passwordSTRIPE_SECRET=sk_test_exampleThe real .env should normally not be committed. A safe template may be
tracked instead:
.env.exampleExample:
APP_ENV=localDB_DATABASE=DB_USERNAME=DB_PASSWORD=STRIPE_SECRET=.env.example lists the required configuration keys without storing real
secrets.
What .gitignore actually does
Section titled “What .gitignore actually does”
.gitignoretells Git which matching untracked paths it should normally avoid showing and adding.
It does not:
- Delete files from the computer.
- Encrypt files.
- Protect already exposed secrets.
- Remove files from old commits.
- Automatically stop tracking an already tracked file.
Tracked, untracked, and ignored
Section titled “Tracked, untracked, and ignored”Tracked
Section titled “Tracked”A tracked file is known to Git and belongs to the tracked project state. It may be unmodified, modified, or staged.
Untracked
Section titled “Untracked”An untracked file exists in the Working Tree but Git is not currently tracking it. It normally appears when running:
git statusIgnored
Section titled “Ignored”An ignored path normally means an untracked path matches an ignore rule. Git usually hides it from the normal untracked-files list.
Every ignored path is normally untracked, but not every untracked path is ignored.
A tracked file does not become ignored merely because its name is added to
.gitignore.
Testing an ignored file
Section titled “Testing an ignored file”Suppose .gitignore contains:
.envIf .env has never been tracked, running:
git statusshould normally not show it under Untracked files.
Check the matching rule with:
git check-ignore -v .envgit check-ignore Tests whether a path matches an ignore rule.
-v Shows the matching rule and where that rule was defined.
.env The path to test.Illustrative output:
.gitignore:1:.env .envThis identifies the ignore file, the matching line, the pattern, and the checked path.
To include ignored paths in Git’s status summary, use:
git status --ignored--ignored asks git status to show ignored paths as well as its normal
tracked and untracked state summary. This is an inspection option; it does not
change the files, the Staging Area, or a commit.
The critical rule
Section titled “The critical rule”Suppose .env was already committed:
git add .envgit commit -m "add environment configuration"Adding this later:
.envdoes not make Git forget the file. Git continues reporting changes to
.env because it is already tracked.
Ignore rules normally affect untracked paths. They do not retroactively remove files from the Index or previous snapshots.
Stop tracking .env but keep it locally
Section titled “Stop tracking .env but keep it locally”First add the rule:
.envThen run:
git rm --cached .envgit rm Prepares removal of a tracked path from the next snapshot.
--cached Removes the path from Git's Index while keeping the Working Tree copy.
.env The path Git should stop tracking.
git rm --cached .envremoves.envfrom the Index and stages its removal from the next commit snapshot, while keeping the local Working Tree file on disk.
The file does not physically move between Git areas — the Working Tree,
Staging Area, and HEAD each track a different state or version of the
same content.
Before git rm –cached
- Working Tree
- .env exists
- Staging Area
- .env exists
- HEAD
- .env exists
After git rm –cached
- Working Tree
- .env still exists
- Staging Area
- .env is absent
- HEAD
- .env still exists (until the next commit)
State before the command
Section titled “State before the command”Assume .env is tracked and the repository is clean:
Working Tree: .env existsStaging Area: .env existsHEAD: .env existsAll three states agree.
State immediately after the command
Section titled “State immediately after the command”After:
git rm --cached .envthe conceptual state becomes:
Working Tree: .env still existsStaging Area: .env is absentHEAD: .env still existsThere is now a staged difference between:
Staging Area ↔ HEADThe next snapshot is prepared without .env, but HEAD still contains it
until a new commit is created.
What does git status show?
Section titled “What does git status show?”Run:
git statusExpected idea:
Changes to be committed: deleted: .envdeleted: .env means the next commit snapshot is prepared without .env.
It does not mean the Working Tree copy was deleted from the computer.
If .env matches .gitignore, the retained local copy is ignored and
normally does not appear as Untracked.
Inspecting the actual staged difference
Section titled “Inspecting the actual staged difference”Run:
git diff --stagedgit status Shows a summary of file states.
git diff --staged Shows the actual staged difference between the Staging Area and HEAD.git status does not display line-by-line differences.
What if .env is not ignored?
Section titled “What if .env is not ignored?”If the learner runs:
git rm --cached .envwithout adding .env to .gitignore, the file remains on disk but is
removed from the Index. git status may show:
- A staged deletion for the previously tracked version.
- The remaining local
.envas an untracked file.
Use this order instead:
- Add the ignore rule.
- Remove the path from the Index.
- Inspect the state.
- Commit the change.
Complete workflow
Section titled “Complete workflow”Add these rules:
.env.env.*!.env.exampleStage .gitignore:
git add .gitignoreStop tracking .env:
git rm --cached .envInspect the summary:
git statusInspect the exact staged changes:
git diff --stagedCommit:
git commit -m "build: stop tracking local environment file"Verify:
git statusgit check-ignore -v .envWhat happens after the commit?
Section titled “What happens after the commit?”Previous commit:.env exists in its snapshot
New commit:.env is absent from its snapshot
Working Tree:.env still exists locallyThe Staging Area normally matches the new commit, and the local .env is
ignored. The repository can report a clean Working Tree even though .env
remains on disk.
Is .env removed from old commits?
Section titled “Is .env removed from old commits?”No. Older snapshots may still contain it:
Old commit:.env exists
New commit:.env does not existAdding .env to .gitignore and committing its removal does not rewrite
history.
If the file contained a real password, API key, or token:
- Treat the secret as exposed.
- Revoke or rotate it.
- Create a replacement secret.
- Keep the replacement outside tracked files.
- Use a separate history-cleaning process if required.
rm versus git rm versus git rm --cached
Section titled “rm versus git rm versus git rm --cached”| Command | Working Tree | Staged result |
|---|---|---|
rm .env |
Deletes the local file | The shell command itself does not stage the deletion |
git rm .env |
Deletes the local file | Stages its deletion |
git rm --cached .env |
Keeps the local file | Stages its removal from the next snapshot |
rm is a shell command; git rm is a Git command. For this lesson’s goal,
use:
git rm --cached .envStopping tracking for a directory
Section titled “Stopping tracking for a directory”To stop tracking a directory while keeping it locally:
git rm -r --cached node_modules/The corresponding rule should exist:
/node_modules/-r Process the directory recursively.
--cached Change the Index while preserving Working Tree files.Useful patterns
Section titled “Useful patterns”# Ignore one file.env
# Ignore files by extension*.log
# Ignore a directorynode_modules/
# Ignore only the root-level directory/node_modules/
# Ignore build output/public/build/
# Ignore environment variants.env.*
# Allow the safe template!.env.example#starts a comment.*matches text.- A trailing
/represents a directory pattern. - A leading
/anchors the pattern to the location of this.gitignore. !creates an exception to a previous ignore rule.
Common mistakes
Section titled “Common mistakes”- Assuming
.gitignoreautomatically untracks files. - Using
git rmwhen the local file should remain. - Forgetting to commit the staged removal.
- Running
git rm --cachedbefore adding an ignore rule. - Thinking old commits were cleaned.
- Treating
.gitignoreas secret protection. - Ignoring dependency lock files along with dependency directories.
Command summary
Section titled “Command summary”| Goal | Command |
|---|---|
| Inspect file states | git status |
| Display ignored paths | git status --ignored |
| Check the matching rule | git check-ignore -v .env |
| Stop tracking a file but keep it locally | git rm --cached .env |
| Stop tracking a directory but keep it locally | git rm -r --cached node_modules/ |
| Inspect staged differences | git diff --staged |
| Commit the removal | git commit -m "build: stop tracking local environment file" |
Key takeaway
Section titled “Key takeaway”
.gitignorenormally prevents matching untracked paths from being shown and added. It does not retroactively untrack files.git rm --cachedstages a tracked path’s removal from the next snapshot while keeping the Working Tree copy. After the commit, Git stops tracking the path in new snapshots, but older commits remain unchanged.