Git无法识别重命名和修改的包文件

我有一个名为package/old/myfile.java的java文件。 我通过git提交了这个文件。 然后我将我的包重命名为new所以我的文件在package/new/myfile.java

我现在想将此文件重命名(和内容更改)提交给git。

当我做git status我得到了

 # Changes not staged for commit: # (use "git add/rm ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # deleted: package/old/myfile.java # # Untracked files: # (use "git add ..." to include in what will be committed) # # package/new/myfile.java 

我已经尝试add新的和旧的,反之亦然,我一直在努力

 $ git status # On branch develop # Changes to be committed: # delete: package/old/myfile.java # new file: package/new/myfile.java 

我不能做mv old new因为旧文件不存在,所以我得到了bad source错误。

还有什么我可以尝试的吗?

我已经在SO上尝试了一些针对类似问题的多个答案,但它们没有奏效。

git书中的相关部分解释了这一点。

与许多其他VCS系统不同,Git没有明确跟踪文件移动。 如果你在Git中重命名文件,Git中没有存储元数据,告诉你重命名了文件。 然而,Git非常聪明地确定了事后的结果 – 稍后我们会处理检测文件移动的问题。

这意味着如果您移动文件然后进行重大更改,git将不会知道这是一个移动。 它将看到一个文件被删除并且创建了一个新文件,因为新文件看起来不像旧文件。 为了解决这个问题,人们经常git mv文件,提交移动,然后进行更改。 在你的情况下,你可以做到

 git reset # Move changes from index to working copy git checkout package/old/myfile.java # Undo delete git mv package/old/myfile.java package/new/myfile.java # Move file 

将文件移回,然后提交,并将实际移动放入单独的提交中。 Git不会记录移动(或重命名),但可以根据内容识别它们。 如果内容发生变化,则无法正确检测到移动。 因此,通常的做法是将移动和更改分成两个提交。

用于实现@Nevik Rehnel建议的两个提交的命令,通过重写历史记录来在编辑之前移动文件:

开始条件:

  • 您最近的提交包括对文件的移动和修改以及git log --follow newpath将文件显示为最近提交中新创建的文件

脚步:

  • 标记您当前的状态git tag working_code
  • 启动交互式rebase来编辑历史记录: git rebase -i HEAD~2
    • 在弹出的编辑器中,将第一行的“选择”更改为“编辑”,保存并退出。
  • 您现在正在提交之前编辑历史记录
  • 将移动创建为自己的提交
    • git mv oldpath newpath
    • 必须存在包含新文件位置的目录; 你可能要先mkdir
    • (可选)使用文件重命名所需的任何小改动来编辑文件(例如:在Java中:类名和/或包和导入行) – 避免进行其他更改 Git根据相似性将这些更改检测为同一文件
    • git add . 并检查git status现在显示: renamed: oldpath -> newpath
    • git commit -m "Rename oldpath newpath"
  • git rebase --continue
    • 你应该在newpath上发生冲突。 使用git checkout working_code newpath恢复文件
    • 完成rebase: git rebase --continue
  • validationgit log --follow newpath显示完整历史记录