
The difference between git mv and plain mv is small but worth knowing. git mv moves the file and stages the change in one step. mv only changes the disk, so we have to tell Git what happened. The same goes for git rm and rm.
Git does not store renames as a special action. It stores snapshots, and when we run git status or git log it detects that a deleted file and a new file have the same content, and labels the pair a rename. That is why both routes below end in the same place.
Moving or renaming
| Plain commands | Git commands | |
|---|---|---|
| Move or rename | mv old.js new.js |
git mv old.js new.js |
| What Git sees | old.js deleted, new.js untracked |
rename, already staged |
| Extra steps | git rm old.js and git add new.js |
none |
With git mv
git mv old_name.js new_name.js
git status --shortR old_name.js -> new_name.js
The rename is staged and ready to commit.
With plain mv
mv old_name.js new_name.js
git status --short D old_name.js
?? new_name.js
Git sees a deleted file and an untracked file. Staging only the new one is a common mistake:
git add new_name.js
git status --shortA new_name.js
D old_name.js
The deletion is still unstaged, so a commit now would contain the new file but leave the old one in the repository. We need to stage both:
git rm old_name.js # stages the deletion (the file is already gone from disk)
git add new_name.jsor, in one step:
git add -AR old_name.js -> new_name.js
git add -A is also the easy way to stage a whole batch of manual moves, or renames done in a file manager or editor such as VS Code.
git mv only works on files Git already tracks. For an untracked file it stops with fatal: not under version control, so use plain mv there.
Deleting
| Plain command | Git command | |
|---|---|---|
| Delete a file | rm file.txt |
git rm file.txt |
| What Git sees | deleted, not staged | deleted, staged |
rm file.txt
git status --short # D file.txt (not staged)
git rm file.txt
git status --short # D file.txt (staged)git rm also works after the file has already been removed by hand, as above: it just stages the deletion.
Stop tracking a file but keep it on disk
If we committed a file by mistake, such as a .env with secrets, we want Git to forget it without deleting our copy:
git rm --cached .env
git status --shortD .env
?? .env
The file stays on disk, but Git now lists it as untracked. To keep it from being added again, put it in .gitignore.
git rm --cached removes the file from future commits only. It stays in the repository’s history, so a secret that was committed should be treated as exposed and changed.
Rename history
After a rename, git log --follow lists the commits from before the rename too:
git log --follow --oneline new_name.jsWithout --follow, the log of the new name starts at the rename.
Summary
git mv=mv+ staging. Plainmvplusgit add -Agives the same result.git rm=rm+ staging.git rm --cachedstops tracking and keeps the file.- Git detects renames from the content, so both routes give the same commit.