为什么“git reset HEAD”不能撤消我未提交的、未暂存的更改?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21306821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 09:38:05  来源:igfitidea点击:

Why won't "git reset HEAD" undo my uncommitted, unstaged changes?

git

提问by Nilzor

I've previously been able to undo changes through SourceTree by performing the "Discard" function, which under the hood produces this command:

我以前能够通过执行“丢弃”功能通过 SourceTree 撤消更改,该功能在后台生成以下命令:

git -c diff.mnemonicprefix=false -c core.quotepath=false reset -q HEAD -- myproj.csproj 
git -c diff.mnemonicprefix=false -c core.quotepath=false checkout HEAD -- myproj.csproj

Suddenly this doesn't work. I do the Discard, no error occurs, refreesh the view, but the files are still "modified". I've then tried to do the same in the command line with the following, same result:

突然这不起作用。我做了丢弃,没有发生错误,重新刷新视图,但文件仍然被“修改”。然后我尝试在命令行中使用以下相同的结果执行相同的操作:

c:\myproject> git reset HEAD

Unstaged changes after reset:
M       myproj.csproj

Why is it still listed as an unstaged change?

为什么它仍然被列为未分阶段的更改?

I've verified that the file is indeed writable (no process is holding a lock)

我已经验证该文件确实是可写的(没有进程持有锁)

update

更新

git checkoutdidn't work either:

git checkout也没有用:

C:\myproject>git checkout myproj.csproj

C:\myproject>git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   myproj.csproj
#
no changes added to commit (use "git add" and/or "git commit -a")

Update 2Also tried:

更新 2也尝试过:

  • git checkout --
  • git checkout -- .
  • git checkout HEAD
  • git checkout --
  • git checkout -- .
  • git checkout HEAD

,none of which solves my problem

,没有一个能解决我的问题

update 3 - huge step closer:

更新 3 - 又近了一大步:

Turns out when I do the checkout, the .csproj is indeed reverted to the correct version, butthe checked out version uses a different line feed encoding. While the checked-in version has CR-LF (0D-0A) for line feed, the checked-out has only LF (0A). Hence git belives the file to be different on every single line. Why this?

事实证明,当我结帐时, .csproj 确实恢复到了正确的版本,检出的版本使用了不同的换行编码。虽然签入版本具有用于换行的 CR-LF (0D-0A),但签出版本只有 LF (0A)。因此 git 相信文件在每一行都不同。为什么这个?

update 4:added the second line of git-commands issued by SourceTree. I didn't notice that the first time around, that's why I thought git reset HEADwould do anything. This doesn't change the fact that the underlying problem still is CR/LF-related (I think)

更新 4:添加了 SourceTree 发出的第二行 git-commands。我第一次没有注意到,这就是为什么我认为git reset HEAD会做任何事情。这并没有改变潜在问题仍然与 CR/LF 相关的事实(我认为)

summaryI never found a solution to the issue, but I "solved" it by checking in the file. My original question didn't contain information that SourceTree indeed issued the correct commands to rollback what I wanted, so most answers here address that issue. The realissue is still unclear, but my main theory is that it was CR/LF related.

总结我从未找到该问题的解决方案,但我通过检入文件“解决”了它。我最初的问题不包含 SourceTree 确实发出了正确的命令来回滚我想要的东西的信息,所以这里的大多数答案都解决了这个问题。在真正的问题是,目前还不清楚,但我的主要理论是,这是CR / LF有关。

采纳答案by Thushan

If you need to remove local changes then run following command

如果您需要删除本地更改,请运行以下命令

git checkout -- file_name

git reset HEADdoes not remove local changes.

git reset HEAD不会删除本地更改。

回答by Collin K

I suspect that you had files saved with CRLF line endings in your repository, and then somewhere along the way your configuration was changed so that git started normalizing end-of-line characters (either core.autocrlf was set to true, or the .gitAttributes file was added or changed). When I ran into this problem, it turned out that a .gitAttributes file that contained * text=autohad been added to my repo.

我怀疑您在存储库中保存了带有 CRLF 行结尾的文件,然后在更改配置的过程中的某个地方,git 开始规范化行尾字符(core.autocrlf 设置为 true,或 .gitAttributes添加或更改文件)。当我遇到这个问题时,原来包含的 .gitAttributes 文件* text=auto已添加到我的存储库中。

(EOL normalization means that git will write the end-of-line characters as LF in its database, regardless of what you use in your working copy).

(EOL 规范化意味着 git 会将行尾字符写入其数据库中的 LF,无论您在工作副本中使用什么)。

Git doesn't automatically check your files to see if they require EOL normalization after you enable it. You have to explicitly tell it to check all of your files, or else you end up in this situation: the files in your repository still have CRLF line endings, and git will only notice that it should normalize them when it touches each file. So the next time you commit some changes to a file, git will write the file to its database with LF line endings.

Git 不会自动检查您的文件以查看它们在您启用后是否需要 EOL 规范化。你必须明确地告诉它检查你的所有文件,否则你最终会遇到这种情况:你的存储库中的文件仍然有 CRLF 行结尾,而 git 只会注意到它在接触每个文件时应该规范化它们。因此,下次您对文件进行一些更改时,git 会将文件以 LF 行结尾写入其数据库。

The problem occurs when git touches the file through a read operation. Say you make changes to a file that has CRLF line endings and then try to discard your changes. Git will read the clean copy from its database, see that it has CRLF line endings, and then mark the file as modified. The file has not actually been modified, but git is saying that it wants to write a change to the EOL characters to its database. This happens every time you attempt to discard your changes, check out that file, or even do a hard reset. That is why it seems to be impossible to undo those modifications.

当 git 通过读取操作接触文件时,就会出现问题。假设您对具有 CRLF 行结尾的文件进行了更改,然后尝试放弃您的更改。Git 将从它的数据库中读取干净的副本,看到它有 CRLF 行结尾,然后将文件标记为已修改。该文件实际上并未被修改,但 git 说它想将 EOL 字符的更改写入其数据库。每次您尝试放弃更改、检出该文件甚至进行硬重置时都会发生这种情况。这就是为什么似乎无法撤消这些修改的原因。

You should have git normalize the line endings on all of your text files, so this problem doesn't continue to pop up (see https://stackoverflow.com/a/4683783/1369for instructions on how to do that). If it's possible, you might even want to modify your history so the line endings are normalized at the same time the .gitAttributes settings were changed.

您应该让 git 规范化所有文本文件的行尾,这样就不会继续出现此问题(有关如何执行此操作的说明,请参阅https://stackoverflow.com/a/4683783/1369)。如果可能,您甚至可能想要修改历史记录,以便在更改 .gitAttributes 设置的同时对行尾进行规范化。

If you cannot modify your history, then you may run into situations where you need to check out old versions of your files that still have the CRLF line endings. You will probably get stuck with a list of modified files that you cannot discard and don't want to commit. In that case, you can use this work-around to essentially make git forget that it wants to modify those files:

如果您无法修改历史记录,那么您可能会遇到需要检查仍具有 CRLF 行结尾的旧版本文件的情况。您可能会遇到无法丢弃且不想提交的已修改文件列表。在这种情况下,您可以使用此变通方法基本上让 git 忘记它要修改这些文件:

  1. Check out the old version
  2. Turn off end-of-line normalization
  3. git reset
  4. Re-enable end-of-line normalization
  1. 查看旧版本
  2. 关闭行尾标准化
  3. git reset
  4. 重新启用行尾标准化

回答by zooppoop

I ran into something similar. My setup is using git on a web server to pull down the most recent code. For an unknown reason, it ran into this issue.

我遇到了类似的事情。我的设置是在 Web 服务器上使用 git 来拉取最新的代码。由于未知原因,它遇到了这个问题。

# git reset HEAD —hard

Unstaged changes after reset:

重置后未暂存的更改:

 'File Name'

I tried all the suggested things here. None fixed it.

我在这里尝试了所有建议的东西。没有人修复它。

I fix it in this case by doing

在这种情况下,我通过做来修复它

git add 'File Name'

then,

然后,

git reset --hard HEAD

Which cleared the issue for me.

这为我解决了这个问题。

回答by twalberg

"Why is it still listed as an unstaged change?"

“为什么它仍然被列为未分阶段的变化?”

Because bare git reset HEADdoes not do anything to your working tree. It only resets the HEAD pointer to the commit you name (a no-op in this case, since you name HEAD), and resets the index to match the new HEAD (which, again, is the same in this case - so the net effect is basically only throwing away any git add, git rm, etc. commands you had done).

因为裸git reset HEAD对你的工作树没有任何作用。它只将 HEAD 指针重置为您命名的提交(在这种情况下为无操作,因为您命名为 HEAD),并重置索引以匹配新的 HEAD(在这种情况下也是相同的 - 所以网络效果基本上只有扔掉任何git addgit rm等命令你做了)。

回答by CaffeineConnoisseur

I just got stuck in this situation and the only thing which fixed it was the following:

我只是陷入了这种情况,唯一修复它的是以下内容:

git log

Find the first commit in the repo and get the hash (in my case started with fdb14f)

在 repo 中找到第一个提交并获取哈希值(在我的例子中是从 fdb14f 开始的)

Note:This only works because the repo with the issue was on a Linux server while I had a remote repo "origin" on my Windows box that contained the most recent commit which fixed the CRLF issue.

注意:这只有效,因为有问题的存储库在 Linux 服务器上,而我的 Windows 机器上有一个远程存储库“源”,其中包含修复了 CRLF 问题的最新提交。

git reset --hard fdb14f
git pull origin master

After trying all kinds of different things this is what finally allowed me to get around the issue. I had fixed the CRLF issue in the most recent commit, but nothing else I tried would allow me to get around these files.

在尝试了各种不同的事情之后,这终于让我解决了这个问题。我在最近的提交中修复了 CRLF 问题,但我尝试过的任何其他方法都无法让我绕过这些文件。