Git:如何恢复顽固地卡在“已更改但未提交”的 2 个文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6335521/
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
Git: How to revert 2 files that are stubbornly stuck at "Changed but not committed"?
提问by Greg Hendershott
I have a repo that has two files that supposedly I changed locally.
我有一个 repo,其中有两个文件,据说我在本地更改了这些文件。
So I'm stuck with this:
所以我坚持这个:
$ git status
# On branch master
# 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: dir1/foo.aspx
# modified: dir2/foo.aspx
#
no changes added to commit (use "git add" and/or "git commit -a")
Doing git diff
says that the entire file contents have changed, even though from eyeballing it that seems untrue (there seem to be common line ranges that diff seems to be failing to see).
Doinggit diff
表示整个文件内容都发生了变化,即使从眼球上看似乎是不真实的(似乎有 diff 似乎没有看到的公共行范围)。
Interestingly I don't remember changing these files locally. This repo is used with one remote repo (private, at GitHub.com, FWIW).
有趣的是,我不记得在本地更改过这些文件。此存储库与一个远程存储库(私有,位于 GitHub.com,FWIW)一起使用。
No matter what I've tried, I can't discard these local changes. I have tried all of:
无论我尝试过什么,我都不能放弃这些本地更改。我已经尝试了所有:
$ git checkout -- .
$ git checkout -f
$ git checkout -- dir1/checkout_receipt.aspx
$ git reset --hard HEAD
$ git stash save --keep-index && git stash drop
$ git checkout-index -a -f
In other words I've tried everything described in How do I discard unstaged changes in Git?plus more. But the 2 files remain stuck as "changed but not committed".
换句话说,我已经尝试了如何丢弃 Git 中未暂存的更改中描述的所有内容?加上更多。但是这两个文件仍然停留在“已更改但未提交”状态。
What the heck would cause two files to be stuck like this and seemingly "un-revert-table"??
到底是什么会导致两个文件像这样卡住并且看似“取消还原表”?
P.S. In the list above showing commands I'd already tried, I mistakenly wrote git revert
when I meant git checkout
. I'm sorry and thank you to those of you who answered that I should try checkout
. I edited the question to correct it. I definitely did already try checkout
.
PS 在上面显示我已经尝试过的命令的列表中,git revert
我的意思是git checkout
. 我很抱歉并感谢那些回答我应该尝试的人checkout
。我编辑了问题以更正它。我确实已经尝试过了checkout
。
采纳答案by Tekkub
What are the line endings in the files? I'm betting they're CRLF. If they are, check out this guide: http://help.github.com/line-endings/
文件中的行尾是什么?我打赌他们是 CRLF。如果是,请查看本指南:http: //help.github.com/line-endings/
In short, you need to make sure git is set to convert the line endings to LF on commit, and then commit those files. Files in the repo should always be LF, files checked out should be the OS's native, assuming you set git correctly.
简而言之,您需要确保将 git 设置为在提交时将行尾转换为 LF,然后提交这些文件。存储库中的文件应该始终是 LF,检出的文件应该是操作系统的本机,假设您正确设置了 git。
回答by Alan Forsyth
I spent hours trying to solve a similar issue - a remote branch that I had checked out, which stubbornly showed four files as 'Changed but not updated', even when deleting all files and running git checkout -f
again (or other variations from this post)!
我花了几个小时试图解决一个类似的问题 - 我检查过的一个远程分支,它顽固地将四个文件显示为“已更改但未更新”,即使删除所有文件并git checkout -f
再次运行(或本文中的其他变体)!
These four files were necessary, but certainly hadn't been modified by me. My final solution - persuade Git that they had not been changed. The following works for all checked out files, showing 'modified' status - make sure you have already committed/stashed any that have really been modified!:
这四个文件是必须的,但肯定没有被我修改过。我的最终解决方案 - 说服 Git 他们没有被改变。以下适用于所有签出的文件,显示“已修改”状态 - 确保您已经提交/隐藏了任何真正被修改的文件!:
git ls-files -m | xargs -i git update-index --assume-unchanged "{}"
On Mac OSX, however xargs operates a little bit different (thx Daniel for the comment):
在 Mac OSX 上,但是 xargs 操作有点不同(感谢 Daniel 的评论):
git ls-files -m | xargs -I {} git update-index --assume-unchanged {}
I've added this as a placeholder for myself for next time, but I hope it helps someone else too.
我已将其添加为下一次自己的占位符,但我希望它对其他人也有帮助。
-Al
-Al
回答by Abu Assar
this is how I fixed the same problem in my case: open .gitattributes change:
这就是我在我的情况下解决相同问题的方法:打开 .gitattributes 更改:
* text=auto
to:
到:
#* text=auto
save and close , then revert or reset, thanks to @Simon East for the hint
保存并关闭,然后还原或重置,感谢@Simon East 的提示
回答by Eyal
Another possibility is that the difference (that's preventing your from reverting these files with a checkout command) is one of file mode. This is what happened to me. On my version of git you can discover this by using
另一种可能性是差异(阻止您使用 checkout 命令恢复这些文件)是文件模式之一。这就是发生在我身上的事情。在我的 git 版本上,您可以通过使用来发现这一点
git diff dir1/foo.aspx
git diff dir1/foo.aspx
And it will show you file mode changes. It still won't let you revert them, though. For that use either
它将向您显示文件模式更改。但是,它仍然不会让您还原它们。为此使用
git config core.filemode false
git 配置 core.filemode 假
or change your git .config in your text editor by adding
或通过添加更改您的文本编辑器中的 git .config
[core]
filemode = false
[核]
filemode = false
After you do this, you can use
完成此操作后,您可以使用
git reset HEAD dir1/foo.aspx
git reset HEAD dir1/foo.aspx
and the file should disappear.
并且文件应该消失。
(I got all of this from the answer to How do I make git ignore mode changes (chmod)?)
(我从How do I make git ignore mode changes (chmod)?的答案中得到了所有这些信息?)
回答by Simon East
I had some phantom changed files that were showing as modified, but were actually identical.
我有一些虚拟更改的文件显示为已修改,但实际上是相同的。
Running this command sometimesworks:
(Turns off git's "smart" but often unhelpful line-ending conversions)
运行此命令有时有效:(
关闭 git 的“智能”但通常无用的行尾转换)
git config --local core.autocrlf false
But in another case I found it was due to a .gitattributes
file in the root which had some line-ending settings present, which was trying to apply autocrlf
for certain files even when it was turned off. That wasn't actually helpful, so I deleted .gitattributes
, committed, and the file no longer showed as modified.
但在另一种情况下,我发现这是由于.gitattributes
根目录中的一个文件存在一些行结束设置,autocrlf
即使它被关闭,它也试图申请某些文件。这实际上并没有帮助,所以我删除了.gitattributes
,提交了,并且文件不再显示为已修改。
回答by Tadeck
Try to revert local changes:
尝试恢复本地更改:
git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx
回答by smexy
You also might have had a problem related to directories naming letter cases. Some of your colleagues could have changed the name of the directory from e.g. myHandlerto MyHandler. If you later on pushed and pulled some of the files of the original directory you would have had 2 separate directorieson the remote repository AND only one on your local machinesince on Windows you only can have just one. And you're in trouble.
您也可能遇到与目录命名字母大小写相关的问题。您的某些同事可能已将目录名称从例如myHandler 更改为MyHandler。如果您稍后推送和拉取原始目录的一些文件,您将在远程存储库上有2 个单独的目录,而在您的本地计算机上只有一个,因为在 Windows 上您只能有一个。而你有麻烦了。
To check if that is the case, just see if the remote repository has double structure.
要检查是否是这种情况,只需查看远程存储库是否具有双重结构。
To fix this, make a backup copy of the parent directory outside of the repo, then delete the parent directory, push it. Make a pull (here's when the second one marked as deleted should appear on status) and push again. After that, recreate the whole structure from your backup and push the changes again.
要解决此问题,请在 repo 之外制作父目录的备份副本,然后删除父目录,将其推送。拉动(这是标记为已删除的第二个应该出现在状态上的时候)并再次推动。之后,从备份中重新创建整个结构并再次推送更改。
回答by Marinos An
I think it would be helpful to provide a hint on how to reproduce the issue, in order to better understand the problem:
我认为提供有关如何重现问题的提示会很有帮助,以便更好地理解问题:
$ git init
$ echo "*.txt -text" > .gitattributes
$ echo -e "hello\r\nworld" > 1.txt
$ git add 1.txt
$ git commit -m "committed as binary"
$ echo "*.txt text" > .gitattributes
$ echo "change.." >> 1.txt
# Ok let's revert now
$ git checkout -- 1.txt
$ git status
modified: 1.txt
# Oooops, it didn't revert!!
# hm let's diff:
$ git diff
warning: CRLF will be replaced by LF in 1.txt.
The file will have its original line endings in your working
directory.
diff --git a/1.txt b/1.txt
index c78c505..94954ab 100644
--- a/1.txt
+++ b/1.txt
@@ -1,2 +1,2 @@
-hello
+hello
world
# No actual changes. Ahh, let's change the line endings...
$ file 1.txt
1.txt: ASCII text, with CRLF line terminators
$ dos2unix 1.txt
dos2unix: converting file 1.txt to Unix format ...
$ git diff
git diff 1.txt
diff --git a/1.txt b/1.txt
index c78c505..94954ab 100644
--- a/1.txt
+++ b/1.txt
@@ -1,2 +1,2 @@
-hello
+hello
world
# No, it didn't work, file is still considered modified.
# Let's try to revert for once more:
$ git checkout -- 1.txt
$ git status
modified: 1.txt
# Nothing. Let's use a magic command that prints wrongly committed files.
$ git grep -I --files-with-matches --perl-regexp '\r' HEAD
HEAD:1.txt
2nd way to reproduce:In the above script replace this line:echo "*.txt -text" > .gitattributes
withgit config core.autocrlf=false
and keep the rest of the lines as is
第二种重现方式:在上面的脚本中替换此行:echo "*.txt -text" > .gitattributes
使用git config core.autocrlf=false
并保持其余行不变
What all the above say?A text file can(under some circumstances) be
committed with CRLF, (e.g. -text
in .gitattributes
/ or core.autocrlf=false
).
以上都是怎么说的?可以(在某些情况下)使用 CRLF 提交文本文件(例如-text
在.gitattributes
/ 或 中core.autocrlf=false
)。
When we later want to treat the same file as text (-text
-> text
) it will need to be committed again.
Of course you can temporarily revert it (as correctly answered by Abu Assar). In our case:
当我们稍后想要将同一个文件视为文本 ( -text
-> text
) 时,它需要再次提交。
当然,您可以暂时还原它(正如Abu Assar正确回答的那样)。在我们的例子中:
echo "*.txt -text" > .gitattributes
git checkout -- 1.txt
echo "*.txt text" > .gitattributes
The answer is: do you really want to do that, because it's gonna cause the same problem everytime you change the file.
答案是:您真的想这样做吗,因为每次更改文件时都会导致相同的问题。
For the record:
作为记录:
To check which files can cause this problem in your repo execute the following command (git should be compiled with --with-libpcre):
要检查仓库中哪些文件会导致此问题,请执行以下命令(git 应使用 --with-libpcre 编译):
git grep -I --files-with-matches --perl-regexp '\r' HEAD
By committing the file(s) (supposing that you want to treat them as text), it is the same thing as doing what is proposed in this link http://help.github.com/line-endings/for fixing such problems. But, instead of you removing .git/index
and performing reset
, you can just change the file(s), then perform git checkout -- xyz zyf
and then commit.
通过提交文件(假设您想将它们视为文本),这与执行此链接http://help.github.com/line-endings/ 中提出的解决此类问题的方法相同. 但是,您可以只更改文件,然后执行然后提交,而不是删除.git/index
和执行。reset
git checkout -- xyz zyf
回答by Steve Prentice
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx
回答by Zhenya
For me the issue was not about line endings. It was about changing case in folder name (Reset_password -> Reset_Password). This solution helped me: https://stackoverflow.com/a/34919019/1328513
对我来说,问题不在于行尾。这是关于更改文件夹名称的大小写(Reset_password -> Reset_Password)。这个解决方案帮助了我:https: //stackoverflow.com/a/34919019/1328513