I'd read that when renaming files in Git, you should commit any changes, perform your rename and then stage your renamed file. Git will recognise the file from the contents, rather than seeing it as a new untracked file, and keep the change history.
However, doing just this tonight I ended up reverting to git mv.
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
I renamed my stylesheet in Finder from iphone.css to mobile.css:
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: css/iphone.css
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# css/mobile.css
So Git now thinks I've deleted one CSS file, and added a new one. It is not what I want. Let’s undo the rename and let Git do the work.
> $ git reset HEAD .
Unstaged changes after reset:
M css/iphone.css
M index.html
I am back to where I began:
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
Let's use git mv instead:
> $ git mv css/iphone.css css/mobile.css
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: css/iphone.css -> css/mobile.css
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: index.html
#
It looks like we're good. So why didn't Git recognise the rename the first time around when I used Finder?

For
git mvthe manual page saysSo, at first, you have to update the index on your own (by using
git add mobile.css). Howevergit statuswill still show two different files:You can get a different output by running
git commit --dry-run -a, which results in what you expect:I can't tell you exactly why we see these differences between
git statusandgit commit --dry-run -a, but here is a hint from Linus:A
dry-runuses the real renaming mechanisms, while agit statusprobably doesn't.