Moving and Deleting Files
Deleting or renaming a tracked file is a change like any other: it needs to be staged and committed. You can do it with ordinary file commands and then stage the result, or let git rm and git mv do both steps at once.
Deleting a file
If you delete a tracked file normally, Git notices the deletion but doesn't stage it:
rm toast-draft.txt git status
On branch main Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: toast-draft.txt no changes added to commit (use "git add" and/or "git commit -a")
Stage the deletion with git add (or git rm on the missing file), then commit:
git add toast-draft.txt
git commit -m "Remove toast draft"
[main 158d8bf] Remove toast draft 1 file changed, 1 deletion(-) delete mode 100644 toast-draft.txt
git rm does both at once — it deletes the file from disk and stages the deletion:
git rm granola.txt git status -s
rm 'granola.txt' D granola.txt
Deleting a file only affects future snapshots. The file still exists in every earlier commit, so you can always get it back (lesson 16).
Removing from Git but keeping the file
git rm --cached removes a file from the repository while leaving it on your disk — the usual fix for a file that should have been ignored (lesson 14). To remove a whole folder, add -r: git rm -r --cached build/.
If a file has changes that haven't been committed, git rm refuses to delete it, to protect your work. -f forces it.
Renaming and moving
git mv renames or moves a file and stages the change:
git mv omelette.txt cheese-omelette.txt git status
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) renamed: omelette.txt -> cheese-omelette.txt
mkdir breakfast
git mv pancakes.txt breakfast/
git commit -m "Organise recipes"
[main b12c5f4] Organise recipes 2 files changed, 0 insertions(+), 0 deletions(-) rename pancakes.txt => breakfast/pancakes.txt (100%) rename omelette.txt => cheese-omelette.txt (100%)
Git doesn't actually store renames. It records that one path disappeared and another appeared, then detects renames by comparing contents: if a deleted file and a new file are mostly the same, it reports a rename. That means renaming with your file manager or editor works just as well, as long as you stage both sides:
mv cheese-omelette.txt breakfast/ git status -s
D cheese-omelette.txt ?? breakfast/cheese-omelette.txt
git add -A git status -s
R cheese-omelette.txt -> breakfast/cheese-omelette.txt
Before staging, Git saw a deletion (D) and an untracked file (??). After git add -A it pairs them as a rename (R). A rename combined with heavy edits may show up as a delete plus an add; that's harmless, but renaming in one commit and editing in the next keeps the history clearest.
Following a file through renames
git log on a single path normally stops where the file got its current name. --follow continues past renames:
git log --oneline -- breakfast/cheese-omelette.txt
ec33ed1 (HEAD -> main) Move omelette into breakfast folder
git log --oneline --follow -- breakfast/cheese-omelette.txt
ec33ed1 (HEAD -> main) Move omelette into breakfast folder b12c5f4 Organise recipes 8f53e6c Add recipes
Case-only renames
On Windows and macOS the file system usually ignores letter case, so renaming readme.md to README.md in a file manager may not be noticed by Git. Use git mv readme.md README.md, which handles it correctly.
Summary
| Command | Effect |
|---|---|
git rm file | Delete from disk and stage the deletion |
git rm --cached file | Stop tracking, keep the file on disk |
git rm -r folder | Delete a folder and its contents |
git mv old new | Rename or move, and stage it |
git log --follow -- file | History of a file including before renames |
Try it yourself
Commit three files, then in one commit: delete one with git rm, rename another with plain mv, and move the third into a new folder with git mv. Check that git status -s shows one D and two R lines before committing.