37
git mv file1 file2

git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    file1 -> file2

git stash
git stash pop

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   file2
#
# 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:    file1

如您所见,git 在 stash / pop 之后失去了重命名的关系。有没有办法恢复这种关系,或者让 stash 知道文件被移动了?我经常隐藏以查看我的系统状态是什么样的预更改,但是让它失去重命名关系对我来说是个问题。除了删除新文件,再次执行 git mv 并替换新文件的内容之外,我不知道如何修复它。

4

2 回答 2

48

如果您还没有弹出您的存储,请执行以下操作:

git stash pop --index

这正确地保留了存储中移动(但未提交)的文件关系。根据git help stash

如果使用 --index 选项,则不仅尝试恢复工作树的更改,还尝试恢复索引的更改。但是,当您遇到冲突时(存储在索引中,因此您不能再像原来那样应用更改),这可能会失败。

如果您已经弹出您的存储并且想要重新创建移动的关系,请执行以下操作:

git rm --cached file1

这会从索引中删除“旧”未移动的文件:

使用此选项仅从索引中取消暂存和删除路径

于 2011-12-13T21:04:05.363 回答
21

简短的回答:git rm --cached file1

真正要做git mv的就是重命名文件(在文件系统上),然后将文件删除和创建添加到索引(暂存区)。它没有特别标记。其他机器随后通过看到以前称为 file1 的内容现在称为 file2 来意识到这是一个重命名。

由于git stash命令会修改索引,因此它们会扰乱事物。请注意,现在您已经完成了创建,但没有删除!(通常 git-stash 会在弹出后保留所有内容,但在这种情况下,我认为除了将新文件放在索引中之外别无选择,以避免您不知道要保留哪个文件。您可以避免这种情况曾经发生过git stash pop --index,但是如果无法干净地应用隐藏的更改,那么它就会爆炸,因此它不是默认值。)git status不可能再将其显示为重命名,因为重命名有效地在索引和工作树之间拆分,任何部分都不能完全声称它。

只需运行git rm --cached file1以暂存删除(即从索引中删除 file1),它将再次显示为重命名。您也可以运行git add -u以自动添加更改,只要您没有不想暂存的其他更改。

请注意,这意味着在实践中您不必担心:当您正确地暂存所有内容以准备提交时(例如使用git add -u),“问题”会自行解决。

于 2011-12-13T20:05:43.797 回答