git stash和pop命令显示文件不再标记为移动?

40
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知道文件已经移动了? 我经常使用stash查看更改前的系统状态,但它失去重命名关系对我来说是个问题。除了删除新文件,再次执行git mv并替换新文件内容,我不知道如何解决这个问题。


1
注意:尝试在 Git 2.12(2017年第一季度)再次尝试会很有趣。请参见https://dev59.com/03vaa4cB1Zd3GeqPFJnT#41307892。 - VonC
2个回答

50

如果你还没有使用你的stash,请执行以下操作:

git stash pop --index

这个方法可以正确地在暂存区中保留已移动(但未提交)的文件关系。根据git help stash的说明:

如果使用了 --index 选项,则尝试还原工作树的更改和索引的更改。然而,当存在冲突时(存储在索引中),这可能会失败,因为您无法像最初那样应用更改。

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

git rm --cached file1

这将从索引中删除"旧"未移动的文件:

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


2
我不知道这是否比@Jefromi的答案更好。 - Andy Ray
2
如果你记得第一次就这样做,那么git stash pop --index会更好。但是如果你之前忘记了弹出索引,git rm --cached file1将使你回到文件2被重命名的状态。 - Mike Monkiewicz
2
有点烦人。为什么 Git 总是有这些小毛病,似乎只是为了让你措手不及!? - Steve
@Steve 因为它不是bzr :-( - Theodore R. Smith
git stash pop --index 对我没有起作用,文件仍被标记为已删除和新文件。 - Mossmyr

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),问题就会得到解决。

如果您不想暂存某些更改,您可以在*nix上使用以下命令:git diff --name-status | grep ^D | cut -f2 | grep 'some/example/path/' | xargs git rm --cached。只需修改第二个grep以按文件路径过滤即可。 - Vladislav Yundin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接