【问题标题】:Reset local repository branch to be just like remote repository HEAD将本地存储库分支重置为就像远程存储库 HEAD
【发布时间】:2010-12-10 07:54:17
【问题描述】:

如何将我的本地分支重置为与远程存储库上的分支一样?

我做到了:

git reset --hard HEAD

但是当我运行git status时,

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   java/com/mycompany/TestContacts.java
      modified:   java/com/mycompany/TestParser.java

你能告诉我为什么我有这些'修改'?我没碰过这些文件?如果我这样做了,我想删除它们。

【问题讨论】:

  • 根据git status 的输出,您的第二个命令git reset --hard HEAD 失败。不过,您没有粘贴它的输出。 → 不完整的问题。
  • 您在这里混合了两个问题:1)如何将本地分支重置到远程位置以及 2)如何清除暂存区域(可能还有工作目录),以便 @ 987654327@ 说nothing to commit, working directory clean。 – 请说明!
  • 如果 repo 很大,显然不是答案,但是对于小的 repo,你可以用锤子敲它并完全避免 git:rm -fr ./repo; git clone repo。我发现的最好方法

标签: git undo


【解决方案1】:

git reset --hard HEAD 实际上只重置为最后提交的状态。在这种情况下,HEAD 是指您的分支的 HEAD。

如果您有多个提交,这将不起作用..

您可能想要做的是重置为源头或远程存储库被调用的任何内容。我可能会做类似的事情

git reset --hard origin/HEAD

不过要小心。硬重置不能轻易撤消。最好按照 Dan 的建议去做,并在重置之前将更改的副本分支出来。

【讨论】:

  • 我的回答中有一个不正确的建议,Dan 早些时候发现了这个建议。我把它删掉了,因为我不想让任何人误入歧途。至于 origin/master 或 origin/HEAD 的东西,我希望这取决于你是否真的先进行 fetch。如果您只是克隆了 origin,并且它没有其他分支,我发现这很常见,那么它应该重置它。但当然,丹是对的。
【解决方案2】:

将您的分支设置为与远程分支完全匹配可以分两步完成:

git fetch origin
git reset --hard origin/master

如果您想在执行此操作之前保存当前分支的状态(以防万一),您可以这样做:

git commit -a -m "Saving my work, just in case"
git branch my-saved-work

现在,您的工作已保存在“my-saved-work”分支中,以防您决定将其取回(或想稍后查看或将其与更新后的分支进行比较)。

请注意,第一个示例假定远程仓库的名称是“origin”,并且远程仓库中名为“master”的分支与本地仓库中当前签出的分支匹配。

顺便说一句,您所处的这种情况看起来很像一种常见的情况,即推送到非裸存储库的当前签出分支中。您最近是否推送到本地仓库?如果没有,那么不用担心——肯定是其他原因导致这些文件意外地最终被修改。否则,您应该知道不建议推送到非裸存储库(特别是不要推送到当前签出的分支)。

【讨论】:

  • 感谢您的回答。你说'请注意,第一个示例假设远程仓库的名称是“origin”,并且远程仓库中名为“master”的分支与本地仓库中的分支匹配。在执行“git reset --hard”之前,如何仔细检查远程仓库的名称和分支名称以确保?再次感谢。
  • 如果你没有明确命名遥控器,那么它的名字很可能只是“起源”(默认)。您可以使用“git remote”来获取所有远程名称的列表。然后,您可以使用“git remote ”查看哪些分支相互推/拉(例如,如果您的“master”分支是从名为“origin”的远程中的“master”克隆的,那么您将得到一行上面写着“master 与 remote master 合并”)。
  • "不建议推送到非裸仓库中(尤其不要推送到当前签出的分支中)"为什么?
  • 刚抓取完,相信你也可以改成git reset FETCH_HEAD --hard,也是这个意思。
  • 它没有删除我添加的文件。
【解决方案3】:

如果你想为工作目录和索引返回HEAD 状态,那么你应该git reset --hard HEAD,而不是HEAD^。 (这可能是一个错字,就像--hard 的单破折号和双破折号一样。)

至于您关于为什么这些文件显示为已修改状态的具体问题,看起来您可能进行了软重置而不是硬重置。这将导致在 HEAD 提交中更改的文件看起来好像它们是暂存的,这很可能是您在此处看到的。

【讨论】:

    【解决方案4】:

    这是一个脚本,可以自动执行最流行的答案所建议的内容... 有关支持分支的改进版本,请参阅 https://stackoverflow.com/a/13308579/1497139

    #!/bin/bash
    # reset the current repository
    # WF 2012-10-15
    # see https://stackoverflow.com/questions/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
    timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
    git commit -a -m "auto commit at $timestamp"
    if [ $? -eq 0 ]
    then
      git branch "auto-save-at-$timestamp" 
    fi
    git fetch origin
    git reset --hard origin/master
    

    【讨论】:

      【解决方案5】:

      这是我经常遇到的问题,我已经概括了 Wolfgang 上面提供的脚本以适用于任何分支

      我还添加了“你确定”提示和一些反馈输出

      #!/bin/bash
      # reset the current repository
      # WF 2012-10-15
      # AT 2012-11-09
      # see http://stackoverflow.com/questions/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
      timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
      branchname=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
      read -p "Reset branch $branchname to origin (y/n)? "
      [ "$REPLY" != "y" ] || 
      echo "about to auto-commit any changes"
      git commit -a -m "auto commit at $timestamp"
      if [ $? -eq 0 ]
      then
        echo "Creating backup auto-save branch: auto-save-$branchname-at-$timestamp"
        git branch "auto-save-$branchname-at-$timestamp" 
      fi
      echo "now resetting to origin/$branchname"
      git fetch origin
      git reset --hard origin/$branchname
      

      【讨论】:

      • 您可能想使用“git remote”来获取远程的名称。在某些情况下,它不会是“原点”
      • 您脚本中的逻辑不正确。 [ "$REPLY" != "y" ] || 只会跳过下一行 echo "about to auto-commit any changes" 并继续运行脚本的其余部分。该行的内容应类似于[[ "$REPLY" != "y" ]] &amp;&amp; { echo "Exiting branch reset"; exit; }
      【解决方案6】:

      我做到了:

      git branch -D master
      git checkout master
      

      完全重置分支


      注意,您应该结帐到另一个分支才能删除所需的分支

      【讨论】:

      • 你应该再次阅读问题,没有什么影响远程,但设置为与远程相同,所以你不应该对远程做任何事情,这对我的情况有帮助,而不是以上。
      • 如果您想将其设置为与远程相同,您至少应该在某个时候进行一次提取,您不同意吗?
      • 你至少应该试试这个或阅读文档:kernel.org/pub/software/scm/git/docs/git-checkout.html
      • 好的,我在分支中有一个损坏的 .pck 文件,其他选项都不起作用,谢谢!!
      【解决方案7】:

      如果你和我一样有问题,你已经提交了一些更改,但是现在,出于任何原因你想摆脱它,最快的方法是像这样使用git reset

      git reset --hard HEAD~2
      

      我有 2 个不需要的提交,因此编号为 2。您可以将其更改为您自己的提交数以重置。

      所以回答你的问题 - 如果你在远程存储库 HEAD 之前提交了 5 次提交,你应该运行这个命令:

      git reset --hard HEAD~5
      

      请注意,您将丢失所做的更改,所以要小心!

      【讨论】:

        【解决方案8】:

        如果您不介意保存本地更改,但仍想更新存储库以匹配源/HEAD,您可以简单地存储本地更改,然后拉取:

        git stash
        git pull
        

        【讨论】:

          【解决方案9】:

          我需要做(已接受答案中的解决方案):

          git fetch origin
          git reset --hard origin/master
          

          接着是:

          git clean -f
          

          to remove local files

          查看哪些文件将被删除(不实际删除):

          git clean -n -f
          

          【讨论】:

          • 另外,git clean -d -f 如果存在未跟踪的目录。
          • 还有git clean -fdx
          • 如果你想要远程分支的精确副本,你必须跟随 git clean -ffdx。请注意,这是两个 f。
          • git clean -f 是我需要的重要部件。谢谢!
          • 小心使用 clean 命令。它可以从其他分支中删除被忽略的文件。
          【解决方案10】:

          首先,使用git reset重置为之前获取的对应上游分支的HEAD

          git reset --hard @{u}
          

          指定@{u} 或其详细形式@{upstream} 的优点是不必显式指定远程repo 和分支的名称。在 Windows 或 PowerShell 中,指定 "@{u}"(带双引号)。

          接下来,根据需要,使用git clean 删除未跟踪的文件,也可以选择使用-x

          git clean -df
          

          最后,根据需要,获取最新的更改:

          git pull
          

          【讨论】:

          • 这似乎是一个比接受的更好的答案,因为它会动态重置到当前的上游分支,而不是总是像origin/master这样的静态分支
          • @GangadharJannu git reset --hard 需要提交,否则它不知道将您重置为什么。 @{u} 指向一个特定的提交——被跟踪分支的头部,从你上次执行 git fetch 开始。
          • @KristofferBakkejord 感谢您的解释,但即使没有提交哈希,我们也可以执行git reset --hard,尽管它不会重置为远程分支
          • 对于几乎在这里提出新问题的其他人,如果您从 Powershell 进行 git,请使用引号 (git reset --hard "@{u}")。我花了一段时间才弄明白。
          • @MPStoering 使用引号也适用于 Windows 上的 git bash。干杯
          【解决方案11】:

          以上所有建议都是正确的,但通常要真正重置您的项目,您还需要删除 .gitignore 中的文件。

          从远程删除项目目录并重新克隆的道德等价物是:

          git fetch
          git reset --hard
          git clean -x -d -f
          

          警告git clean -x -d -f不可逆的,您可能会丢失文件和数据(例如,您使用 .gitignore 忽略的内容)。

          【讨论】:

          • 警告:“git clean -x -d -f”是不可逆的,你可能会丢失 .gitignore 中的文件和数据
          • 短一点:git clean -xdf 等于git clean -x -d -f
          • git clean -ffxd 删除所有不在 repo 中的东西
          【解决方案12】:

          这个问题在这里混合了两个问题:

          1. 如何将本地分支重置到远程所在的位置
          2. 如何清除暂存区(可能还有工作目录),以便git status 显示为nothing to commit, working directory clean.

          一站式答案是:

          1. git fetch --prune (可选)更新远程仓库的本地快照。其他命令仅限本地。
            git reset --hard @{upstream}将本地分支指针指向远程快照所在的位置,并设置索引和工作目录到该提交的文件。
          2. git clean -d --force 删除阻碍 git 说“工作目录干净”的未跟踪文件和目录。

          【讨论】:

          • @{upstream} 语法需要设置上游,如果您使用git checkout &lt;branchname&gt;,默认情况下会发生这种情况。 – 否则替换为origin/&lt;branchname&gt;
          • -x 添加到git clean 以删除不在提交中的所有内容(即,即使是使用 .gitignore 机制忽略的文件)。
          【解决方案13】:

          以前的答案假设要重置的分支是当前分支(已签出)。在 cmets 中,OP hap497 澄清了该分支确实已签出,但这不是原始问题明确要求的。由于至少有一个“重复”问题Reset branch completely to repository state,它不假定分支已被签出,所以这里有一个替代方案:

          如果分支“mybranch”当前检出,要将其重置为远程分支“myremote/mybranch”的头部,您可以使用此low-level 命令:

          git update-ref refs/heads/mybranch myremote/mybranch
          

          此方法将签出的分支保持原样,并且工作树保持不变。它只是将 mybranch 的头部移动到另一个提交,无论作为第二个参数给出什么。如果需要将多个分支更新为新的远程头,这将特别有用。

          但在执行此操作时要小心,并使用gitk 或类似工具仔细检查源和目标。如果你不小心在当前分支上这样做了(并且 git 不会阻止你这样做),你可能会感到困惑,因为新的分支内容与工作树不匹配,工作树没有改变(修复,再次更新分支,到原来的位置)。

          【讨论】:

            【解决方案14】:

            没有多少重置和清理似乎对我本地 git repo 中未跟踪和修改的文件有任何影响(我尝试了上面的所有选项)。我对此的唯一解决方案是 rm 本地 repo 并从远程重新克隆它。

            幸运的是我没有其他我关心的分支。

            xkcd: Git

            【讨论】:

              【解决方案15】:

              前提是远程仓库是origin,并且你对branch_name感兴趣:

              git fetch origin
              git reset --hard origin/<branch_name>
              

              另外,你将origin的当前分支重置为HEAD

              git fetch origin
              git reset --hard origin/HEAD
              

              工作原理:

              git fetch origin 从远程下载最新版本,而不尝试合并或变基任何内容。

              然后git reset&lt;branch_name&gt; 分支重置为您刚刚获取的内容。 --hard 选项会更改工作树中的所有文件以匹配 origin/branch_name 中的文件。

              【讨论】:

              • 我不确定我在这里关注origin/HEAD,我认为这不正确
              【解决方案16】:

              在我见过的所有情况下,唯一可行的解​​决方案是删除和重新克隆。也许还有另一种方式,但显然这种方式不会留下旧状态的机会,所以我更喜欢它。如果您经常在 git 中搞砸事情,您可以将 Bash 单线设置为宏:

              REPO_PATH=$(pwd) && GIT_URL=$(git config --get remote.origin.url) && cd .. && rm -rf $REPO_PATH && git clone --recursive $GIT_URL $REPO_PATH && cd $REPO_PATH
              

              * 假设您的 .git 文件没有损坏

              【讨论】:

              • 如果你想确定,你也可以重新安装你的操作系统!
              【解决方案17】:

              这是我经常使用的:

              git fetch upstream develop;
              git reset --hard upstream/develop;
              git clean -d --force;
              

              请注意,最好不要对本地 master/develop 分支进行更改,而是将任何更改签出到另一个分支,分支名称前面要加上更改类型,例如feat/chore/fix/ 等。因此您只需要拉取更改,而不需要从 master 推送任何更改。其他人贡献的其他分支也是如此。因此,仅当您碰巧将更改提交到其他人已提交的分支并需要重置时,才应使用上述内容。否则以后避免推送到其他人推送到的分支,而是通过签出分支结帐并推送到所述分支。

              如果您想将本地分支重置为上游分支中的最新提交,到目前为止对我有用的是:

              检查您的遥控器,确保您的上游和来源符合您的预期,如果不符合预期,请使用git remote add upstream &lt;insert URL&gt;,例如您派生出的原始 GitHub 存储库和/或 git remote add origin &lt;insert URL of the forked GitHub repo&gt;

              git remote --verbose
              
              git checkout develop;
              git commit -m "Saving work.";
              git branch saved-work;
              git fetch upstream develop;
              git reset --hard upstream/develop;
              git clean -d --force
              

              在 GitHub 上,您还可以签出与本地分支同名的分支,以便将工作保存在那里,尽管如果原始开发与本地保存的工作分支具有相同的更改,则不需要这样做。我以开发分支为例,但它可以是任何现有的分支名称。

              git add .
              git commit -m "Reset to upstream/develop"
              git push --force origin develop
              

              然后,如果您需要在有任何冲突的情况下将这些更改与另一个分支合并,保留开发中的更改,请使用:

              git merge -s recursive -X theirs develop
              

              使用时

              git merge -s recursive -X ours develop
              

              保留 branch_name 的冲突更改。否则使用带有git mergetool 的合并工具。

              将所有更改放在一起:

              git commit -m "Saving work.";
              git branch saved-work;
              git checkout develop;
              git fetch upstream develop;
              git reset --hard upstream/develop;
              git clean -d --force;
              git add .;
              git commit -m "Reset to upstream/develop";
              git push --force origin develop;
              git checkout branch_name;
              git merge develop;
              

              请注意,您可以使用提交哈希、其他分支名称等代替上游/开发。使用 CLI 工具(例如 Oh My Zsh)检查您的分支是否为绿色,表示没有任何内容可提交和工作目录是干净的(由git status 确认或验证)。请注意,如果提交自动添加了任何内容,则与上游开发相比,这实际上可能会添加提交,例如UML 图、许可证头等,所以在这种情况下,如果需要,您可以将origin develop 上的更改拉到upstream develop

              【讨论】:

                【解决方案18】:

                使用以下命令。这些命令也会从本地 git 中删除所有未跟踪的文件

                git fetch origin
                git reset --hard origin/master
                git clean -d -f
                

                【讨论】:

                • 这是一个更完整的响应,因为没有git clean -d -f,我们在本地目录中仍然会有一些旧分支的东西。谢谢大佬。
                • 这就是真正让它像遥控器一样的原因。清洁很重要。
                • git clean -ffxd 真正删除一切
                • 这正是我所需要的。谢谢
                【解决方案19】:

                您是否忘记创建功能分支并错误地直接在 master 上提交?

                您现在可以创建功能分支并将 master 设置回来,而不会影响 工作树(本地文件系统)以避免触发构建、测试和文件锁定问题:

                git checkout -b feature-branch
                git branch -f master origin/master
                

                【讨论】:

                  【解决方案20】:

                  只有 3 个命令可以让它工作

                  git fetch origin
                  git reset --hard origin/HEAD
                  git clean -f
                  

                  【讨论】:

                    【解决方案21】:

                    答案

                    git clean -d -f
                    

                    被低估了(-d 删除目录)。 谢谢!

                    【讨论】:

                    • 对于没有额外文件的完整、100% 干净的 repo 文件夹,请运行 git clean -xdf。这将删除 git 不知道的所有文件,并使您的文件夹与 git 对象列表中的内容完全匹配。请注意,您可以添加-n(例如git clean -nxdf)来执行“假设”,它会告诉您它将删除什么而无需实际执行任何操作。 (git clean)
                    猜你喜欢
                    • 2022-11-09
                    • 2011-09-16
                    • 2013-06-09
                    • 1970-01-01
                    • 2010-12-04
                    相关资源
                    最近更新 更多