【问题标题】:How do I revert all local changes in Git managed project to previous state?如何将 Git 托管项目中的所有本地更改恢复到以前的状态?
【发布时间】:2010-11-11 22:19:30
【问题描述】:

我有一个运行git init 的项目。 几次提交后,我做了git status,它告诉我一切都是最新的,并且没有本地更改。

然后我连续做了几次改变,意识到我想扔掉所有东西,回到我原来的状态。这个命令会为我做吗?

git reset --hard HEAD

【问题讨论】:

    标签: git revert git-checkout


    【解决方案1】:

    两个简单的步骤

    git fetch origin
    
    git reset --hard origin/master
    

    或者如果你的 git 使用 main 而不是 master 使用这个:

    git reset --hard origin/main
    

    【讨论】:

      【解决方案2】:

      如果你在顶级项目目录中试试这个:

      git restore .
      

      如果没有,则使用:

      git restore :/
      

      如果您想恢复子集的本地更改:

      • 使用顶级路径规范魔法恢复所有工作树文件:git restore :/
      • 恢复当前目录下所有文件:git restore .
      • 文件类型(例如所有 C 源文件):git restore '*.c'

      详情见git restore documentation

      要删除未跟踪的文件:git clean -f

      【讨论】:

      • 谢谢。不过,那个“魔法”是可憎的。为什么不支持通配符?
      【解决方案3】:

      如果您只想删除所有更改,请选择 git checkout . 这是一种更快、更简单的方法。

      【讨论】:

        【解决方案4】:

        在此处添加另一个选项。

        我指的是标题:还原本地更改。
        它还可以应用于未暂存以进行提交的更改。

        在这种情况下,您可以使用:

        git restore <file>
        

        返回之前的状态。

        【讨论】:

        • 要恢复当前本地目录中的所有文件更改,您可以使用: git restore .
        • 最好的答案在这里
        • 请运行 git help - 你应该在那里看到它..(:
        【解决方案5】:

        在阅读了一堆答案并尝试之后,我发现了各种边缘情况,这意味着有时它们不能完全清理工作副本。

        这是我当前的 bash 脚本,它一直有效。

        #!/bin/sh
        git reset --hard
        git clean -f -d
        git checkout HEAD
        

        从工作副本根目录运行。

        【讨论】:

        • 最后一个命令给了我error: pathspec 'HEAD' did not match any file(s) known to git.
        • 当我取出“--”时它对我有用。 git checkout HEAD
        • git reset --hard 恢复跟踪的文件(暂存与否),git clean -f -d 删除未跟踪的文件,git checkout -- HEAD 那我们为什么需要这个?
        • 我们不需要双连字符。一定是错字。
        • 删除了git checkout -- HEAD 中的--,因为这不是一个有效的命令,而git checkout HEAD 是。
        【解决方案6】:

        只需执行 -

        git stash
        

        它将删除您的所有本地更改。你也可以稍后通过执行来使用它 -

        git stash apply 
        

        【讨论】:

        • 使用 git stash pop 会自动为您删除最顶层的隐藏更改
        • git stash drop 删除最新的隐藏状态而不应用于工作副本。
        • git stash apply 不会添加新创建的文件
        【解决方案7】:

        这个问题更多的是关于更广泛的存储库重置/恢复,但如果您有兴趣恢复个别更改 - 我在这里添加了类似的答案:

        https://stackoverflow.com/a/60890371/2338477

        问题的答案:

        • 如何在 git 历史记录中保留或不保留更改来恢复单个更改

        • 如何返回旧版本以从相同状态重新启动

        【讨论】:

          【解决方案8】:

          重新克隆

          GIT=$(git rev-parse --show-toplevel)
          cd $GIT/..
          rm -rf $GIT
          git clone ...
          
          • ✅ 删除本地、非推送的提交
          • ✅ 还原您对跟踪文件所做的更改
          • ✅ 恢复您删除的跟踪文件
          • ✅ 删除.gitignore 中列出的文件/目录(如构建文件)
          • ✅ 删除未跟踪且不在.gitignore 中的文件/目录
          • ? 你不会忘记这种方法
          • ? 浪费带宽

          以下是我每天忘记的其他命令。

          清理并重置

          git clean --force -d -x
          git reset --hard
          
          • ❌ 删除本地、非推送的提交
          • ✅ 还原您对跟踪文件所做的更改
          • ✅ 恢复您删除的跟踪文件
          • ✅ 删除.gitignore 中列出的文件/目录(如构建文件)
          • ✅ 删除未跟踪且不在.gitignore 中的文件/目录

          清洁

          git clean --force -d -x
          
          • ❌ 删除本地、非推送的提交
          • ❌ 还原您对跟踪文件所做的更改
          • ❌ 恢复您删除的跟踪文件
          • ✅ 删除.gitignore 中列出的文件/目录(如构建文件)
          • ✅ 删除未跟踪且不在.gitignore 中的文件/目录

          重置

          git reset --hard
          
          • ❌ 删除本地、非推送的提交
          • ✅ 还原您对跟踪文件所做的更改
          • ✅ 恢复您删除的跟踪文件
          • ❌ 删除.gitignore 中列出的文件/目录(如构建文件)
          • ❌ 删除未跟踪且不在.gitignore 中的文件/目录

          注意事项

          确认以上所有的测试用例(使用 bash 或 sh):

          mkdir project
          cd project
          git init
          echo '*.built' > .gitignore
          echo 'CODE' > a.sourceCode
          mkdir b
          echo 'CODE' > b/b.sourceCode
          cp -r b c
          git add .
          git commit -m 'Initial checkin'
          echo 'NEW FEATURE' >> a.sourceCode
          cp a.sourceCode a.built
          rm -rf c
          echo 'CODE' > 'd.sourceCode'
          

          另请参阅

          • git revert 进行撤消先前提交的新提交
          • git checkout 及时返回到之前的提交(可能需要先运行上述命令)
          • git stash 与上面的git reset 相同,但您可以撤消它

          【讨论】:

          • 我很确定,第一个选项(Re-clone)实际上确实“删除了本地、非推送的提交”:)
          • @styfle ✅ 是它做的事,❌ 是它不做的事
          • @FullDecent 读起来有点混乱。 “❌ 不删除本地的、非推送的提交”。这意味着它不会删除。双重否定意味着它确实删除了?
          • 关于git clean -f -d -x 中的-x 标志:如果指定了-x 选项,也会删除被忽略的文件。例如,这对于删除所有构建产品很有用。- 从 GIT 文档
          • @calyxofheld 它并没有说它会删除未跟踪的文件。 ❌ 表示“它不做”,✅ 表示它做。在重置部分,我看到“❌删除未跟踪且不在 .gitignore 中的文件/目录”。
          【解决方案9】:

          我搜索了一个类似的问题,

          想要丢弃本地提交:

          1. 克隆了存储库(git clone)
          2. 切换到开发分支(git checkout dev)
          3. 很少提交 (git commit -m "commit 1")
          4. 但决定丢弃这些本地提交以返回远程(源/开发)

          以下也是如此:

          git reset --hard origin/dev
          

          检查:

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

          现在本地提交丢失,回到最初的克隆状态,上面的第 1 点。

          【讨论】:

          • 谢谢,这是唯一对我有用的东西——“git reset --hard origin”
          • 很高兴知道它有帮助。
          • 这是唯一对我有用的东西。非常感谢
          【解决方案10】:

          尝试恢复本地分支中未提交的所有更改

          $ git reset --hard HEAD
          

          但是如果你看到这样的错误:

          fatal: Unable to create '/directory/for/your/project/.git/index.lock': File exists.
          

          您可以导航到 '.git' 文件夹然后删除 index.lock 文件:

          $ cd /directory/for/your/project/.git/
          $ rm index.lock
          

          最后,再次运行命令:

          $ git reset --hard HEAD
          

          【讨论】:

            【解决方案11】:

            如果您想恢复对工作副本所做的更改,请执行以下操作:

            git checkout .
            

            如果您想恢复对索引所做的更改(即您添加的),请执行此操作。 警告这会将您所有未推送的提交重置为 master!

            git reset
            

            如果您想恢复已提交的更改,请执行以下操作:

            git revert <commit 1> <commit 2>
            

            如果您想删除未跟踪的文件(例如,新文件、生成的文件):

            git clean -f
            

            或未跟踪的目录(例如,新的或自动生成的目录):

            git clean -fd
            

            【讨论】:

            • fwiw 这么长时间后,git checkout path/to/file 只会将本地更改还原为path/to/file
            • +1 在下面的答案中还提到了 git clean -f(删除未跟踪的更改)和 -fd(也删除未跟踪的目录)
            • git checkout .git reset [--hard HEAD] 不起作用,我必须执行 git clean -fd 才能恢复我的更改。
            • git reset 不会重置您的更改,git reset --hard 会这样做。
            • 警告完全错误!首先, git reset 在当前分支(HEAD)上工作,它的作用与“master”分支无关。此外,reset 与未推送的提交无关,不,您不会因为使用 git reset 而自动丢失它们。
            【解决方案12】:

            您可能不一定想要/需要将您的工作/文件存放在您的工作目录中,而只是完全摆脱它们。命令git clean 将为您执行此操作。

            执行此操作的一些常见用例是删除由合并或外部工具生成的 cruft 或删除其他文件,以便您可以运行干净的构建。

            请记住,您需要非常谨慎地使用此命令,因为它旨在从本地工作目录中删除未跟踪的文件。如果您在执行此命令后突然改变主意,则无法回头查看已删除文件的内容。另一种更安全的方法是执行

            git stash --all

            这将删除所有内容,但将其全部保存在一个藏匿处。然后可以稍后使用此存储。

            然而,如果你真的想删除所有文件并清理你的工作目录,你应该执行

            git clean -f -d

            这将删除所有文件以及由于该命令而没有任何项目的任何子目录。在执行git clean -f -d 命令之前,明智的做法是运行

            git clean -f -d -n
            

            这将向您显示执行git clean -f -d 后将删除的内容的预览

            所以这里是您的选项的摘要,从最激进到最不激进


            选项 1:在本地删除所有文件(最激进)

            git clean -f -d
            

            选项2:预览上述影响(预览最激进)

            git clean -f -d -n
            

            选项 3:存储所有文件(最不激进)

            `git stash --all` 
            

            【讨论】:

              【解决方案13】:

              如果您想恢复所有更改并与当前的远程 master 保持同步(例如,您发现 master HEAD 自从您分支它以来已经向前移动并且您的推送被“拒绝”),您可以使用

              git fetch  # will fetch the latest changes on the remote
              git reset --hard origin/master # will set your local branch to match the representation of the remote just pulled down.
              

              【讨论】:

              • git reset --hard origin/master(有效)中指定origin 似乎很重要——没有它(即git reset --hard)似乎什么都没有改变。
              • 我有一些本地更改,但无法通过我执行的任何命令来摆脱它们 git reset --hard origin/master 并且它也能够提取 master 的更改
              【解决方案14】:

              注意:您可能还想运行

              git clean -fd
              

              作为

              git reset --hard
              

              删除未跟踪的文件,而 git-clean 将从已跟踪的根目录中删除不在 git 跟踪下的所有文件。警告 - 小心这个!最好先用 git-clean 运行一次试运行,看看它会删除什么。

              当您收到错误消息时,这也特别有用

              ~"performing this command will cause an un-tracked file to be overwritten"
              

              在做几件事时可能会发生这种情况,当您和您的朋友都添加了一个同名的新文件时更新工作副本,但他首先将其提交到源代码管理中,而您并不关心删除您的未跟踪副本。

              在这种情况下,进行试运行还有助于向您显示将被覆盖的文件列表。

              【讨论】:

              • 文件清理命令是“git clean -f”。使用“git clean -d”删除未跟踪的目录
              • git clean -fd(-d 需要强制)
              • -n 或 --dry-run 是空运行的标志。
              • git clean -ffd 如果您的 git 存储库中有另一个 git 存储库。如果没有 double f,它将不会被删除。
              【解决方案15】:

              前面的危险:(请阅读 cmets。执行我的回答中提出的命令可能会删除比你想要的更多)

              彻底删除所有文件,包括我必须运行的目录

              git clean -f -d
              

              【讨论】:

              • 为了避免我刚刚经历的痛苦:这也会删除 .gitignore-d 文件!
              • 很抱歉给您带来任何麻烦。那时我只是试图恢复并删除该文件夹中的所有内容。我不记得确切的情况,但“-d”是唯一对我有用的东西。我希望我没有给你带来太多痛苦:-)
              • 没有伤害。我有备份,但这可能需要免责声明;)
              【解决方案16】:

              我遇到了类似的问题。 解决方案是使用git log 查找本地提交的哪个版本与远程不同。 (例如版本是3c74a11530697214cbcc4b7b98bf7a65952a34ec)。

              然后使用git reset --hard 3c74a11530697214cbcc4b7b98bf7a65952a34ec 恢复更改。

              【讨论】:

                【解决方案17】:

                查看 git-reflog。它将列出它记住的所有状态(默认为 30 天),您可以简单地检查您想要的状态。例如:

                $ git init > /dev/null
                $ touch a
                $ git add .
                $ git commit -m"Add file a" > /dev/null
                $ echo 'foo' >> a
                $ git commit -a -m"Append foo to a" > /dev/null
                $ for i in b c d e; do echo $i >>a; git commit -a -m"Append $i to a" ;done > /dev/null
                $ git reset --hard HEAD^^ > /dev/null
                $ cat a
                foo
                b
                c
                $ git reflog
                145c322 HEAD@{0}: HEAD^^: updating HEAD
                ae7c2b3 HEAD@{1}: commit: Append e to a
                fdf2c5e HEAD@{2}: commit: Append d to a
                145c322 HEAD@{3}: commit: Append c to a
                363e22a HEAD@{4}: commit: Append b to a
                fa26c43 HEAD@{5}: commit: Append foo to a
                0a392a5 HEAD@{6}: commit (initial): Add file a
                $ git reset --hard HEAD@{2}
                HEAD is now at fdf2c5e Append d to a
                $ cat a
                foo
                b
                c
                d
                

                【讨论】:

                • 非常感谢 William 提供 git reflog。我将树重置为旧版本,不知道如何恢复到最近。你的 git reflog 救了我。再次感谢。
                • 也救了我!在我的情况下,我与git rebase -i 的冒险出了问题(由于编辑错误最终清除了一些提交)。多亏了这个提示,我恢复了良好的状态!
                • 默认 30 天是什么意思!?
                • @MoheTheDreamy 我的意思是有时间限制。最终,当它们的年龄超过该限制时,垃圾收集器将删除无法访问的引用。默认值曾经是(也许现在仍然是)30 天。所以旧的参考文献可能不可用。
                猜你喜欢
                • 2011-10-21
                • 1970-01-01
                • 1970-01-01
                • 2011-06-27
                • 1970-01-01
                • 1970-01-01
                • 2021-05-22
                • 1970-01-01
                相关资源
                最近更新 更多