KhueApps
Home/DevOps/Fix .gitignore for Files Already Tracked in Git Repos

Fix .gitignore for Files Already Tracked in Git Repos

Last updated: October 07, 2025

Overview

Symptom: you add patterns to .gitignore, but Git still shows changes for files you expected to be ignored. Root cause: .gitignore only affects untracked files. Anything already in the index remains tracked until explicitly removed from the index.

This guide shows how to untrack already tracked files safely, verify ignore patterns, and handle history if sensitive data was committed.

Quickstart (most cases)

  • Edit .gitignore to include the patterns you want.
  • Remove tracked files from the index without deleting your working copies:
# Stop tracking paths that now match .gitignore
# Replace PATHSPEC with a file, directory, or pattern
git rm -r --cached PATHSPEC

# Stage the .gitignore change and the index removals
git add .gitignore

# Commit the changes
git commit -m "Stop tracking ignored files"

Examples of PATHSPEC:

  • A single file: secrets.env
  • A directory: build/
  • Everything matching current .gitignore: . (see performance notes before using)

Minimal working example

# Start a demo repo
mkdir demo && cd demo
git init

echo "temp logs" > app.log
mkdir config && echo "API_KEY=abc" > config/dev.env

echo "(initial)" > README.md

git add . && git commit -m "initial"

# Now decide to ignore logs and env files
echo "*.log" >> .gitignore
echo "config/*.env" >> .gitignore

git status  # You'll still see app.log and config/dev.env tracked

# Fix: untrack but keep files locally
git rm --cached app.log config/dev.env

git add .gitignore

git commit -m "ignore logs and env; untrack already-tracked files"

git status  # Clean; future changes to those files are ignored

Step-by-step: robust fix

  1. Verify your .gitignore pattern matches
  • Check which rule applies:
git check-ignore -v path/to/file
  • If nothing prints, the file is not ignored by your patterns. Adjust .gitignore until this command shows a matching rule and source file.
  1. Untrack the affected files
  • Untrack specific paths:
# Preview first (dry run)
git rm -r -n --cached build/ config/*.env
# Execute
git rm -r --cached build/ config/*.env
  • To untrack everything currently ignored (use with care on large repos):
# Preview
git ls-files -ci --exclude-standard -z | xargs -0 -n50 echo
# Execute
git ls-files -ci --exclude-standard -z | xargs -0 git rm --cached -r
  1. Commit the changes
git add .gitignore
git commit -m "stop tracking ignored files"
  1. Push and coordinate
  • Push to the remote and notify teammates; they may need to pull and possibly prune their indexes similarly.
git push

If sensitive data is already in history

Untracking stops future tracking but does not remove past commits. To purge secrets or large files from history, rewrite the repository history, then force-push and rotate credentials.

  • Using git filter-repo (preferred if available):
# Remove file(s) from all history
git filter-repo --path secrets.env --invert-paths

# Or remove by glob
git filter-repo --path-glob "config/*.env" --invert-paths

git push --force --all
git push --force --tags
  • Using git filter-branch (built-in, slower):
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch secrets.env' \
  --prune-empty --tag-name-filter cat -- --all

git push --force --all
git push --force --tags

After history rewrites:

  • Invalidate caches and artifacts that may hold the data (CI, Docker layers, artifact stores).
  • Rotate any leaked credentials.

Pattern tips that often cause “not working”

  • Leading slash anchors to repo root: /build/ ignores build/ only at the root.
  • A trailing slash matches directories: logs/.
  • Use ! to unignore a subset: logs/** then !logs/keep.log.
  • Whitespace matters; escape spaces or quote in shell when testing.
  • .gitignore applies to the index; it does not delete files.

Alternatives and scope of ignoring

  • Repository-level: .gitignore (committed, shared with team).
  • Local-only (not shared): .git/info/exclude.
  • Global ignore for your user:
git config --global core.excludesFile ~/.gitignore_global

Use local or global ignores for machine-specific files (e.g., editor backups) rather than committing them to the repo.

Pitfalls and gotchas

  • Forgetting to commit .gitignore: teammates won’t benefit until it’s committed.
  • Using git rm without --cached: this deletes files from disk; always include --cached when you only want to untrack.
  • Negative rules order: later ! rules can override earlier ignores; keep patterns ordered and specific.
  • Submodules: .gitignore does not ignore submodule directories; remove the submodule entry from .gitmodules and the index instead.
  • assume-unchanged/skip-worktree: these flags hide local changes but do not ignore new files and are not shared. Use only for local, temporary workflows.
# Local-only: keep file tracked but stop seeing changes (not shared)
git update-index --skip-worktree path/to/file
# Undo
git update-index --no-skip-worktree path/to/file

Performance notes

  • Prefer targeted untracking over repo-wide operations. Use pathspecs to limit scope.
  • Always dry-run first: git rm -r -n --cached PATHSPEC.
  • On very large repos, generating full file lists can be slow. Consider:
    • Untracking only top-level directories known to be ignored (e.g., build/, dist/).
    • Running commands from the narrowest subdirectory.
  • Avoid git rm -r --cached . on monorepos unless you’ve verified the list with a dry run.

Helpful commands overview

TaskCommand
Verify a rulegit check-ignore -v PATH
Untrack file/dirgit rm --cached [-r] PATH
Preview untrackinggit rm -n --cached [-r] PATH
List cached ignoredgit ls-files -ci --exclude-standard

FAQ

  • Why does .gitignore not affect already tracked files?

    • Because .gitignore only determines which untracked files Git will consider for adding. The index keeps tracking until you remove entries from it.
  • How do I ignore a file but keep my local edits and still track it for others?

    • You cannot share that state. Use --skip-worktree locally if you must, but it’s fragile. Prefer refactoring the file into a template with a local override.
  • Will git rm --cached delete my files?

    • No. It removes paths from the index only. Your working tree files remain.
  • Do I need to run these commands on every machine?

    • Teammates pulling your commit will stop tracking the paths too, but local caches may persist. If they had local modifications, they might need to run similar commands or resolve conflicts.
  • How do I remove a secret from all history?

    • Rewrite history with git filter-repo or git filter-branch, force-push, and rotate the secret. Untracking alone is not sufficient.

Series: Git

DevOps