Git Mv

git mv moves or renames a file and stages the change, so Git records it as a rename rather than a delete and an add.

git mv renames or moves a file and stages the result in one step. Because both halves are staged together, Git records it as a rename — which keeps the file's history attached to it.

A plain mv is nearly as good:

git mv a b is exactly mv a b followed by git add a b. Git detects renames when it builds a diff, so using git mv is a convenience and a reminder to stage, not a requirement. Use it because it saves a step, not because plain mv loses history.

Renaming

git mv old-name.ts new-name.ts

Moving

git mv helpers/util.ts src/lib/util.ts

To a directory that already exists, the filename stays the same. To rename while moving, give both the new path and the new name.

After the fact

Git works out that a file was renamed by comparing content, so renaming outside Git and staging the result is equivalent:

mv old-name.ts new-name.ts
git add -A
git status

git status is the check worth doing after any manual rename. It lists the old path as deleted and the new one as untracked until both are staged, and git add -A is what collapses them back into a rename.

Seeing it as a rename

git diff --cached -M
git log --follow src/lib/util.ts

-M tells the diff to detect renames explicitly. --follow is the more useful one in practice: it makes git log follow a file through a rename, which is how you see a file's history even though it does not exist under that name currently.

The case git mv gets wrong

Renaming a case-only change on a case-insensitive filesystem — readme.md to README.md — needs two steps, because the second mv finds the target already there:

git mv readme.md tmp.md
git mv tmp.md README.md

Undoing it

git restore --staged <path>   # unstage, keep the file where it is now
git mv <path> <old-path>      # or just move it back

See Restore for the unstaging command, and Adding & Updating Files for the rest of the file workflow.