tags:

views:

888

answers:

5

I've moved a file manually and then I've modified it. According to Git, it is a new file and a removed file. Is there any way to force Git into treating it as a file move?

+4  A: 

Do the move and the modify in separate commits.

Hank Gay
I understand that Git is can handle moves and modifications at the same time. When programming in Java and using an IDE, renaming a class is both a modification and a move. I understand that Git even should be able to automatically figure it out when there's a move (out of a remove and a creation).
J. Pablo Fernández
Perl requires this too, and I have never not had Git detect the move/rename.
jrockway
+12  A: 

Git will automatically detect the move/rename if your modification is not too severe. Just git add the new file, and git rm the old file. git status will then show whether it has detected the rename. If it hasn’t you need to follow Hank Gay’s advice and make two separate commits.

Bombe
Clarification: 'not too severe' means that the new file and old file are >50% 'similar' based on some similarity indexes that git uses.
pjz
+12  A: 

Its all a perceptual thing. Git is generally rather good at recognising moves, because GIT is a content tracker

All that really depends is how your "stat" displays it. The only difference here is the -M flag.

git log --stat -M

commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date:   Fri Jan 9 22:13:51 2009 +1300


        Category Restructure

     lib/Gentoo/Repository.pm                |   10 +++++-----
     lib/Gentoo/{ => Repository}/Base.pm     |    2 +-
     lib/Gentoo/{ => Repository}/Category.pm |   12 ++++++------
     lib/Gentoo/{ => Repository}/Package.pm  |   10 +++++-----
     lib/Gentoo/{ => Repository}/Types.pm    |   10 +++++-----
     5 files changed, 22 insertions(+), 22 deletions(-)

git log --stat

commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date:   Fri Jan 9 22:13:51 2009 +1300

    Category Restructure

 lib/Gentoo/Base.pm                |   36 ------------------------
 lib/Gentoo/Category.pm            |   51 ----------------------------------
 lib/Gentoo/Package.pm             |   41 ---------------------------
 lib/Gentoo/Repository.pm          |   10 +++---
 lib/Gentoo/Repository/Base.pm     |   36 ++++++++++++++++++++++++
 lib/Gentoo/Repository/Category.pm |   51 ++++++++++++++++++++++++++++++++++
 lib/Gentoo/Repository/Package.pm  |   41 +++++++++++++++++++++++++++
 lib/Gentoo/Repository/Types.pm    |   55 +++++++++++++++++++++++++++++++++++++
 lib/Gentoo/Types.pm               |   55 -------------------------------------
 9 files changed, 188 insertions(+), 188 deletions(-)

git help log

   -M
       Detect renames.

   -C
       Detect copies as well as renames. See also --find-copies-harder.
Kent Fredric
Sorry if this seems a bit pedantic, but "Git is generally rather good at recognising moves, because GIT is a content tracker" seems like a non-sequitur to me. It's a content tracker, yes, and perhaps it happens to be good at detecting moves, but the one statement doesn't really follow from the other. Just because it's a content tracker the move detection isn't necessarily good. In fact, a content tracker could have no move detection at all.
Laurence Gonsalves
+5  A: 

git diff -M or git log -M should automatically detect such changes as a rename with minor changes as long as they indeed are. If your minor changes are not minor, you can reduce the similarity threashold, e.g.

$ git log -M20 -p --stat

to reduce it from the default 50% to 20%.

+1  A: 

This is a quick solution if you've renamed a file, made some changes to it, Git doesn't realize it's a rename, and you haven't committed your changes. Let's say the file was named 'blah' and now it's named 'foo'.

1) Rename 'foo' to a temp name:

% mv foo foo.tmp

2) Checkout 'blah':

% git checkout blah

3) Rename 'blah' to 'foo' so that Git knows about it:

% git mv blah foo

4) Now rename 'foo.tmp' back to 'foo'.

% mv foo.tmp foo

This last step is what gets your changed content back into 'foo'.

Hope that makes sense.

cully
This process serves no purpose. git doesn't add any metadata for renames, `git mv` is simply a convenience for a `git rm`/`git add` pair. If you've already done 'mv bar foo', then all you have to do is make sure that you've `git add foo` and `git rm bar` before making the commit. This could be as done as a single `git add -A` command, or possibly a `git add foo; git commit -a` sequence.
Charles Bailey
All I know is that before I did it, Git didn't recognize it as a move. After I did this, Git recognized it as a move.
cully