关于github:Git:如何还原2个固执地陷入“已更改但未提交”的文件?

Git: How to revert 2 files that are stubbornly stuck at “Changed but not committed”?

我有一个repo,有两个文件,据说我在本地更改。

所以我坚持这个:

1
2
3
4
5
6
7
8
9
10
$ 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")

git diff表示整个文件内容已经改变了,即使从眼球看起来似乎是不真实的(似乎有共同的行范围似乎没有看到)。

有趣的是我不记得在本地更改这些文件。此仓库与一个远程仓库(私人,GitHub.com,FWIW)一起使用。

无论我尝试过什么,我都不能放弃这些局部变化。我尝试了所有:

1
2
3
4
5
6
$ 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

换句话说,我已经尝试了如何在Git中丢弃未分级的更改中描述的所有内容?加上更多。但是这两个文件仍然被"改变但未提交"。

什么导致两个文件被卡住这样看似"un-revert-table"?

附:在上面显示我已经尝试过的命令的列表中,当我的意思是git checkout时,我错误地写了git revert。对不起,谢谢那些回答我应该尝试checkout的人。我编辑了问题来纠正它。我肯定已经尝试过了checkout


我花了好几个小时试图解决一个类似的问题 - 我检查过的一个远程分支,它固执地显示四个文件为'已更改但未更新',即使删除所有文件并再次运行git checkout -f(或此帖子的其他变体) )!

这四个文件是必要的,但我当然没有修改过。我的最终解决方案 - 说服Git他们没有被改变。以下适用于所有已检出文件,显示"已修改"状态 - 确保您已经提交/存储了任何已经修改过的文件!:

1
git ls-files -m | xargs -i git update-index --assume-unchanged"{}"

在Mac OSX上,然而xargs运行有点不同(丹尼尔评论):

1
git ls-files -m | xargs -I {} git update-index --assume-unchanged {}

我下次已将此作为占位符添加到我自己,但我希望它也可以帮助其他人。

-Al


文件中的行结尾是什么?我打赌他们是CRLF。如果是,请查看本指南:http://help.github.com/line-endings/

简而言之,您需要确保将git设置为在提交时将行结尾转换为LF,然后提交这些文件。 repo中的文件应始终为LF,检出的文件应该是操作系统的本机,假设您正确设置了git。


这就是我在我的情况下修复同样问题的方法:
打开.gitattributes
更改:

1
* text=auto

至:

1
#* text=auto

保存并关闭,然后恢复或重置,
感谢@Simon East提示


另一种可能性是差异(阻止您使用checkout命令恢复这些文件)是文件模式之一。这就是发生在我身上的事。在我的git版本上你可以通过使用来发现它

git diff dir1/foo.aspx

它会显示文件模式的变化。但它仍然不会让你回复它们。对于那个用途

git config core.filemode false

或者通过添加在文本编辑器中更改你的git .config

[core]

1
filemode = false

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

git reset HEAD dir1/foo.aspx

并且文件应该消失。

(我从答案中得到了所有这些如何使git忽略模式更改(chmod)?)


我有一些幻影更改的文件显示为已修改,但实际上是相同的。

运行此命令有时会起作用:
(关闭git的"智能"但通常无益的线路结束转换)

1
git config --local core.autocrlf false

但在另一种情况下,我发现这是由于根目录中的.gitattributes文件存在一些行结束设置,即使关闭了某些文件也试图应用autocrlf。这实际上没有用,所以我删除了.gitattributes,已提交,并且该文件不再显示为已修改。


尝试还原本地更改:

1
2
git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx


1
2
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx


您也可能遇到与命名字母案例的目录相关的问题。
你的一些同事可能已经改变了目录的名称
从例如myHandler到MyHandler。
如果您稍后推送并拉出了原始目录中的一些文件,那么您在远程存储库上将拥有2个单独的目录,而在本地计算机上只有一个目录,因为在Windows上您只能拥有一个。你遇到了麻烦。

要检查是否是这种情况,只需查看远程存储库是否具有双重结构。

要解决此问题,请在repo之外创建父目录的备份副本,然后删除父目录,将其推送。拉动(这是当标记为已删除的第二个应该出现在状态时)并再次按下。
之后,从备份中重新创建整个结构并再次推送更改。


对我来说,问题不在于线路结束。它是关于更改文件夹名称中的大小写(Reset_password - > Reset_Password)。这个解决方案帮助我:
https://stackoverflow.com/a/34919019/1328513


我认为提供一个如何重现问题的提示会有所帮助,以便更好地理解问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
$ git init
$ echo"*.txt -text"> .gitattributes
$ echo -e"hello

world"> 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 '
' HEAD

HEAD:1.txt

第二种方式重现:
在上面的脚本中替换此行:
echo"*.txt -text"> .gitattributes

git config core.autocrlf=false
并按原样保留其余的行

以上所说的是什么?文本文件可以(在某些情况下)
使用CRLF提交(例如-text / core.autocrlf=false中的-text)。

当我们后来想要将同一个文件视为文本(-text - > text)时,需要再次提交。
当然你可以暂时还原它(正如Abu Assar正确回答的那样)。在我们的情况下:

1
2
3
echo"*.txt -text"> .gitattributes
git checkout -- 1.txt
echo"*.txt text"> .gitattributes

答案是:你真的想这样做,因为每次更改文件都会导致同样的问题。

作为记录:

要在repo中检查哪些文件可能导致此问题,请执行以下命令(git应使用--with-libpcre编译):

1
2
git grep -I --files-with-matches --perl-regexp '
' HEAD

通过提交文件(假设您希望将它们视为文本),与执行此链接http://help.github.com/line-endings/中提出的修复此类问题的内容相同。但是,您可以只更改文件,然后执行git checkout -- xyz zyf然后提交,而不是删除.git/index并执行reset