【问题标题】:git status shows modifications, git checkout -- <file> doesn't remove themgit status 显示修改, git checkout -- <file> 不会删除它们
【发布时间】:2011-01-02 06:01:08
【问题描述】:

我想删除对我的工作副本的所有更改。
运行 git status 显示文件已修改。
我所做的一切似乎都无法消除这些修改。
例如:

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ 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:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git checkout -- Rhino.Etl.Core/Enumerables/CachingEnumerable.cs

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ 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:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git checkout `git ls-files -m`

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ 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:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git reset --hard HEAD
HEAD is now at 6c857e7 boo libraries updated to 2.0.9.2 and rhino.dsl.dll updated.

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ 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:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

【问题讨论】:

  • 不知道为什么git reset --hard 在这里不起作用。注意:取消文件应该是git checkout -- `git ls-files -m`(--)
  • 如果您删除文件并使用checkout -- &lt;file&gt;,它应该可以工作。在某些情况下,更改检测有点挑剔(尤其是如果存在 CRLF 不匹配)
  • @BuZZ-dEE - 它是重复的,而且较旧,因此优先。但是,虽然您链接到的问题基本相同,但我在下面接受的答案比那里的任何答案都提供更多信息,并且解决了我的问题。
  • 不是解决方案,而是解决无聊案例的瑞士刀:git update-index --assume-unchaged 强制文件处于未更改状态(即使对于已更改的文件!)

标签: git revert git-status working-copy


【解决方案1】:

有多个问题可能导致此行为:

行尾归一化

我也遇到过这类问题。归结为 git 自动将 crlf 转换为 lf。这通常是由单个文件中的混合行结尾引起的。该文件在索引中被规范化,但是当 git 再次对其进行非规范化以将其与工作树中的文件进行比较时,结果是不同的。

但如果你想解决这个问题,你应该禁用 core.autocrlf,将所有行尾更改为 lf,然后再次启用它。或者您可以通过以下方式完全禁用它:

git config --global core.autocrlf false

除了core.autocrlf,您还可以考虑使用.gitattribute 文件。这样,您可以确保使用 repo 的每个人都使用相同的规范化规则,防止混合行结尾进入存储库。

还可以考虑设置 core.safecrlf 如果您希望 git 在执行不可逆规范化时发出警告。

git manpages 这样说:

CRLF 转换的机会很小 的损坏数据。 autocrlf=true 将 在提交期间将 CRLF 转换为 LF 和 结帐时从 LF 到 CRLF。一份文件 包含 LF 和 CRLF 的混合物 在无法重新创建提交之前 通过 git。对于文本文件,这是 正确的做法:纠正线路 结尾使得我们只有 LF 行 存储库中的结尾。但对于 意外的二进制文件 分类为文本转换可以 损坏的数据。

不区分大小写的文件系统

在不区分大小写的文件系统上,当存储库中存在相同的文件名但大小写不同的文件时,git 会尝试同时检出两者,但只有一个最终会出现在文件系统上。当 git 尝试比较第二个时,它会将其与错误的文件进行比较。

解决方案要么切换到不区分大小写的文件系统,但在大多数情况下这是不可行的,要么重命名并提交另一个文件系统上的一个文件。

【讨论】:

  • 好的...这样就完成了...现在 git status 显示没有任何变化。我已经阅读了 autocrlf 设置,但似乎无法正确设置。
  • 好收获! +1。我的另一个论点将其设置为 false (stackoverflow.com/questions/1249932/…)。
  • 这是什么意思:“在提交之前包含 LF 和 CRLF 混合的文件不能被 git 重新创建。”这是因为 git 总是会根据 core.autocrlf 设置规范化行尾吗?
  • 解决区分大小写问题的一个更明智的解决方案是在您的存储库中不要有多个名称仅因大小写不同而不同的文件夹
  • 要查找仅字母大小写不同的文件名,您可以运行git ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d。要列出此类文件的大小写名称,请运行git ls-tree -r --name-only HEAD | fgrep -i -f &lt;(git ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d) | sort -i
【解决方案2】:

有一致的行尾是一件好事。例如,它不会触发不必要的合并,尽管是微不足道的。我已经看到 Visual Studio 创建具有混合行尾的文件。

还有一些程序,如 bash(在 linux 上)确实要求 .sh 文件是 LF 终止的。

为了确保发生这种情况,您可以使用 gitattributes。无论 autcrlf 的值是什么,它都适用于存储库级别。

例如,您可以拥有这样的 .gitattributes: * 文本=自动

如果对您的情况很重要,您还可以更具体地说明每个文件类型/扩展名。

然后 autocrlf 可以在本地转换 Windows 程序的行尾。

在混合的 C#/C++/Java/Ruby/R、Windows/Linux 项目上,这运行良好。到目前为止没有问题。

【讨论】:

    【解决方案3】:

    对于以后遇到此问题的人:更改文件模式也可能有相同的症状。 git config core.filemode false 会修复它。

    【讨论】:

    • 完成此操作后,您可能需要做一个git checkout .
    • 为我工作,无需再次结帐
    • 供将来参考:要知道这是否是您需要的修复程序(而不是其他答案中的其他修复程序),请使用git diff,它将显示具有类似 old mode 100755 / new mode 100644 的模式更改的文件。
    • 这为我修复了它,绝对没有别的办法。我真的不认为人们应该在互联网上制作 git 备忘单和“简单指南”。 Git 真的不是随便学习和使用的东西,我认为在使用它之前你必须接受专门的正式培训和练习。
    • 谢谢,你帮我省了很多眼泪!
    【解决方案4】:

    这一直让我发疯,尤其是如果没有在线找到任何解决方案,我无法解决这个问题。这是我解决它的方法。由于这是同事的工作,因此无法在此处获得学分:)

    问题的根源:我最初安装的 git 在 windows 上没有自动行转换。这导致我对 GLFW 的初始提交没有正确的行尾。

    注意:这只是一个本地解决方案。下一个克隆 repo 的人 仍然会遇到这个问题。一个永久的解决方案可以是 在这里找到: https://help.github.com/articles/dealing-with-line-endings/#re-normalizing-a-repository.

    设置: 许邦图 12.04 带有 glfw 项目的 Git 仓库

    问题:无法重置 glfw 文件。无论我尝试什么,它们总是显示为已修改。

    已解决:

    edit .gitattributes
    
    Comment out the line:    # text=auto
    
    Save the file
    
    restore .gitattributes:   git checkout .gitattributes
    

    【讨论】:

    • 提及注释行的内容可能会有所帮助。
    • 很遗憾,大多数项目都没有这个可选的 .gitattribute 文件
    • 谢谢。我只是不明白为什么这是必要的
    • 为什么?基本上,这是对行尾的临时修复。按照注释中的链接使用永久解决方案。
    【解决方案5】:

    我只能通过临时删除我的 repo 的 .gitattributes 文件(定义 * text=auto*.c text)来解决这个问题。

    删除后我运行git status,修改消失了。即使在 .gitattributes 被放回原位后,它们也没有返回。

    【讨论】:

    • 这甚至适用于更复杂的 gitattributes,例如过滤器
    【解决方案6】:

    我在 Windows 上遇到了这个问题,但没有准备好研究使用 config --global core.autocrlf false 的后果我只需要完成一些事情。现在。

    这对我有用,因为你让 git 完全重写你的工作目录:

    git rm --cached -r .
    git reset --hard
    

    (请注意,仅运行 git reset --hard 还不够好,在 reset 之前的文件上也不是简单的 rm,如 cmets 对原始问题的建议)

    【讨论】:

    • 在更改core.autocrlf后再次成功在这里没有任何效果。
    • 即使使用core.autocrlf false,在 Windows 上也遇到了这个问题。这个答案在没有其他方法的情况下有效。
    • 我从这个问题和其他问题中尝试了多个建议。这是唯一对我有用的解决方法。我没有属性文件,并且我已经以 false 开始使用 core.autocrlf。
    • 这对我不起作用。所以,我以更丑陋的方式创建了一个新分支来提交这些更改,因为它们对我来说毫无用处。 [java]git checkout -b a-branch-to-commit-bad-crlf-files[/java] [java]git commit -am"提交错误的 crlf 文件"[/java]
    • 有时候像这样的问题让我真的很想念SVN。
    【解决方案7】:

    我有一个 .bat 文件存在同样的问题(无法在未跟踪的文件中删除它)。 git checkout - 没有用,这个页面上的任何建议也没有。唯一对我有用的是:

    git stash save --keep-index
    

    然后删除存储:

    git stash drop
    

    【讨论】:

    • 这对我有用。请注意,--keep-index 很重要。
    • 为什么 --keep-index 很重要?
    【解决方案8】:

    我也有同样的症状,但是是由不同的东西引起的。

    我无法做到:

    git checkout app.js //did nothing
    git rm app.js //did nothing
    rm -rf app.js //did nothing
    

    即使在 git rm --cached app.js 它标记为已删除,并且在未跟踪的文件中我可以看到 app.js。但是当我尝试rm -rf app.js 并再次执行git status 时,它仍然向我显示“未跟踪”中的文件。

    经过与同事的几次尝试,我们发现它是由 Grunt 引起的!

    由于 Grunt 已打开,并且由于 app.js 是从其他几个 js 文件生成的,我们发现在每次使用 js 文件(也是这个 app.js)进行操作后,再次 grunt 重新创建 app.js .

    【讨论】:

      【解决方案9】:

      另一个可能对人们有用的解决方案,因为没有一个文本选项对我有用:

      1. .gitattributes 的内容替换为一行:* binary。这告诉 git 将每个文件都视为一个不能做任何事情的二进制文件。
      2. 检查违规文件的消息是否消失;如果不是,您可以git checkout -- &lt;files&gt; 将它们恢复到存储库版本
      3. git checkout -- .gitattributes.gitattributes 文件恢复到初始状态
      4. 检查文件是否仍未标记为已更改。

      【讨论】:

      • 在过去的几个小时里,我一直无法恢复、提取或存储文件。这对我来说是修复!谢谢! (Git 1.8.3.1)
      • 在终于找到成功之前,我尝试了很多东西。谢谢!
      • 这是如何工作的?我认为将.gitattributes 恢复为原始会重新引入相同的问题,但是我的问题现在已经解决了。其他建议都不适用于我的情况。
      • @jdk1.0 我的理解/猜测是涉及两种不同的比较方法。当您在某处有不同的行结束时会发生错误,并且 git 有时会忽略它。当你问git status时,发现它们是不同的文件。当你问git checkout时,发现它们的内容相同。此解决方案暂时指示 git 忽略任何可能的行尾聪明,并确保您的本地副本逐字节与 HEAD 相同。一旦解决了这个问题,就可以恢复聪明了,因为它不会增加新的错误。
      • 已经花了几个小时来处理这个问题,这个解决方案终于对我有用了!
      【解决方案10】:

      当 repo 的贡献者在 Linux 机器上工作,或者带有 Cygwin 和文件权限的窗口发生更改时,也会发生此问题。 Git 只知道 755 和 644。

      此问题的示例以及如何检查:

      git diff styleguide/filename
      
      diff --git a/filename b/filename
      old mode 100644
      new mode 100755
      

      为避免这种情况,您应该确保使用正确设置 git

      git config --global core.filemode false
      

      【讨论】:

        【解决方案11】:

        两次遇到同样的问题!两次存储我所做的一些更改然后尝试将它们弹出回来。由于我有很多已更改的文件,因此无法弹出更改-但它们不是!它们完全一样。

        我现在认为我已经尝试了上述所有解决方案,但均未成功。尝试后

        git rm --cached -r .
        git reset --hard
        

        现在,我的存储库中的几乎所有文件都已修改。

        比较文件时,它说我已经删除了所有行,然后再次添加它们。

        有点令人不安。我现在会避免将来藏起来..

        唯一的解决方案是克隆一个新的存储库并重新开始。 (上次成功了)

        【讨论】:

          【解决方案12】:

          这里有很多解决方案,在我想出自己的解决方案之前,我也许应该尝试其中的一些。无论如何,这里还有一个......

          我们的问题是我们没有强制执行 endlines 并且存储库混合了 DOS / Unix。更糟糕的是,它实际上是这个位置的一个开源仓库,我们已经分叉了。那些拥有 OS 存储库主要所有权的人决定将所有结束行更改为 Unix,并且提交包含 .gitattributes 以强制行结束。

          不幸的是,这似乎会导致类似于此处描述的问题,一旦完成 DOS-2-Unix 之前的代码合并,文件将永远被标记为已更改且无法恢复。

          在对此进行研究的过程中,我遇到了 - https://help.github.com/articles/dealing-with-line-endings/ - 如果我再次遇到这个问题,我会首先尝试一下。


          这是我所做的:

          1. 我最初进行了合并,然后才意识到我遇到了这个问题并且不得不中止它 - git reset --hard HEAD (I ran into a merge conflict. How can I abort the merge?)

          2. 我在 VIM 中打开了有问题的文件并更改为 Unix (:set ff=unix)。当然可以使用dos2unix 之类的工具

          3. 承诺

          4. 合并master in (master 有 DOS-2-Unix 改动)

            git checkout old-code-branch; git merge master

          5. 解决了冲突,文件又是 DOS,所以在 VIM 中必须:set ff=unix。 (注意我已经安装了https://github.com/itchyny/lightline.vim,它让我可以看到VIM状态行上的文件格式)

          6. 承诺。全部排序!

          【讨论】:

            【解决方案13】:

            如果您克隆存储库并立即看到待处理的更改,则存储库处于不一致状态。请不要从.gitattributes 文件中注释掉* text=auto。这是专门放在那里的,因为存储库的所有者希望所有文件都以 LF 行结尾一致地存储。

            正如 HankCa 所述,遵循https://help.github.com/articles/dealing-with-line-endings/ 上的说明是解决问题的方法。简易按钮:

            git clone git@host:repo-name
            git checkout -b normalize-line-endings
            git add .
            git commit -m "Normalize line endings"
            git push
            git push -u origin normalize-line-endings
            

            然后将分支合并(或拉取请求)到 repo 的所有者。

            【讨论】:

              【解决方案14】:

              我遇到的问题是 windows 不关心文件名的大小写,但 git 关心。所以git存储了文件的大小写版本,但只能签出一个。

              【讨论】:

                【解决方案15】:

                此页面上的其他内容均无效。这终于对我有用。显示没有未跟踪或已提交的文件。

                git add -A
                git reset --hard
                

                【讨论】:

                  【解决方案16】:

                  尝试做一个

                  git checkout -f

                  这应该清除当前工作本地 repo 中的所有更改

                  【讨论】:

                  • 不错!这对我有用。尽管对于一个顽固的案例,我必须先git checkout -f &lt;another recent branch&gt; 然后用git checkout -f &lt;branch I'm working on&gt; 回到我的分支
                  【解决方案17】:

                  我提交了所有更改,然后在提交时执行并撤消。 这对我有用

                  git 添加。

                  git commit -m "随机提交"

                  git reset --hard HEAD~1

                  【讨论】:

                    【解决方案18】:

                    我们公司也遇到过类似的情况。所提出的方法都没有帮助我们。作为研究的结果,问题暴露了。 问题是在 Git 中有两个文件,它们的名称仅在符号寄存器中有所不同。 Unix 系统将它们视为两个不同的文件,但 Windows 快疯了。 为了解决这个问题,我们删除了服务器上的一个文件。之后,在 Windows 上的本地存储库中帮助了接下来的几个命令(以不同的顺序):

                    git reset --hard
                    git pull origin
                    git merge
                    

                    【讨论】:

                      【解决方案19】:

                      对我来说,问题是执行命令时打开了 Visual Studio

                      git checkout &lt;file&gt;

                      关闭 Visual Studio 后,该命令起作用了,我终于可以从堆栈中应用我的工作了。因此,请检查所有可能对您的代码进行更改的应用程序,例如 SourceTree、SmartGit、NotePad、NotePad++ 和其他编辑器。

                      【讨论】:

                        【解决方案20】:

                        通常,在 GIT 中,要清除所有修改和新文件,以下 2 个命令应该可以很好地工作(小心,这将删除您可能创建的所有新文件+文件夹并恢复您所有修改的文件到您当前提交的状态):

                        $ git clean --force -d
                        $ git checkout -- .
                        

                        也许更好的选择有时只是使用可选消息执行“git stash push”,如下所示:

                        $ git stash push -m "not sure if i will need this later"
                        

                        这也会清除所有新的和修改过的文件,但您会将它们全部隐藏起来,以备不时之需。 GIT 中的 Stash 从一个分支传送到另一个分支,因此您可以根据需要在不同的分支中恢复它们。

                        附带说明,如果您已经暂存了一些新添加的文件并想删除它们,这应该可以解决问题:

                        $ git reset --hard
                        

                        如果以上所有方法都不适合您,请阅读以下内容,看看之前对我有用的方法:

                        我之前遇到过几次这个问题。我目前正在我的雇主提供的 Windows 10 机器上进行开发。今天,这种特殊的 git 行为是由我从我的“开发”分支创建一个新分支引起的。出于某种原因,在我切换回“develop”分支后,一些看似随机的文件仍然存在,并在“git status”中显示为“modified”。

                        另外,那时我无法签出另一个分支,所以我被困在我的“开发”分支上。

                        这就是我所做的:

                        $ git log
                        

                        我注意到我今天早些时候从“develop”创建的新分支显示在第一个“commit”消息中,在末尾引用了“HEAD -> develop, origin/develop, origin/HEAD, -branch-i-created-earlier-today”。

                        由于我真的不需要它,所以我删除了它:

                        $ git branch -d The-branch-i-created-earlier-today
                        

                        更改的文件仍然显示,所以我这样做了:

                        $ git stash
                        

                        这解决了我的问题:

                        $ git status
                        On branch develop
                        Your branch is up to date with 'origin/develop'.
                        
                        nothing to commit, working tree clean
                        

                        当然$ git stash list 会显示隐藏的更改,由于我的存储很少而且不需要任何存储,我使用$ git stash clear 删除所有存储。

                        注意:我还没有尝试过按照我之前的建议进行操作:

                        $ git rm --cached -r .
                        $ git reset --hard
                        

                        这可能也有效,下次遇到此问题时,我一定会尝试。

                        【讨论】:

                          【解决方案21】:

                          我通过编辑.git / config解决了它,添加:

                          [branch "name_branch"]
                              remote = origin
                              merge = refs/heads/name_branch
                          

                          然后我去了.git/refs/heads/name_branch 并放置最后一次提交的identer code here

                          【讨论】:

                            【解决方案22】:

                            我是这样解决的:

                            1. 复制你想要的正确代码的内容
                            2. 从磁盘中删除导致问题的文件(您无法恢复的文件)。现在您应该会发现同一文件的两个版本都被标记为已删除。
                            3. 提交删除文件。
                            4. 再次使用相同的名称创建文件并粘贴您在步骤 1 中复制的正确代码
                            5. 提交新文件的创建。

                            这对我有用。

                            【讨论】:

                              【解决方案23】:

                              这里提出的一个解决方案不起作用,我发现该文件实际上是指向一些特殊字符的链接:

                              % ls -l StoreLogo.png
                              lrwxrwxrwx 1 janus janus 8 Feb 21 10:37 StoreLogo.png -> ''$'\211''PNG'$'\r\n\032\n'
                              
                              % git status    
                              Changes not staged for commit:
                                  modified:   StoreLogo.png
                              
                              % git rm --cached -r StoreLogo.png
                              rm 'src/GWallet.Frontend.XF.UWP/Assets/StoreLogo.png'
                              
                              % git reset StoreLogo.png         
                              Unstaged changes after reset:
                              M   src/GWallet.Frontend.XF.UWP/Assets/StoreLogo.png
                              
                              % git status                      
                              Changes not staged for commit:
                                  modified:   StoreLogo.png
                              

                              【讨论】:

                                【解决方案24】:

                                我有一个旧的冗余分支,具有不同的行尾。切换到这个让我有点卡住了,直到我应用了一些 --force。

                                git checkout mainbranch --force
                                

                                后跟一个 swift git branch -D brokenbranch

                                【讨论】:

                                • 这对我有用。不过,不确定最终结果与其他建议的答案有何不同。在我看来,在做任何涉及--forcerm 的事情之前备份整个本地存储库总是一个好主意...
                                猜你喜欢
                                • 2020-05-19
                                • 2012-06-15
                                • 2015-06-08
                                • 2018-11-24
                                • 1970-01-01
                                • 1970-01-01
                                • 2013-01-11
                                • 1970-01-01
                                相关资源
                                最近更新 更多