Applying .gitignore to committed files
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
.gitignore only affects files Git is not already tracking. If a file was committed in the past, adding it to .gitignore does not automatically remove it from the index. The fix is to stop tracking that file while leaving it on disk, then commit the index change so future updates stay ignored.
Understand the Difference Between Tracked and Ignored
Git has two separate ideas here:
- tracked files are already in the index
- ignored files are untracked paths Git should not stage automatically
That is why this sequence surprises people:
- commit
config.local.json - add
config.local.jsonto.gitignore - edit the file
- Git still shows it as modified
The file is still tracked, so .gitignore has no effect yet.
Remove the File from the Index, Not from Disk
The standard fix is:
--cached removes the file from the Git index but keeps the working copy on disk. That is exactly what you want for machine-local config, build artifacts, and secret files that should stay present locally but disappear from version control.
Then add the ignore rule:
After the commit, future changes to that file stay untracked.
Handle Directories the Same Way
If an entire directory was committed and should now be ignored, remove it recursively from the index:
And add the ignore pattern:
This is common for editor settings, build output, dependency caches, and generated assets.
Check That the Ignore Rule Actually Matches
If Git still shows the file after you removed it from the index, confirm the pattern works:
This command shows which .gitignore rule matched the path. It is useful when:
- the ignore pattern is in the wrong directory
- the path is matched by a negation rule
- a wildcard is broader or narrower than intended
Do not guess. Check the actual rule evaluation.
Know When History Rewriting Is Needed
Stopping tracking today does not erase the file from previous commits. If the committed file contains secrets, simply adding it to .gitignore is not enough. You may need to rotate the secret and rewrite repository history with an appropriate history-cleaning tool.
That is a separate operation from normal ignore cleanup. The basic git rm --cached flow only affects commits going forward.
For ordinary noise files such as IDE metadata or local logs, history rewriting is usually unnecessary. For secrets, it is often mandatory.
Coordinate with the Team
If other developers already have the tracked file in their clones, your commit will remove it from version control for everyone on the next pull. That is often correct, but it should not be a surprise.
A common safe pattern is:
- commit the
.gitignorechange - remove the file from tracking with
git rm --cached - document whether teammates should keep or regenerate a local replacement
This matters especially for local config templates. You may want to keep a committed example file such as config.example.json while ignoring the real machine-specific file.
Common Pitfalls
- Assuming
.gitignoreautomatically untracks files that were already committed. - Running
git rmwithout--cachedand deleting the working file from disk unintentionally. - Forgetting to verify whether the ignore pattern actually matches the intended path.
- Treating forward-looking ignore cleanup as if it removed sensitive data from past commits.
- Ignoring the team impact when a once-tracked local file disappears from the repository.
Summary
- '
.gitignoredoes not apply retroactively to tracked files.' - Use
git rm --cachedto remove a file from the index while keeping it locally. - Add or verify the ignore rule so future changes stay untracked.
- Use the same approach for directories with
-r --cached. - If the file contained secrets, handle history cleanup and credential rotation separately.

