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?
add+rm
ormv
- it produces the same result. Git then uses its rename/copy detection to let you know it was a rename. The source you quoted is inaccurate, too. It really doesn't matter whether you modify+rename in the same commit or not. When you do a diff across both the modify and rename, the rename detection will see it as a rename+modification, or if the modification is a total rewrite, it'll show as added and deleted - still doesn't matter how you performed it. – Cheriegit mv old new
automatically updates the index. When you rename outside of Git, you will have to do thegit add new
andgit rm old
to stage the changes to the index. Once you have done thisgit status
will work as you expect. – Modulationpublic_html
dir, that are tracked in git. Having performedgit add .
andgit commit
, it still showed a bunch of 'deleted' files ingit status
. I performed agit commit -a
and the deletions were commited but now I've no history on the files that live inpublic_html
now. This work flow is not as smooth as I'd like. – Sayersgit mv
stages the rename immediately, whereas in the manual rename, you have to stage the rename yourself before you see it as a "rename" in git status. To answer _"why didn't it detect it with my rename using Finder", it's because you didn't stage it yet. Once you stage both the delete and the untracked files, it will be detected. (Also, there's a threshold percentage of changes in the file content after which it's no longer considered a rename.) – Nozicka