在git重置后——很难,git状态给了我在Changes not staging for commit:部分中的文件。

我也试过git reset ., git checkout。而git check - out-index -f -a,毫无用处。

那么,我怎样才能摆脱这些未分阶段的变化呢?

这似乎只影响Visual Studio项目文件。奇怪。请看这个粘贴:http://pastebin.com/eFZwPn9Z。这些文件的特殊之处在于,在.gitattributes中我有:

*.sln        eol=crlf
*.vcproj     eol=crlf
*.vcxproj*   eol=crlf

另外,在我的全局.gitconfig中,selflf被设置为false。这有什么关系吗?


当前回答

我遇到了一个类似的问题,也涉及.gitattributes,但我的案例涉及GitHub的LFS。虽然这并不完全是OP的场景,但我认为它提供了一个机会来说明.gitattributes文件的功能以及为什么它会以“幻影”差异的形式导致未分阶段的更改。

在我的例子中,一个文件已经在我的存储库中,就像从一开始一样。在最近的一次提交中,我添加了一个新的git-lfs跟踪规则,使用的模式事后看来有点太宽泛了,最终匹配了这个古老的文件。我知道我不想改变这个文件;我知道我没有更改文件,但现在它在我的非阶段性更改中,无论对该文件进行多少签出或硬重置都无法修复它。为什么?

GitHub LFS extension works primarily through leveraging the hooks that git provides access through via the .gitattributes file. Generally, entries in .gitattributes specify how matching files should be processed. In the OP's case, it was concerned with normalizing line endings; in mine, it was whether to let LFS handle the file storage. In either case, the actually file that git sees when computing a git diff does not match the file that you see when you inspect the file. Hence, if you change how a file is processed via the .gitattributes pattern that matches it, it will show up as unstaged changes in the status report, even if there really is no change in the file.

综上所述,我对这个问题的“回答”是,如果.gitattributes文件中的更改是您想要做的,那么您应该只添加更改并继续前进。如果不是,那么修改.gitattributes以更好地表示您想要做的事情。

参考文献

GitHub LFS规范-很好地描述了它们如何钩子到clean和smudge函数调用中,用一个带散列的简单文本文件替换git对象中的文件。 gitattributes文档——所有可用于自定义git如何处理文档的细节。

其他回答

可能原因1 -行结束归一化

可能发生这种情况的一种情况是,在没有正确配置行结束符(1)的情况下,将有问题的文件签入存储库,导致存储库中的文件行结束符不正确,或者行结束符混合。要确认,验证git diff只显示行结束符的变化(默认情况下这些可能不可见,尝试git diff | cat -v查看回车为字面^M字符)。

随后,可能有人添加了.gitattributes或修改了内核。(2).基于.gitattributes或全局配置,Git已经对你的工作副本应用了本地更改,应用了所请求的行结束规范化。不幸的是,由于某些原因,git reset—hard并没有撤消这些行规范化的更改。

解决方案

重置本地行结束符的变通方法不能解决问题。每次文件被git“看到”时,它都会尝试重新应用规范化,从而导致相同的问题。

最好的选择是让git应用它想要的规范化,通过规范化repo中的所有行结束符来匹配.gitattributes,并提交这些更改——参见尝试用git filter-branch修复行结束符,但运气不好。

如果你真的想尝试手动恢复对文件的更改,那么最简单的解决方案似乎是删除修改过的文件,然后告诉git恢复它们,尽管我注意到这个解决方案似乎不能100%一致地工作(警告:如果你修改的文件除了行尾之外有更改,请不要运行这个!!):

    git status --porcelain | grep "^ M" | cut -c4- | xargs rm
    git checkout -- .

注意,除非您在某个时候对存储库中的行结束符进行了规范化,否则您将继续遇到这个问题。

可能原因2 -不区分大小写

第二个可能的原因是Windows或Mac OS/X不区分大小写。例如,存储库中存在如下路径:

/foo/bar

现在Linux上有人将文件提交到/foo/Bar(可能是由于构建工具或其他创建该目录的工具)并推送。在Linux上,这实际上是两个独立的目录:

/foo/bar/fileA
/foo/Bar/fileA

在Windows或Mac上签出这个repo可能会导致修改后的fileA不能被重置,因为在每次重置时,Windows上的git都会签出/foo/bar/fileA,然后因为Windows不区分大小写,会用/foo/bar/fileA覆盖fileA的内容,导致它们被“修改”。

另一种情况可能是repo中存在的单个文件,当在不区分大小写的文件系统上签出时,它们将重叠。例如:

/foo/bar/fileA
/foo/bar/filea

可能还有其他类似的情况会导致这样的问题。

不区分大小写的文件系统上的Git应该真正检测到这种情况并显示有用的警告消息,但目前没有(这在未来可能会改变——请参阅本讨论和Git的相关补丁。Git邮件列表)。

解决方案

解决方案是使git索引中的文件大小写与Windows文件系统中的大小写保持一致。这既可以在Linux上完成,它将显示事物的真实状态,也可以在Windows上使用非常有用的开源实用程序Git-Unite。git - unite将对git索引应用必要的case更改,然后将其提交给repo。

(1)这很可能是有人使用Windows,没有任何。gitattributes定义的文件,并使用默认的全局核心设置。这是错误的(见(2))。

(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/

如果您使用的是面向Windows的Git,那么这可能就是您的问题

我也遇到过同样的问题,隐藏,硬重置,清理,甚至所有这些都仍然留下了变化。原来的问题是git没有正确设置x文件模式。这是windows git的一个“已知问题”。gitk和git的本地变化显示为旧模式100755新模式100644,没有任何实际的文件差异。

修复方法是忽略文件模式:

git config core.filemode false

更多信息请点击这里

执行clean命令:

# Remove all untracked files and directories. (`-f` is `force`, `-d` is `remove directories`)

git clean -fd

我也遇到了同样的问题,这与.gitattributes文件有关。 但是,在.gitattributes中没有指定导致问题的文件类型。

我可以通过简单的跑步来解决这个问题

git rm .gitattributes
git add -A
git reset --hard

我相信Windows的git有一个问题,git在签出时随机写了错误的行结束符,唯一的解决方法是签出一些其他分支并迫使git忽略更改。然后签出您实际想要处理的分支。

git checkout master -f
git checkout <your branch>

请注意,这将丢弃您可能有意做出的任何更改,因此只有在签出后立即出现此问题时才执行此操作。

编辑:我第一次可能真的很幸运。原来换树枝后我又被咬了。结果是git在更改分支后报告的文件被修改了。(显然是因为git没有始终正确地将CRLF行结束应用到文件中。)

我更新到最新的Windows git,希望这个问题已经解决了。