Moving & Renaming (git mv)
git mv renames or moves a file and stages that change in one step. It is identical to running the OS-level move followed by two git add commands. You can also rename files with your editor or with plain mv — Git will figure out it was a rename when you stage the deletion and the addition.
Renaming a file
The simple form
git mv old-name.js new-name.js git status # renamed: old-name.js -> new-name.js git commit -m "Rename old-name.js to new-name.js"
Moving a file
git mv src/utils.js lib/utils.js # moves the file into a different folder git mv components/Header.js components/header/Header.js # can rename and move at the same time
Moving a folder
git mv src/components src/views # every file inside is moved as a rename git status # renamed: src/components/Header.js -> src/views/Header.js # renamed: src/components/Footer.js -> src/views/Footer.js
git mv vs plain mv
git mv old newis exactly equivalent to:mv old new && git add new && git rm old.If you prefer to rename in your file explorer or editor, that is fine — Git will detect the rename when you stage both the deletion and the addition.
Git does NOT track renames; it detects them when you ask. Rename detection is based on content similarity at commit time.
Rename detection
When you git status or git diff shows "renamed: A -> B", Git is inferring it from similarity. By default, files that are 50% similar are considered renamed. You can tune this:
Tweaking rename detection
git config --global diff.renames true # default on modern Git git diff -M70% # require 70% similarity to call it a rename git diff -B # break apart and re-pair files even more aggressively git log --follow path/to/file.js # follow through renames
git mv on a folder vs `git mv -r`
Unlike git rm, git mv does not need a -r flag. Pointing it at a directory moves the directory and everything inside it.
Forcing overwrite
When the target already exists
git mv -f old.js new.js # Use only when you really want to overwrite new.js
Dry run
git mv -n old-name.js new-name.js # Would move old-name.js -> new-name.js # (no change made yet)
Following a file across renames
git log normally stops at a rename — --follow continues
git log --follow -p src/new-name.js # shows history before AND after the rename
Common mistakes
Renaming a file outside Git and forgetting to stage both halves —
git statuswill then show one deletion and one untracked file. Rungit add -Aand Git will collapse them into a rename automatically.Renaming with a typo —
git mvdoes not validate that the new path is sensible. Rungit mvagain to fix.Renaming files on case-insensitive filesystems (macOS/Windows by default) — e.g.,
mv Foo.js foo.jsmay not register a rename. Usegit mvexplicitly:git mv Foo.js foo.js(Git is case-sensitive even when the FS is not).
Case-only renames on macOS / Windows
The two-step trick
git mv Foo.js TEMP_NAME.js git mv TEMP_NAME.js foo.js # Two moves are needed because the FS thinks Foo.js == foo.js
git config --global core.ignorecase false to make Git case-sensitive — then case-only renames work in one step.Don’t fear renames
A rename is not a delete + create from Git’s perspective — the file’s history follows it (with
--follow).git blamekeeps working after a rename, telling you who wrote each line of the renamed file.PR review tools show renames as one row rather than two, when they detect the rename.