Setup & configAlways fixable

Fix a .gitignore that isn't ignoring files

Why is .gitignore not working for files that are already tracked?

Short answer

.gitignore only applies to untracked files. Once a file has been committed, Git keeps tracking it no matter what the ignore rules say. Remove it from the index with git rm --cached <file> — that stops tracking while leaving the file on your disk.

quick fix
git rm --cached path/to/file
git commit -m "Stop tracking file"

Untracks the file without deleting it from your computer

Does this match your situation?

  • You added a file to .gitignore but it still appears in git status.
  • node_modules, bin/, obj/, Library/ or .env keep showing up as modified.
  • Ignore rules work for teammates but not for you (or vice versa).

Step-by-step fix

  1. Check why Git isn't ignoring it

    check-ignore names the exact rule and file that matched — or tells you nothing matched, which means the file is tracked and ignore rules simply don't apply.

    step 1
    git check-ignore -v path/to/file
    

    No output means no rule matched. Output means the rule matched but the file is already tracked.

  2. Stop tracking the file, keep it on disk

    --cached removes the file from Git's index only. Your local copy is untouched, but Git stops following it and the ignore rule takes effect from now on.

    step 2
    git rm --cached .env
    
    # a whole directory:
    git rm -r --cached node_modules/
    
    git commit -m "Stop tracking files covered by .gitignore"
    

    Without --cached, git rm deletes the file from your disk too.

  3. Reset the whole index when several files are involved

    If the ignore file has drifted a long way from reality, it's cleaner to clear the index and re-add everything — Git then honours the current rules for every path at once.

    step 3
    git rm -r --cached .
    git add .
    git commit -m "Apply .gitignore to the whole repository"
    
  4. Check your ignore-rule syntax

    Most 'broken' ignore files are pattern mistakes. Directories need care, negation only works if the parent directory isn't excluded, and a leading slash anchors to the repo root.

    step 4
    node_modules/          # a directory, at any depth
    /build                 # only at the repository root
    *.log                  # every .log file
    !important.log         # except this one
    Library/               # Unity: never commit this
    **/bin/                # bin at any depth
    
  5. Remember the file stays in history

    Untracking stops future commits from including the file, but every existing commit still contains it. If it held a secret, that secret is still in history and must be purged and rotated.

    step 5
    git log --all --oneline -- .env
    

Why this works

Git divides files into tracked and untracked, and .gitignore is only consulted for untracked ones. That design is deliberate: once you've explicitly told Git to manage a file, a stray ignore pattern shouldn't silently stop recording your changes to it. So the fix isn't to adjust the pattern but to move the file back to untracked status, which is exactly what git rm --cached does — it deletes the index entry while leaving the working file alone.

How to stop it happening again

  • Create .gitignore before your first commit — gitignore.io generates one for your stack.
  • For Unity, ignore Library/, Temp/, Obj/, Build/, Logs/ and UserSettings/ from the very start.
  • Use a global ignore file for editor and OS junk: git config --global core.excludesFile ~/.gitignore_global.

Commands used in this guide

git status

Show what's changed, what's staged, and what Git is ignoring.

git restore

Throw away working-directory changes or unstage files (the modern, clearer replacement for checkout).

git filter-repo

Rewrite an entire repository's history - the supported way to purge a leaked secret or a huge file.

git add

Stage changes so they go into your next commit.

Still stuck?

Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.

Browse all guides →

Frequently asked questions

Why is .gitignore not working?

Almost always because the file is already tracked. .gitignore only affects untracked files, so a committed file keeps being tracked regardless of ignore rules. Run git rm --cached <file> to untrack it, then commit.

How do I untrack a file without deleting it?

git rm --cached <file>. The --cached flag removes it from Git's index while leaving your local copy in place. Omit --cached and Git deletes the file from your disk as well.

How do I apply .gitignore to files already committed?

git rm -r --cached . followed by git add . and a commit. This clears the index and rebuilds it while honouring the current ignore rules, so everything newly covered gets untracked in one commit.

Does untracking remove the file from history?

No. Every previous commit still contains it. If the file held credentials, you also need to rewrite history with git filter-repo — and rotate the credentials, since they should be considered compromised.

Related rescue guides

← All Git Rescue guides