16

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

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

当我这样做时,git status我得到

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

我已经尝试add过新rm的和旧的,反之亦然,我不断得到

$ 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 的多个答案,但它们没有奏效。

4

3 回答 3

19

git book中的相关部分对此进行了解释。

与许多其他 VCS 系统不同,Git 不会显式跟踪文件移动。如果您在 Git 中重命名文件,Git 中不会存储任何元数据来告诉它您重命名了该文件。然而,Git 非常聪明地在事后弄清楚这一点——我们稍后会处理检测文件移动。

What this means is that if you move a file and then make significant changes git will not know that it was a move. It will see a file deleted and a new file created because the new file doesn't look like the old one. To get around this people often git mv files, commit the move, and then make changes. In your situation you can do

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
于 2013-01-25T17:42:00.667 回答
7

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

于 2013-01-25T17:37:01.950 回答
3

Commands to implement @Nevik Rehnel's suggestion of two commits by rewriting history to move the file before it's edited:

Starting condition:

  • your most recent commit includes both a move and modification to a file and git log --follow newpath shows the file as newly created in the most recent commit

Steps:

  • Tag your current status git tag working_code
  • Start an interactive rebase to edit the history: git rebase -i HEAD~2
    • in the editor that pops up, change "pick" on the first line to "edit", save and exit.
  • Your are now editing history just before your commit
  • Create the move as its own commit
    • git mv oldpath newpath
    • The directory to contain the new file location has to exist; you may have to mkdir it first
    • (optionally) Edit the file with any small changes needed to accompany the file rename (ex: in Java: class name and/or package and import lines) - Avoid making other changes Git detects these as the same file based on similarity
    • git add . and check that git status now shows: renamed: oldpath -> newpath
    • git commit -m "Rename oldpath newpath"
  • git rebase --continue
    • You should get a conflict on newpath. Restore the file with git checkout working_code newpath
    • Complete the rebase: git rebase --continue
  • Verify that git log --follow newpath shows the full history
于 2015-07-24T21:26:00.963 回答