The Hook (The "Byte-Sized" Intro)
Deleting a file with rm is fine for your OS — but Git has no idea it happened. Renaming with mv? Git sees it as "one file deleted, one new file created." Use git rm and git mv instead, and Git tracks the change properly — your history stays clean, blame works correctly, and nobody panics during code review.
📖 What is git rm and git mv?
These commands handle file deletion and renaming within Git's tracking system. They perform the filesystem operation AND stage the change in one step, keeping your repository history clean and consistent.
Conceptual Clarity
| Command | What It Does | Equivalent Manual Steps |
|---|---|---|
git rm file.txt | Deletes the file AND stages the deletion | rm file.txt + git add file.txt |
git mv old.txt new.txt | Renames/moves the file AND stages the change | mv old.txt new.txt + git add new.txt + git add old.txt |
git rm --cached file.txt | Removes from tracking but keeps the file on disk | Untrack only (useful for secrets accidentally committed) |
Key insight: Git doesn't have a native "rename" concept. Internally, git mv is a delete + add. Git detects renames by comparing file contents using a similarity index (files >50% similar = rename).
Real-Life Analogy
git rm= Removing a book from the library catalog AND from the shelf in one step. Just throwing the book away (plainrm) leaves a ghost entry in the catalog.git mv= Moving a book to a new shelf and updating the catalog simultaneously. Just moving the book (plainmv) confuses the librarian.
Visual Architecture
Why It Matters
- Clean history:
git mvpreserves rename detection, sogit log --followcan track a file across renames. - One step: Both commands do the filesystem change + staging in a single command.
- Untracking secrets:
git rm --cachedremoves a file from Git without deleting it — essential for accidentally committed.envfiles. - Code review clarity: Diffs show clean renames instead of confusing delete+add pairs.
Code
# ─── Delete a tracked file ───
git rm old-feature.js
git status
# Output: deleted: old-feature.js (staged)
git commit -m "Remove deprecated feature module"
# ─── Rename/move a file ───
git mv utils.js helpers.js
git status
# Output: renamed: utils.js -> helpers.js (staged)
git commit -m "Rename utils to helpers for clarity"
# ─── Move a file to a different directory ───
git mv config.json src/config/config.json
git commit -m "Move config to src/config directory"
# ─── Untrack a file but keep it on disk ───
git rm --cached .env
echo ".env" >> .gitignore
git add .gitignore
git commit -m "Remove .env from tracking, add to gitignore"
# The .env file still exists locally but Git no longer tracks it
# ─── Force delete a modified, staged file ───
git rm -f modified-file.js
# Use -f when the file has staged changes Git wants to protect
# ─── Remove an entire directory ───
git rm -r old-tests/
git commit -m "Remove old test directory"
# ─── Track renames through history ───
git log --follow --oneline helpers.js
# Shows full history including before the renameCommon Scenarios
| Scenario | Command |
|---|---|
| Delete a file | git rm file.txt |
| Rename a file | git mv old.txt new.txt |
| Move to a directory | git mv file.txt dir/file.txt |
| Untrack without deleting | git rm --cached file.txt |
| Delete a directory | git rm -r directory/ |
| Force-delete modified file | git rm -f file.txt |
Key Takeaways
- Use
git rmandgit mvinstead of plainrm/mv— they stage the change automatically. git rm --cacheduntracts a file without deleting it from disk — essential for secret files.- Git detects renames by content similarity, not by filename —
git mvhelps ensure clean detection. - Use
git log --followto trace a file's history across renames.
Interview Prep
-
Q: What is the difference between
rm file.txtandgit rm file.txt? A:rmonly deletes the file from the filesystem.git rmdeletes the file AND stages the deletion for the next commit. With plainrm, you'd still need to rungit add file.txtto stage the change. -
Q: How do you stop tracking a file without deleting it? A: Use
git rm --cached <file>. This removes the file from Git's index (staging area) but leaves it on disk. You should then add the file to.gitignoreto prevent re-tracking. -
Q: Does Git natively track renames? A: No. Git has no explicit rename concept. It detects renames after the fact by comparing file contents — if a deleted file and a new file share >50% similarity, Git reports it as a rename.
git mvperforms the delete+add cleanly to help this detection.