Rename or Move a File
Goal: Track file renames with git mv, and understand why Git has no rename to track.
Projects get tidied up: utils.js becomes src/lib/format.js, readme.txt becomes README.md. Git handles this well, but not in the way most people expect.
Git does not store renames
A commit is a snapshot of file contents at paths, not a list of edits. There is no "rename" entry to record. When you move a file, Git simply sees one path disappear and another appear with the same contents.
Git works the rename out afterwards, when it shows you history, by noticing that the deleted and added files are identical (or nearly so). This is called rename detection, and it is why renaming a file and heavily editing it in the same commit can show up as a delete plus an add.
What the three areas see
Step 1 of 3
Working Tree
Empty
Staging Area
Empty
Repository
- notes.txt
notes.txt is committed and unchanged.
Step 1 of 3. `notes.txt` is committed and unchanged.
What git status says after a staged rename
$ git status
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) renamed: notes.txt -> docs/notes.md
Git prints renamed: because the staged delete and the staged add have identical contents. Change the file as well and the same state is reported as a separate deleted: and new file:.
Two ways to do the same thing
git mv old new
- Moves the file and stages the change
- One command, nothing left half-done
- Refuses to overwrite an existing file unless you pass
-f
Move it in your editor
- Git sees an untracked file and a missing one
- You then run
git add old new, orgit add . - Exactly the same commit in the end
