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
Output
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"
Output
[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
Output
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
Output
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"
Output
[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
Output
 D cheese-omelette.txt
?? breakfast/cheese-omelette.txt
$
git add -A
git status -s
Output
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
Output
ec33ed1 (HEAD -> main) Move omelette into breakfast folder
$
git log --oneline --follow -- breakfast/cheese-omelette.txt
Output
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

CommandEffect
git rm fileDelete from disk and stage the deletion
git rm --cached fileStop tracking, keep the file on disk
git rm -r folderDelete a folder and its contents
git mv old newRename or move, and stage it
git log --follow -- fileHistory 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.