【问题标题】:Unstaged changes left after git reset --hardgit reset --hard 后留下未暂存的更改
【发布时间】:2012-07-08 03:29:47
【问题描述】:

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。这可能有某种相关性吗?

【问题讨论】:

  • 您是否从存储库的根目录应用了这些命令?注意.代表当前目录而不是根目录
  • 我确实是从根存储库中完成的。
  • 您的git 版本是什么?要么你犯了一个愚蠢的错误,要么你的旧版本有问题?
  • 这是 git 1.7.4 msysgit。这可能是一个错误,但命令似乎很简单,我无法发现错误。
  • 为了记录,我尝试使用最新版本的msysgit(1.7.11),但问题仍然存在。

标签: git git-reset


【解决方案1】:

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

我可以通过简单的运行来解决这个问题

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

【讨论】:

  • 这是 gitattributes 文件中的 * text=auto 指令。它会自动更改文件结尾,因此当您检查状态时,文件会自动标记为“已修改”。
  • 这行得通,但我不完全明白为什么。有人愿意解释每个命令吗?
  • @NLwino, git rm .gitattributes 从索引中删除 .gitattributes。 git add -A 将所有(包括删除 .gitattributes)添加到索引中,如果这确实是问题,那么 应该 然后只删除 .gitattributes。 git reset --hard 重置所有未提交的更改,其中包括删除 .gitattributes。本质上,这会通过删除一次提交忽略 .gitattributes (和* text=auto 指令),然后在删除索引时重置索引,因此将其放回原处,但是在您已经重置其他文件之后,它们不是再次修改。
  • @GameScripting,这个解决方案对我不起作用。没有.gitattributes这样的文件:"fatal: pathspec '.gitattributes' did not match any files"
  • 我这样做了,上面写着fatal: pathspec '.gitattributes' did not match any files 。我做错了什么?
【解决方案2】:

我已使用以下步骤解决了此问题

  1. 从 Git 的索引中删除所有文件。

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

    git reset --hard
    

解决方案是Configuring Git to handle line endings 中描述的步骤的一部分

【讨论】:

  • 这在没有其他方法的情况下有效!我们已经尝试了这个线程和许多其他线程中的所有内容——这是一个庞大的开发团队,所以让每个人都使用同一个 crlf 是一场噩梦,但这解决了问题。
  • 有趣...我使用“git rm --chached ,而不是删除所有内容。“git status”报告该文件已删除且未跟踪。然后“git reset --hard”修复该文件所有其他被报告为“未暂存更改”的文件。(在使用 git rm 之前,我努力尝试重置无效)。我喜欢这种神秘的源代码控制系统。
  • 这太残酷了。您可以通过删除 repo 目录并重新克隆来做同样的事情。
  • 请考虑您在 Windows 上并且它不区分大小写。如果您还与使用区分大小写的文件系统(如 Mac 或 Linux)的开发人员合作,他们可能会在不同情况下提交标签、分支甚至文件。在这种情况下,您的索引将显示在拉取时被操作系统覆盖的现有文件。解决此问题的唯一方法是在您的 Git 服务器(挂钩)上制定命名策略或提前发现错误。
  • 这对我不起作用。我需要在git reset --hard之前做git add .
【解决方案3】:

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

$ git add .
$ git reset --hard

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

如果这不起作用,您可以尝试存储并删除您的更改:

$ git stash
$ git stash drop

【讨论】:

  • 文件已被跟踪。无论如何都试过了,它也不起作用。我的回购一定有什么问题,但我不知道是什么。对于 git stash thingy,请参阅我对 Shahbaz 的回答。
  • 执行 git status 时会发生什么?
  • 我想到了一个解决方案。进行提交和交互式变基以删除该提交。
  • 我曾经尝试过,但它确实奏效了,后来我又尝试了一次,并在我的答案编辑中得出了令人惊讶的结果。
  • @YuriAlbuquerque,Git 不太了解POLAgit reset --hard 的重点不就是“reset both the staging area and the working directory to match”吗?如果文件未暂存,显然我们希望在执行reset --hard 时将其删除。
【解决方案4】:

如果您使用 Git for Windows,这可能是您的问题

我也遇到过同样的问题,存储、硬重置、清理甚至所有这些问题都仍然留下更改。原来的问题是 git 没有正确设置 x 文件模式。这是 git for windows 的“已知问题”。本地更改在 gitk 和 git status 中显示为旧模式 100755 新模式 100644,没有任何实际文件差异。

解决方法是忽略文件模式:

git config core.filemode false

More info here

【讨论】:

  • 即使rm -rf *; git checkout HEAD . 没有,这也有效。呸!
  • 为我工作,而 stash drop / hard reset / rm .attributes 都失败了。
  • 当我在使用 Mac 上托管的 Linux 中的 git repo 时遇到问题时,这也适用于我
  • 为我工作 - 尝试了其他所有方法,是的,旧模式与新模式是问题所在(注意到我的编号不同,但文件相同)
  • 巨大的救生员!为什么在 Windows 上工作这么痛苦?!
【解决方案5】:

好的,我已经解决了这个问题。

.gitattributes 文件似乎包含:

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

使项目文件显示为未暂存。我不知道为什么会这样,我真的希望知道 git 方式的人能给我们一个很好的解释。

我的解决办法是删除这些文件,并在.git/config 中的[core] 下添加autocrlf = false

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

编辑:

我评论了有罪的行,取消了评论,它起作用了。什么...我什至不...!

【讨论】:

  • 我刚刚遇到了同样的问题,这是唯一有效的解决方案。在我的例子中,我从一个特性分支切换到我的主分支,并从上游提取了一些新的更改,它刚刚开始发生在 2 个被修改的文件上。看起来文件可能已从 Unix 切换到 Windows 行结尾,这可能与它有关。不知道如何或为什么。
  • +1 Windows Git 上的相同问题。已经有autocrlf = false。我合并了上游 svn repo (git svn fetch / git merge git-svn) 的更改,并留下了 1 个标记为已修改的文件。奇怪的是,我之前遇到过这个问题,我需要做的就是检查另一个分支(带有-f 标志),然后切换回来。我这样做了,它奏效了,但是当我切换到功能分支时,“更改”又回来了!您在答案底部的编辑是解决方案。就我而言,我在 .gitattributes 文件顶部注释/取消注释了一行:* text=auto !eol
  • 那个 EDIT 也对我有用:注释掉 .gitattributes 中的行,运行 git status,取消注释 .gitattributes 中的行,再次运行 git status
  • 这是因为 git 正在重置这些文件,然后再次应用 .gitattributes 中指定的行尾。 git diff 可能显示了著名的红墙/绿墙,这是典型的行尾差异。
  • 我的解决方案: 开始之前:提交您当前的工作。 那么: 1. git reset --hardgit checkout --force <branch> 2. git add --all --renormalize 3. git commit -m "Normalize all the line endings"Reference
【解决方案6】:

可能的原因 #1 - 行尾标准化

可能发生这种情况的一种情况是,当有问题的文件在没有正确配置行尾 (1) 的情况下签入存储库时,导致存储库中的文件具有不正确的行尾或混合的行尾。要确认,请确认 git diff 仅显示行尾的更改(默认情况下这些可能不可见,请尝试 git diff | cat -v 将回车视为文字 ^M 字符)。

随后,有人可能添加了 .gitattributes 或修改了 core.autocrlf 设置以规范行尾 (2)。基于.gitattributes 或全局配置,Git 已将本地更改应用于您的工作副本,这些更改应用了请求的行尾规范化。不幸的是,出于某种原因,git reset --hard 不会撤消这些行规范化更改。

解决方案

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

最好的选择是让 git 通过规范化 repo 中的所有行结尾以匹配 .gitattributes 并提交这些更改来应用它想要的规范化 - 请参阅 Trying to fix line-endings with git filter-branch, but having no luck

如果您真的想尝试手动还原对文件的更改,那么最简单的解决方案似乎是删除修改后的文件,然后告诉 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 不区分大小写,会覆盖 @ 的内容987654339@ 和 /foo/Bar/fileA,导致它们被“修改”。

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

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

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

不区分大小写的文件系统上的 git 应该真正检测到这种情况并显示有用的警告消息,但它目前没有(这可能会在未来发生变化 - 请参阅 this discussion 和 git.git 邮件列表上的相关建议补丁) .

解决方案

解决方案是将 git 索引中的文件大小写与 Windows 文件系统上的大小写对齐。这可以在 Linux 上完成,这将显示事物的真实状态,或者在 Windows 上使用非常有用的开源实用程序 Git-Unite。 Git-Unite 会将必要的案例更改应用于 git 索引,然后可以将其提交到 repo。

(1) 这很可能是使用 Windows 的人,没有为相关文件定义任何 .gitattributes,并使用 core.autocrlf 的默认全局设置 false(参见 (2))。

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

【讨论】:

  • 该死的儿子,一路走到这一步。我不得不在第一行之后提交,但我终于能够结帐主人。那不好玩。
【解决方案7】:

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

$ git add -A
$ git reset --hard

在我的例子中,当 git 正在跟踪一堆空文件时,这会有所帮助。

【讨论】:

  • 这行得通。我只是使用$ git add . 而不是$ git add -A
  • 这对我也有用。我使用了$ git add .,然后使用了$ git reset --hard
【解决方案8】:

造成这种情况的另一个原因可能是不区分大小写的文件系统。如果您在同一级别的存储库中有多个文件夹,其名称仅因大小写而异,您将受到打击。使用其 Web 界面(例如 GitHub 或 VSTS)浏览源存储库以确保。

欲了解更多信息:https://stackoverflow.com/a/2016426/67824

【讨论】:

  • 要查找此类文件的名称,请运行git ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d
  • 除文件夹外,这也可能发生在多个文件仅因大小写而异的情况下。我在 Linux(区分大小写)主机上的 Windows(不区分大小写)存储库中看到了这一点 - 不知何故,我们在那里得到了一个不同大小写的文件的副本。
【解决方案9】:

您可以stash 删除您的更改,然后删除存储:

git stash
git stash drop

【讨论】:

  • 您可能还对this感兴趣。
【解决方案10】:

运行clean命令:

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

git clean -fd

【讨论】:

  • 很遗憾,这并不能解决与行尾相关的问题。
  • 这只是解决我的问题的方法,不管我的问题是什么。我没有.gitattributes 文件,行尾不是问题,因为我使用的是 linux 机器,所有开发人员和我们的服务器都是 linux。
【解决方案11】:

这些方法都不适合我,唯一的解决方案是核对整个 repo 并重新克隆它。这包括存储、重置、添加然后重置、clrf 设置、区分大小写等。叹息..

【讨论】:

  • 更新,原来我安装的区分大小写的文件系统实际上并不区分大小写。在我解决了这个问题之后,可以使用上述技术解决。
【解决方案12】:

检查您的.gitattributes

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

当 git 自动转换我的文件行结尾并阻止我修复它甚至 git reset --hard HEAD 没有做任何事情时,它让我陷入了这种情况。

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

看起来它只是 git 魔法。

【讨论】:

【解决方案13】:

我认为 git for Windows 存在问题,git 在结帐时随机写入错误的行尾,唯一的解决方法是结帐其他分支并强制 git 忽略更改。然后检查你真正想要工作的分支。

git checkout master -f
git checkout <your branch>

请注意,这将放弃您可能有意进行的任何更改,因此只有在您在结帐后立即遇到此问题时才执行此操作。

编辑:我第一次可能真的很幸运。事实证明,我在切换分支后又被咬了。事实证明,在更改分支更改后,git 报告的文件已修改。 (显然是因为 git 没有始终如一地将 CRLF 行正确地应用到文件中。)

我已更新到最新的 Windows git,希望问题消失。

【讨论】:

    【解决方案14】:

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

    我的解决方案相对简单。 我刚刚关闭了我的 IDE(这里是 Xcode)并关闭了我的命令行(这里是我的 Mac OS 上的终端)并再次尝试它并且它工作了。

    但我始终无法找到问题的根源。

    【讨论】:

    • 在我的例子中,IDE (codium) 总是更新文件.classpath,然后又一次又一次地出现修改。
    【解决方案15】:

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

    就我而言,一个文件已经在我的存储库中,就像从一开始一样。在最近的一次提交中,我添加了一个新的git-lfs track 规则,使用一种事后看来有点过于宽泛的模式,并最终匹配了这个古老的文件。我知道我不想更改此文件;我知道我没有更改文件,但现在它在我的未分阶段更改中,并且对该文件的任何签出或硬重置都无法修复它。为什么?

    GitHub LFS 扩展主要通过利用 git 通过 .gitattributes 文件提供访问权限的挂钩来工作。通常,.gitattributes 中的条目指定应如何处理匹配文件。在 OP 的情况下,它与规范化行尾有关;在我看来,是是否让 LFS 处理文件存储。在任何一种情况下,git 在计算 git diff 时看到的实际文件都与您在检查文件时看到的文件不匹配。因此,如果您通过与之匹配的.gitattributes 模式更改文件的处理方式,它将在状态报告中显示为未暂存的更改,即使文件中确实没有更改。

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

    参考文献

    1. GitHub LFS Specification - 很好地描述了它们如何连接到 cleansmudge 函数调用,以使用带有哈希的简单文本文件替换 git 对象中的文件。

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

    【讨论】:

      【解决方案16】:

      尝试简单 git 恢复。

      这就是 git 所说的并且它正在工作

      【讨论】:

        【解决方案17】:

        类似的问题,虽然我确定只是表面上。无论如何,它可能对某人有所帮助:我做了什么(FWIW,在 SourceTree 中):隐藏了未提交的文件,然后进行了硬重置。

        【讨论】:

          【解决方案18】:

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

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

          *.svg 二进制文件

          【讨论】:

            【解决方案19】:

            类似的情况。经过多年折磨的结果,许多程序员能够将行尾的不同编码(.asp、.js、.css ... 不是本质)填充到一个文件中。前段时间拒绝了.gitattributes。 repo 的设置留给autorclf = truesafecrlf = warn

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

            The line will have its original line endings in your working directory. warning: LF will be replaced by CRLF in ...

            来自How to normalize working tree line endings in Git? 的提示帮助

            git add -u

            【讨论】:

              【解决方案20】:

              我遇到的另一种可能性是存储库中的一个包以分离的 HEAD 结尾。如果这里的答案都没有帮助,并且您遇到这样的 git status 消息,您可能会遇到同样的问题:

              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 你应该走出困境!

              【讨论】:

                【解决方案21】:

                由于某种原因

                git add .

                没用,但是

                $ git add -A

                成功了!

                【讨论】:

                  猜你喜欢
                  • 2020-07-25
                  • 2011-05-18
                  • 2018-11-10
                  • 1970-01-01
                  • 2018-11-02
                  • 2012-04-05
                  • 1970-01-01
                  • 2018-07-02
                  • 2018-11-24
                  相关资源
                  最近更新 更多