git重置后留下的非阶段性变化——很难

git reset --hard之后,git status给出了Changes not staged for commit:部分中的文件。

我也试过git reset .git checkout -- .git checkout-index -f -a,都没有用。

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

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

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

此外,autocrlf在全局.gitconfig中设置为false。这有什么关系吗?

239567 次浏览

你可以stash删除你的更改,然后删除stash:

git stash
git stash drop

Git不会重置不在存储库中的文件。所以,你可以:

$ git add .
$ git reset --hard

这将执行所有更改,这将使Git知道这些文件,然后重置它们。

如果这不起作用,你可以尝试隐藏并删除你的更改:

$ git stash
$ git stash drop

好吧,我差不多把问题解决了。

似乎.gitattributes文件包含:

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

使项目文件出现非阶段性。我不知道为什么会这样,我真的希望了解git的人会给我们一个很好的解释。

我的修复是删除这些文件,并在.git/config[core]下添加autocrlf = false

这与前面的配置并不完全相同,因为它要求每个开发人员都有autocrlf = false。我想找个更好的办法。

编辑:

我注释了那些有罪的句子,然后取消注释,它起作用了。搞什么…我甚至不……!

我也有同样的问题,这与.gitattributes文件有关。 但是,在.gitattributes.

. 0中没有指定导致问题的文件类型

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

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

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

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

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

git config core.filemode false

更多信息在这里

另一个原因可能是不区分大小写的文件系统。如果你的repo中有多个文件夹在同一层上,它们的名称只是大小写不同,你就会遇到这种情况。使用其web界面(例如GitHub或VSTS)浏览源存储库以确保。

有关更多信息:https://stackoverflow.com/a/2016426/67824

我也有同样的问题。我做了git reset --hard HEAD,但每次我做git status时,我都看到一些文件被修改了。

我的解决办法相对简单。 我只是关闭我的IDE(这里是Xcode)和关闭我的命令行(这里是我的Mac OS的终端),并再次尝试,它工作了

然而,我始终无法找到问题的根源。

这些方法都不适合我,唯一的解决方案是核整个回购和重新克隆它。这包括存储,重置,添加然后重置,clrf设置,大小写敏感性等。叹息……

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

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

GitHub LFS扩展主要通过利用git通过.gitattributes文件提供访问的钩子来工作。通常,.gitattributes中的条目指定如何处理匹配文件。在OP的情况下,它涉及到规范的行结束;我的问题是是否让LFS处理文件存储。在任何一种情况下,git在计算git diff时看到的实际文件与你在检查该文件时看到的文件不匹配。因此,如果你通过匹配的.gitattributes模式改变了一个文件的处理方式,它将在状态报告中显示为未分阶段的变化,即使文件中确实没有变化。

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

参考文献

  1. GitHub LFS规范 -很好地描述了它们如何钩入cleansmudge函数调用,用一个带散列的简单文本文件替换git对象中的文件。

  2. gitattributes Documentation -所有可用于自定义git如何处理文档的详细信息。

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

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

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

解决方案

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

最好的选择是让git应用它想要的规范化,通过规范化repo中的所有行结束符来匹配.gitattributes,并提交这些更改——参见试图修复行结束与git过滤器分支,但没有运气

如果你真的想尝试手动恢复对文件的更改,那么最简单的解决方案似乎是删除修改过的文件,然后告诉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上签出这个回购可能会导致修改后的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定义的文件,并使用默认的全局设置core.autocrlffalse(见(2))。

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

我已经通过以下步骤解决了这个问题

  1. 从Git的索引中删除每个文件。

    git rm --cached -r .
    
  2. 重写Git索引以获取所有新的行结束符。

    git reset --hard
    

解决方案是配置Git来处理行结束中描述的步骤的一部分

执行清洁命令:

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


git clean -fd

检查你的.gitattributes

在我的例子中,我有*.js text eol=lf, git选项core.autocrlftrue

它把我带到git自动转换我的文件行结束符并阻止我修复它的情况,甚至git reset --hard HEAD也没有做任何事情。

我通过在我的.gitattributes中注释*.js text eol=lf并在它之后取消注释来修复它。

看起来就像变魔术了。

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

git checkout master -f
git checkout <your branch>

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

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

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

类似的问题,虽然我确定只是表面上的。不管怎样,它可能会帮助某些人:我所做的(FWIW,在SourceTree):隐藏未提交的文件,然后进行硬重置。

正如其他答案所指出的,这个问题是因为行尾自动纠错。我在*.svg文件中遇到了这个问题。我使用svg文件图标在我的项目。

为了解决这个问题,我让git知道svg文件应该被视为二进制文件,而不是文本,方法是在.gitattributes中添加下面的行

* .二进制

如果其他答案不工作,尝试添加文件,然后重置

$ git add -A
$ git reset --hard

在我的情况下,这有助于当有一堆空文件,git正在跟踪。

在类似的情况下。由于多年来与许多程序员的折磨,他们能够填充行尾的不同编码(。asp, .js, .css…不是精华)放入一个文件。前段时间拒绝了.gitattributes。repo的设置留给autorclf = true和__abc1。

最后一个问题出现在从具有不同行尾的存档进行同步时。从存档中复制后,在git状态下许多文件都随注释而改变

这一行将在你的工作目录中有它原来的行结束符。

中LF将被CRLF取代

来自如何规范化工作树形线结束在Git?的提示有帮助

git add -u

我遇到的另一种可能性是,存储库中的一个包最终具有分离的HEAD。如果这里的答案都没有帮助,你遇到了这样的git状态消息,你可能有同样的问题:

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:   path/to/package (new commits)

进入path/to/package文件夹,git status应该产生以下结果:

HEAD detached at 7515f05

下面的命令应该修复这个问题,其中master应该被你的本地分支替换:

git checkout master

您将得到一条消息,您的本地分支将在远程分支后面提交一些数量的文件。git pull和你应该是走出树林!

出于某种原因

git add .

没有工作,但

$ git add -A

工作了!

试着简单

. Git恢复

这是少年犯说的。它的工作

Enviro: Visual Studio 2019 + git + Azure DevOps。

行为

在尝试硬重置后遇到这种情况,但我的是<强> < / >强不由于行结束。

Git在执行一些命令时挂起;换句话说,它永远不会回到命令提示符。它将显示给定命令中的文件已被处理,但它不会完成所有“阶段”;命令的。

以Git克隆为例:

enter image description here

解决方案

创建一个新的个人访问令牌PAT

与我现有的PAT有关的安全/凭据问题,但我找不到任何日志告诉我它失败了。