Skip to content

/commands/git/git-rm-cached-stop-tracking-file

Stop tracking a file but keep it locally: git rm --cached

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · git version 2.55.0.windows.5updated
tool
Git
versions
Git 2.x
os
any

git rm --cached FILE removes FILE from Git's index, so the next commit deletes it from the repository, but leaves the file on your disk. Combine it with a .gitignore entry so it is not added again. .gitignore alone does nothing for files that are already tracked: it only affects untracked files.

Example

A log file was committed by mistake:

bash
git init -q repo && cd repo
printf 'print("hi")\n' > app.py
printf 'debug output\n' > debug.log
git add . && git commit -q -m "initial"
echo "debug.log" > .gitignore
printf 'more output\n' >> debug.log
echo "--- .gitignore alone: still tracked"
git status --short
git rm -q --cached debug.log
git add .gitignore
git commit -q -m "Stop tracking debug.log"
echo "--- tracked files"
git ls-files
echo "--- still on disk"
ls
git status --short --ignored

Output

--- .gitignore alone: still tracked
 M debug.log
?? .gitignore
--- tracked files
.gitignore
app.py
--- still on disk
app.py
debug.log
!! debug.log

!! debug.log in git status --ignored confirms the file is now ignored, and it is still in the working directory.

Errors you may see

Directories need -r. Without it Git refuses:

bash
git init -q repo && cd repo
mkdir build && echo x > build/out.bin
git add . && git commit -q -m "initial"
git rm --cached build

Output · exit 128

fatal: not removing 'build' recursively without -r

A name that is not tracked fails with pathspec did not match any files; check the exact path with git ls-files. When the index holds a version that differs from both the last commit and the file on disk, Git stops with error: the following file has staged content different from both the file and the HEAD and suggests -f; with --cached -f, only that staged version is discarded and the file on disk is kept.

Directories and patterns

bash
git rm -r --cached node_modules        # a whole directory
git rm --cached '*.log'                # quoted so Git expands the pattern, not the shell
git rm -r --cached . && git add .      # re-apply .gitignore to everything (review the diff before committing)

To keep a tracked file in the repository but ignore your local changes to it, git rm --cached is the wrong tool; git update-index --skip-worktree FILE does that for one clone.

Variants

CommandEffect
git rm --cached FILEUntrack FILE, keep it on disk
git rm -r --cached DIRUntrack a directory and everything in it
git rm --cached -n FILEDry run: show what would be removed
git rm FILEUntrack FILE and delete it from disk
git restore --staged FILEUnstage a change but keep the file tracked
git update-index --skip-worktree FILEKeep the file tracked and ignore local changes in this clone

If you only staged a file by mistake and never committed it, git restore --staged is the simpler command.

FAQ

Will git rm --cached delete the file for my teammates?

Yes. When they pull the commit, Git removes the file from their working tree because it is no longer tracked. Ask them to back it up first if it holds local settings.

Why is my file still tracked after adding it to .gitignore?

.gitignore only applies to untracked files. A file that is already in the index stays tracked until you remove it with git rm --cached and commit.

What is the difference between git rm and git rm --cached?

git rm removes the file from the index and deletes it from the disk. git rm --cached removes it only from the index, so the next commit drops it from the repository while your copy stays.

Sources