Git

What Is Git RM? How to Safely Remove Files

What Is Git RM? How to Safely Remove Files

Deleting a tracked file by hand takes two steps. You remove it from disk, then you tell Git about it. git rm does both at once and stages the deletion for the next commit.

Most people use it to get rid of old files or to clear out a folder with -r. The –cached flag covers the other common job, which is untracking a local config file without touching it on disk.

The command has one limit that tutorials often skip. According to the official Git manual, no option removes a file from the working tree while keeping it in the index, and the manual points to /bin/rm for that case.

What Is git rm?

YouTube player

Plain rm deletes a file from disk and leaves Git none the wiser, so the deletion sits unstaged until you record it. git rm removes the file and records the deletion in the same go.

Git’s official manual describes the command as removing paths from the index, or from the working tree and the index together. It only touches paths Git already tracks.

That means tracked files, plus whole directories when you add -r. Untracked files get skipped. Atlassian’s Git tutorial also notes that it affects the current branch only.

The removal lands in the staging area right away, so the next commit picks it up without another command.

How Does git rm Work on the Working Tree and the Index?

YouTube player

git rm compares each target file with the tip of the current branch before it deletes anything. If the file has local edits or staged changes, the comparison fails and the command refuses. Adding -f overrides that.

Two operations in one command

The file goes off disk first, then the removal gets staged. Atlassian’s Git tutorial calls it a convenience command that combines the shell’s rm with git add on the removed path.

Nothing is permanent until the commit is made.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →

What the safety check compares

Per the official manual, the files being removed have to be identical to the tip of the branch, and no updates to their contents can be staged. The -f option overrides that default.

File stateResultWay forward
Matches the branch tip, nothing stagedRemoved from disk and indexNone needed
Edited in the working treeRefusedCommit the edits, use –cached, or use -f
Edits staged with git addRefusedCommit the edits, use –cached, or use -f
Any state, with -fRemoved regardlessUncommitted edits are lost

When Git refuses, the message offers two exits.

error: the following file has local modifications:
notes.txt
(use --cached to keep the file, or -f to force removal)

Forcing it has a real cost. The file goes away even when the edits never reached a commit, and Git cannot restore content that was never committed.

There’s one gap in the design. No option removes a file from the working tree while keeping it in the index, and the manual points to /bin/rm for that.

git rm Syntax and Options

YouTube player

The syntax is git rm [options] [--] pathspec.... Day-to-day use comes down to -r, -f, -n, –cached, –ignore-unmatch and -q, and the table below sorts out which one fits when.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

OptionEffectUse it when
-rRemoves a directory and everything under itThe pathspec is a folder
-f or –forceOverrides the up-to-date checkYou accept losing uncommitted edits
-n or –dry-runShows what would go, removes nothingBefore any recursive or wildcard run
–cachedRemoves from the index only, leaves disk files aloneUntracking a file you want to keep
–ignore-unmatchExits with status zero when nothing matchedScripts and CI jobs
-q or –quietSuppresses the per-file output lineQuiet logs

The -- separator ends option parsing, which matters when a filename starts with a dash. --pathspec-from-file reads the paths from a file (or from standard input when the file is given as a single dash), and --pathspec-file-nul switches the separator to a NUL character.

As of Git 2.56, the manual page has not changed since Git 2.50.0 (2025-06-16), according to the version history on git-scm.com.

Removing multiple files, directories and wildcard matches

YouTube player

git rm a.txt b.txt removes both files, and git rm -r build/ takes out the directory with all its subdirectories. Leave off -r and Git won’t accept a directory name at all.

Quoting matters more than people expect, because globbing in git rm matches across directory boundaries. The official examples show how much that changes.

git rm Documentation/\*.txt lets Git expand the quoted asterisk, so it removes matching files in every subdirectory. git rm -f git-*.sh lets the shell expand it, so subdir/git-foo.sh survives.

The same rule means git rm 'd*' also removes everything in a neighboring directory named d2.

Run -n first on any glob.

How to Remove a File From Git but Keep It Locally

Run git rm --cached on the file. The disk copy stays put and the path leaves the index. After the commit, the file is no longer tracked and sits on disk as an untracked file (or an ignored one, once it is listed in .gitignore).

  1. Untrack the file: git rm --cached config.local
  2. Add the path to .gitignore
  3. Check the result in git status
  4. Commit: git commit -m "Stop tracking config.local"

A quick git status check before the commit shows the deletion as staged and the file still present on disk.

Order matters here. A .gitignore file does not affect files Git already tracks, according to the official gitignore documentation (updated in Git 2.55.0, 2026-06-29).

That same documentation names git rm --cached as the way to stop tracking a file, followed by adding the name to .gitignore so later commits do not reintroduce it.

There’s a small difference from plain git rm too. With --cached, the staged content only has to match the branch tip or the file on disk, per the official manual. A file with unstaged local edits can be untracked this way, where plain git rm would refuse.

Re-applying .gitignore with git rm -r –cached

YouTube player

Run git rm -r --cached . to clear every path from the index, then git add . to stage everything that is not ignored.

  1. Preview with git rm -r --cached -n . to list what would leave the index
  2. Reset with git rm -r --cached .
  3. Re-add with git add .

The commit that follows lists only the ignored-but-tracked files as deleted, since everything else comes back unchanged.

Teammates who pull that commit will see the file deleted from their working tree. So move per-machine configs and secrets to a shared template before untracking them.

git rm vs rm, git mv and git clean

YouTube player

git rm deletes a tracked file and stages the deletion. Add --cached and it untracks the file instead. git mv handles renames, and git clean deals with untracked files.

CommandWorking treeIndexTypical goal
rmFile deletedUnchanged, deletion unstagedManual cleanup
git rmFile deletedDeletion stagedDelete a tracked file
git rm –cachedFile untouchedPath removedStop tracking, keep the file
git mvFile movedRename stagedRename or relocate a tracked file
git cleanUntracked files deletedUnchangedClear build output and stray files

git rm vs rm

After a plain rm, the deletion sits in the working tree and Git hasn’t recorded it. A few commands will fix that.

git add on the deleted path stages the removal, and the end state matches git rm. git add -u stages removals and edits for every tracked file without committing. Committing with -a notices every removal and records it on its own.

Per the official manual, committing with -a picks up every removal made with plain rm, which makes it the quickest route after a bulk delete in a file manager.

When the working tree is dirty and -a is not an option, the manual offers this one-liner to drop only the vanished paths from the index:

git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

git rm vs git mv

git mv is the rename command. git rm only deletes.

According to the official manual, git mv moves or renames a file, directory or symlink and updates the index, but the change still has to be committed. Moving several sources requires an existing destination directory, and overwriting an existing destination requires -f.

git rm vs git clean

git clean works on untracked files, the ones git rm never touches. While clean.requireForce stays at its default of true, it refuses to delete anything without -f.

Use -n to list what would go. Beyond that, -d recurses into untracked directories, -x adds ignored files, and -X removes only ignored files.

Untracked files were never committed, so no commit can bring them back. Run git clean with -n before -f, every time.

How to Undo git rm

Before the commit, run git restore –source=HEAD –staged –worktree on the path to bring back both the index entry and the file. After the commit, restore the file from the parent commit with git restore –source=HEAD~1, or revert the whole commit.

Before the commit

  1. Confirm the staged deletion in git status
  2. Run git restore --source=HEAD --staged --worktree notes.txt
  3. Check that the path no longer appears as deleted

Two separate commands also work, but the order matters. Run git restore --staged notes.txt first, then git restore notes.txt, because the working tree is restored from the index by default and the index no longer holds the path after git rm.

A removal made with --cached needs only the first of those two commands. The file never left the disk.

After the commit

git restore --source=HEAD~1 notes.txt writes the file from the parent commit back into the working tree. Stage it and commit again to make it permanent.

If you’d rather undo the whole commit, git revert adds a new commit that reverses the removal and leaves shared history untouched.

git restore first appears in the Git manual with release 2.23.0 (2019-08-16), which is why older tutorials still use git reset HEAD for the unstage step. The current manual says git restore --staged has the same effect as git reset on that path.

Does git rm Remove a File From Repository History?

YouTube player

No. git rm removes the file from the next commit forward, and every earlier commit still contains it. Purging a file means rewriting history, which is a separate operation with separate tools.

What stays behind after git rm

Earlier commits still hold the file. Clones and forks keep their own copies, and pull requests and cached views on GitHub can still point to the old commits.

Tools that purge a file from history

ToolStatusNotes
git filter-repoRecommended by the Git manual and GitHub Docs–sensitive-data-removal needs version 2.47 or later
BFG Repo-CleanerAlternative for big files and credentialsSkips the latest commit by default, needs Java 11 or above
git filter-branchManual advises against its useIts –index-filter example runs git rm –cached –ignore-unmatch on every commit

The BFG project page claims 10 to 720 times the speed of git filter-branch.

Because BFG leaves the latest commit alone, run git rm and commit first, then point the tool at the earlier commits. git filter-repo with --invert-paths needs no such step, since GitHub Docs describes it as deleting the path from all branches, tags and refs.

As of GitHub Docs in October 2026, the --sensitive-data-removal flag requires git-filter-repo 2.47 or later.

What rewriting history costs

Per GitHub Docs, a rewrite changes the commit hashes of the commit that introduced the file and of every commit after it.

Branch protection that blocks force pushes has to be switched off for a while. git filter-repo strips commit and tag signatures. Diff views of affected closed pull requests break, and comments on open ones can be lost.

Old clones are a trap too, since a plain pull followed by a push from a stale clone brings the data back. Forks keep the commits until their owners clean them.

Collaborators who branched off the old history should rebase onto the new history instead of merging, because one merge commit can reintroduce the purged data (GitHub Docs).

If the file held a password, token or key, rotate or revoke it before anything else. GitHub Docs says rotation can make the rewrite unnecessary.

git rm FAQ

Why does git rm say pathspec did not match any files?

YouTube player

The path is misspelled or Git does not track it, and the command removes only paths known to Git, per the official manual.

Check the spelling and the file’s tracked status. In scripts, add –ignore-unmatch so the command exits with status zero when nothing matches.

Can git rm delete an untracked file?

No. Untracked files fall outside what the command touches.

Delete them with plain rm, or use git clean with -n first to preview which untracked files would go.

How does git rm handle a submodule?

It removes the submodule from the working tree and deletes its section from the .gitmodules file, then stages that file. --cached and -n skip the file update.

The working tree removal covers only submodules that use a gitfile (cloned with Git 1.7.8 or newer). Older ones have their git directory moved into the superproject to protect the history.

To drop just the local checkout without committing anything, the manual points to git submodule deinit.

Does git rm delete the file from other branches or from GitHub?

YouTube player

No. The command acts on the current branch only, according to Atlassian’s Git tutorial.

Other branches keep the file. The remote copy disappears only after the deletion is committed and pushed.

A Safe Order for Removing Files on a Shared Branch

git rm is safest on a shared branch when the removal is previewed, named path by path, and reviewed in the staged diff before the commit.

  1. Preview with git rm -n on the pathspec
  2. Remove by listing each path by name
  3. Review with git diff --cached

Preview comes first because it costs nothing. Review comes last because git diff --cached shows the exact change the commit will record, as long as -a is not used (GitHub Docs).

The sources disagree on one shortcut. The Git manual presents git commit -a as the quick way to record removals made with plain rm, while GitHub Docs advises against it.

On a shared branch, follow GitHub Docs, since -a also commits every other edit to tracked files.

The price is two extra commands per removal, and a git cheat sheet keeps them close at hand.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.