似乎无法在Git中丢弃更改

159

在命令行中看到以下内容:

# On branch RB_3.0.10
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   index.htm

我试图通过输入以下命令来放弃我的更改:

git checkout -- index.htm

但是当我重新运行 git status 命令时,看起来完全相同。检出好像没有生效。我做错了什么吗?我在 windows/cygwin 上使用 GIT 1.6.1.2。

# On branch RB_3.0.10
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   index.htm

4
git checkout HEAD -- index.htm (从最后一次提交的状态进行检出,而不是从索引中检出) 是否可行? - Jakub Narębski
3
“git checkout HEAD -- index.htm” 对我有用! - Ben Tideswell
https://dev59.com/hnI-5IYBdhLWcg3wF0Uc - Ohad Schneider
24个回答

101

这件事困扰了我一段时间,几乎每个我检查过的仓库都有一些我不能放弃的更改。长话短说,我尝试了以上所有方法,但都没有起作用。以下是我为使事情恢复正常所做的事情(在Mac上):

Completely remove the autocrlf & safecrlf settings from ~/.gitconfig
Completely remove the autocrlf & safecrlf settings from your repo's local config ./.git/config
git rm --cached -r .
git reset --hard

14
尝试了以上所有方法后,这是唯一在我的Windows电脑上起作用的方法。 - Anders
谢谢!和Anders说的一样,这个解决方案对我也有效。我用# autocrlf替换了autocrlf。 - David
到目前为止,唯一让它在Windows上运行的方法。谢谢。 - row
只有这个方法对我有效。非常感谢! - GuruJeya

47
这是我的经验;在.git/config配置文件中设置以下变量:
[core]
    autocrlf = false
    safecrlf = false
    eol = crlf

之后运行$ git checkout HEAD .是有效的,但运行$ git checkout -- .却不行 - 真奇怪! * git版本1.9.3

37
git diff显示文件有哪些变化?在Windows上,换行符可能会导致类似这样的问题。在这种情况下,请查看您对git config core.autocrlfgit config core.safecrlf设置的内容。此处有一些关于这些设置的文档

我建议,如果您正在使用git svn与子版本进行集成,请确保关闭autocrlf设置。据我所知,在此配置中,该设置已损坏,并且它会使大多数工具认为文件已更改,当您执行checkout以撤消任何更改时。

如果您发现一个问题,您执行git checkout,然后git status显示文件仍被修改,而git diff显示文件在每一行都被修改,则是您所见到的问题。

core.autocrlf

如果为true,则使git在从文件系统读取文本文件时将行末CRLF转换为LF,并在写入文件系统时进行反向转换。可以将变量设置为input,这样只有在从文件系统读取时才进行转换,但是文件带有LF作为行末。当前基于内容纯粹决定要考虑哪些路径作为“文本”(即受到autocrlf机制的影响)。

core.safecrlf

如果为true,则使git检查由core.autocrlf控制的CRLF是否可逆转。Git将验证命令是否以直接或间接方式修改工作树中的文件。例如,提交文件,然后检出相同的文件应该在工作树中产生原始文件。如果对于core.autocrlf的当前设置不是这种情况,则git将拒绝该文件。变量可以设置为

"警告",在这种情况下 git 仅会发出一个无法逆转的转换的警告,但是继续操作。

core.autocrlf=truecore.safecrlf没有被设置。在Windows中应该将其设置为true吗?这两者有什么区别? - gemini929
如果你正在使用git svn,我建议两个都不要开启。我添加了一些更详细的内容。 - 1800 INFORMATION
4
我理解他的意思是将其旋转至少90度。 - vijrox
2
当我将core.autocrlf和core.safecrlf都设置为true时,通过运行'git reset --hard HEAD'命令,我能够放弃检测到的有问题文件中的更改。 - Aleksey
1
感谢您建议使用 git diff。我一直在努力找到差异所在,但并不是行尾问题,大多数答案都建议更改行尾格式和配置。然而,在运行 git diff 后,我意识到文件模式(权限)是不同的。 - Nagabhushan S N

28

我认为你需要传递-f

根据手册页面(man git-checkout, GIT-CHECKOUT(1)):

-f, --force
即使索引或工作树与HEAD不同也继续进行。
这用于放弃本地更改

例如,丢弃当前分支上的更改并切换到另一个分支:

git checkout -f master

7
传达 -f 是用来做什么的?完整的回答会更好。 - PandaWood
@Matt 我的意图不是要检出一个不同的分支。这个答案是来自2009年,所以我真的不记得了,但根据问题的判断,我想我是想传递 -f 到 checkout -- <filename>,就像 git checkout -f -- filename 这样。 - hasen
@hasen 你之前的三条评论都是在要求澄清,这就是为什么我加了“例如”的原因。这个例子并不排除 -f 的其他用途。 - Matt H
对我来说有效。git checkout -f master 抛出了“已经在'master'上”的错误,但更改已经消失了。 - Christian
对我也起作用。与上面那些提议相比,我觉得使用-f更安全。 - daparic

17

可能是换行符的问题,正如@1800-information所建议的那样,但另一个可能是文件模式的差异(这可能阻止您使用checkout命令还原这些文件)。这就是我的情况。在我的git版本上,您可以通过使用

git diff index.htm

来发现它显示文件模式更改。即使使用-f选项,它也不会让你使用checkout还原它们。要解决这个问题,请使用

git config core.filemode false

或者通过在文本编辑器中添加以下内容来更改git .config:

[core]

filemode = false
执行此操作后,您可以使用

git reset HEAD index.htm

文件应该会消失。

(我从如何使git忽略模式更改(chmod)?仅更新Git中文件权限的答案中获取了所有这些内容。)


非常感谢!其他建议都没有帮助我摆脱文件模式更改的问题。 - Thorkil Værge
谢谢,这解决了我在Windows上的问题。 - Dody Rachmat Wicaksono

7

我的问题与这里类似,我刚刚发现git正在跟踪文件权限的更改。 我尝试了放弃和重置分支,但是这些文件仍然存在。 运行 git config --get --local core.filemode,如果值为true,则需要将其设置为false以关闭对文件权限的跟踪。 运行git config --local core.fileMode false应该解决问题。 您可以在此处阅读更多信息。


2
在我的情况下,我尝试了被接受的解决方案,但是它并没有起作用。当我执行 git diff 命令时,它抱怨文件权限的问题。所以当我将 core.fileMode 设置为 false 并重新运行以下命令时: git rm --cached -r . git reset --hard - Narasimha
这是唯一对我有效的方法 - Alan Draper
这个设置对我来说很有效。不知道为什么 git config --global core.fileMode false 不起作用。 - snowfox

5
你是在使用OSX还是Windows操作系统?如果是的话,问题可能是由于存在两个文件名相同但大小写不同的文件。例如:index.htm和Index.htm。
Windows和默认的OSX使用的是大小写不敏感的文件系统,这与大小写敏感的git冲突了。

我认为这就是我的问题所在,一个名为doCheckoutdocheckout的文件,重置其中一个只会使另一个出现。解决方案是什么? - Max Cascone

4

我曾经遇到过这个问题,试过上面的所有方法都无效。

对我有效的方法是删除该文件所在的目录,然后执行git status检查该目录中的所有文件是否都被标记为删除状态。之后,我只需执行git checkout -f就能使一切恢复正常。


2

我曾遇到同样的问题,以上评论中的解决方案均未奏效。最终发现我的文件系统是不区分大小写的(这是OSX的默认设置,但Windows也可能有类似的情况),一个目录下同时存在大小写不同但内容不同的文件。由于在我的计算机上这两个名称都指向同一个文件,因此无论我做什么,git status 始终会显示修改状态。以下是解决方法:

  • 从另一台计算机删除其中一个文件并将其推送到repo上

  • 完全删除本地版本

  • 从头开始进行 git clone


1
我最终执行了git stash,然后执行git stash clear来清除一些东西。在.git/或~/.git文件中没有看到任何自动cr/lf配置。

1
喜欢这个,简单又快速。只是它是“清晰的”,而不是“干净的”。 - Line

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