mat_boy
mat_boy

Reputation: 13666

IntelliJ marks files of GIT repository as untracked after moving to new package

When I do a refactoring in IntelliJ 2017.3 for a Java project hosted on a git repository and

  1. Create a new package
  2. Move existing tracked and committed Java classes into the new package following IntelliJ recipe

these Java classes becomes red (i.e. untracked files) instead of being green (tracked and modified files). If I commit I lose the whole history of the file, and annotations report me to be the first one to commit.

Am I doing the refactoring wrong or is it a bug from IntelliJ? Is there any way to correctly move the files?

Upvotes: 2

Views: 1779

Answers (2)

Mark Adelsberger
Mark Adelsberger

Reputation: 45659

First let's talk about git, because the issue starts there.

In git there is no such thing as "moving" a file. When you change a file's package, you change its location on the file system; but to git, that means you deleted the file in one place and created a new file in another place.

Sometimes git will report that a file was moved or renamed. If it sees that (1) a file disappeared, and (2) another file appeared, and (3) it determines based on configurable metrics - based on the degree to which the new file content is the same as the old file content - that this was likely intended as a move of a single file... then it says the file moved. But internally it doesn't believe it; it's just trying to help you make sense of things.

And if git reports that a file was moved, then likely other commands will at least have the option to follow the file move through history. For example, git blame (the command for annotating files) does try to follow "whole-file renames" (per the docs).

Now, you say that manually moving files works better but that letting your IDE move them due to changing packages works poorly. The most likely reason would be if the file content was changed significantly in the same commit as the move. For a package-change refactor, we know there's at least a minor content change; but you may want to minimize inclusion of other changes to the file in the same commit.

So if git doesn't believe in file movement, what, then, is git mv? It is a shorthand that creates the file at the new location while removing it from the old location (as git sees things) and stages those changes. It does not make git any more (or less) likely to succeed in understanding that the file was renamed; it just automates the process a bit. Note that if you move a file without git mv, it will show up as "deleted file" and "untracked file" until you stage the changes, at which point rename detection will kick in.

so it is likely that when you "manually" move a file, either you're using git mv or you're using the IDE (which is using git mv or equivalent commands). But when you do a refactor, that operation may not be smart enough to ensure that the change is staged, so it looks different. Nonetheless, once the change is staged and committed, the effect will be the same whether the IDE's refactoring tools were used for the file move or not. (Again, for a particular file this behavior may be subject to how much of the content changed.)

Upvotes: 5

mat_boy
mat_boy

Reputation: 13666

To keep the history of moved files:

  1. Move the files to the new package
  2. Do git add of the untracked files (i.e. those moved)
  3. Via command line do git rm of the moved files in the old path (they are marked as deleted when doing git status)

Upvotes: -1

Related Questions