How to Remove a File from Git Without Deleting It Locally

• 3 min read

If you’ve ever accidentally committed a config file, secret, or environment-specific file to Git, you’ve probably run into this situation:

“I want Git to stop tracking this file — but I don’t want it deleted from my machine.”

This guide covers both:

  1. How to stop Git from tracking a file while keeping it locally.
  2. How to completely remove it from Git history if it ever contained secrets.

The common case: stop tracking, keep local copy

You have a file that:

  • is already tracked by Git
  • is still useful locally
  • should not live in the repository

Common examples:

  • terraform.tfvars
  • .env
  • secrets.yaml
  • local kubeconfig files

Solution: git rm --cached

git rm --cached path/to/file
git commit -m "Remove file from version control"

This tells Git:

  • ❌ stop tracking the file
  • ✅ keep the file on disk

Your local copy remains untouched.


Don’t forget to ignore it

After removing the file from Git, add it to .gitignore so it doesn’t get added again later:

echo "terraform.tfvars" >> .gitignore
git add .gitignore
git commit -m "Ignore terraform.tfvars"

Removing multiple files

git rm --cached *.tfvars
git commit -m "Stop tracking tfvars files"

Or remove an entire directory:

git rm --cached -r secrets/
git commit -m "Remove secrets directory from repo"

Verify the file is no longer tracked

git status
git ls-files | grep terraform.tfvars

If nothing is returned, Git is no longer tracking the file.


⚠️ Important: this does NOT remove it from history

If the file was committed in the past, it still exists in:

  • commit history
  • pull requests
  • forks and clones

If the file contained secrets, assume they are compromised.


To permanently remove a file from all commits, use git filter-repo
(the modern replacement for git filter-branch).

Step 1: Install git filter-repo

brew install git-filter-repo        # macOS
# or
pip install git-filter-repo

Step 2: Rewrite history to remove the file

git filter-repo --path terraform.tfvars --invert-paths

This:

  • removes the file from every commit
  • rewrites repository history

Step 3: Force-push the cleaned history

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

⚠️ This is a breaking change:

  • collaborators must re-clone or reset
  • old commit hashes will no longer exist

After rewriting history (checklist)

  • 🔁 Rotate all affected secrets immediately
  • 📣 Notify collaborators
  • 🧹 Ask others to re-clone:
    git clone <repo>
    or hard-reset:
    git fetch --all
    git reset --hard origin/main

When you should rewrite history

✅ Do this if:

  • secrets were committed
  • credentials were public even briefly
  • compliance or security matters

❌ Skip it if:

  • the file never contained sensitive data
  • the repo is very large and widely cloned
  • risk is low and acceptable

TL;DR

  • Stop tracking a file (keep local copy):
    git rm --cached <file>
  • Prevent it from coming back:
    echo "<file>" >> .gitignore
  • Completely erase it from history:
    git filter-repo --path <file> --invert-paths
    git push --force --all

This is an essential Git pattern for Terraform, Kubernetes, and any repo that evolves from local experimentation into real infrastructure.