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
#
Rename 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. Not what I want, lets undo the rename and let git do the work.
> $ git reset HEAD .
Unstaged changes after reset:
M css/iphone.css
M index.html
Back to where I began.
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
Lets 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
#
Looks like we're good. So why didn't git recognise the rename the first time around when I used Finder?
Best thing is to try it for yourself.
Now git status and git commit --dry-run -a shows two different results where git status shows bbb.txt as a new file/ aaa.txt is deleted, and the --dry-run commands shows the actual rename.
Now go ahead and do the check-in.
Now you can see that the file is in fact renamed, and what's shown in git status is wrong.
Moral of the story: If you're not sure whether your file got renamed, issue a "git commit --dry-run -a". If its showing that the file is renamed, you're good to go.
You have to add the two modified files to the index before git will recognize it as a move.
The only difference between
mv old new
andgit mv old new
is that the git mv also adds the files to the index.mv old new
thengit add -A
would have worked, too.Note that you can't just use
git add .
because that doesn't add removals to the index.See Difference between "git add -A" and "git add ."
For
git mv
the manual page saysSo, at first you have to update the index on your own (by using
git add mobile.css
). Howevergit status
will still show two different filesYou can get a different output by running
git commit --dry-run -a
which results in what you expectI can't tell you exactly why we see these differences between
git status
andgit commit --dry-run -a
, but here is a hint from LinusA
dry-run
uses the real renaming mechanisms, while agit status
probably doesn't.That's where you went wrong.
It's only after you add the file, that git will recognize it from content.
For Xcode users: If your rename your file in Xcode you see the badge icon change to append. If you do a commit using XCode you will actually create a new file and lose the history.
A workaround is easy but you have to do it before commiting using Xcode:
renamed: Project/OldName.h -> Project/NewName.h renamed: Project/OldName.m -> Project/NewName.m
Then go back to XCode and you will see the badge changed from A to M and it is save to commit furtur changes in using xcode now.
Step1: rename the file from oldfile to newfile
Step2: git commit and add comments
Step3: push this change to remote sever