17

One of the great things about using an IDE for Java is the automated refactorings you get. The problem I'm having is that after using Refactor > Move to move a class into a different package (which moves the file itself in the filesystem), git status shows that the file in the old location has been deleted, and the one in the new location has been added.

The workaround I've found is clunky:

mv src/com/example/newpackage/Foo.java src/com/example/oldpackage/Foo.java
git mv src/com/example/oldpackage/Foo.java src/com/example/newpackage/Foo.java

Is there any way (when using the Git plugin for Eclipse) to have the refactoring do a git mv instead of a naive filesystem move?

Josh Glover
  • 25,142
  • 27
  • 92
  • 129
  • What is the actual status you're getting after moving? Are both changes (the add and the remove) staged? If so, try a `git diff --cached -M`. I've found that occasionally you have to tell git to detect a rename, in particular because it's detected afterwards. – deterb Jul 26 '11 at 14:02
  • git shows me that the old file was deleted and the new one is untracked (thus not staged). I tried the `git diff --cached -M`, and see the new location as a new file. What should I be looking for? – Josh Glover Jul 28 '11 at 09:48
  • 1
    That's why you're not seeing the change then. Git isn't going to do anything with a new file until it's in the index (it's moved there by staging). If you stage the new file, both `git status` and `git diff --cached -M` will report the change as a rename. If there are too many changes in the diff, add `--name-status` and it'll just show the similarity index (in the form RXX, where XX is the percent similarity). – deterb Jul 28 '11 at 12:56
  • 1
    Actually, staging both files still doesn't report a rename; it reports a delete and a new file. – Josh Glover Jul 28 '11 at 14:09
  • From http://stackoverflow.com/questions/2641146/handling-file-renames-in-git/2641227#2641227 it looks like git may not do the rename detection (which can be an expensive operation) for git status by default. Try the `git commit --dryrun` command they recommend there. Did the `git diff cached -M` report the rename? If so, was the simularity index high? I did my testing with just a file move and a very small amount of change, the refactoring may have had many more changes which may have reduced it too much. – deterb Jul 28 '11 at 21:29

1 Answers1

13

That's the way how Git works with renames/moves (delete old file and add new file). It then detects the contents of the file, and recognizes a rename based on an algorithm. So even it shows you delete and add, if you commit and then do a "git log --follow movedfilename", it should show you the whole history, even the history before the rename.

dunni
  • 43,386
  • 10
  • 104
  • 99
  • OK, `git log --name-only` does show me that only the new file was changed as well, so I guess I'm happy enough. I was just getting hung up on `git status` not showing me "renamed", but it looks like it matters not a whit when examining commits. Clever git! Thanks for the education, dunni. :) – Josh Glover Jul 28 '11 at 10:02
  • 8
    Important to notice this does not work if while you "move" the file you also modify its content. In that case git will only see this as a delete/add. You need to make sure to stage/commit your move changes (or content changes) in two independent steps. – Roberto Andrade Oct 07 '13 at 21:18