将本地代码库分支重置为与远程代码库HEAD完全一致

5624

如何将本地分支重置为与远程仓库中的分支完全相同?

我试过:

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

17
根据 git status 的输出,你的第二个命令 git reset --hard HEAD 失败了。不过你没有粘贴它的输出。→ 问题不完整。 - Robert Siemer
5
你在混淆两个问题:1)如何将本地分支重置到与远程相同的点;2)如何清除暂存区(以及可能的工作目录),以便git status显示“nothing to commit, working directory clean”。请具体说明你需要的是哪一个。 - Robert Siemer
3
这回答是否解决了你的问题?如何强制“git pull”覆盖本地文件? - Henke
你救了我的命...爱你...我试图检出另一个空的分支...但是没有成功...这时我的一周工作都没了...而且我无法按时完成任务。谢天谢地! - Rajib
git reset --hard FETCH_HEAD 对我来说很有效。我在变基之后没有推送。 - undefined
显示剩余2条评论
27个回答

9651
将您的分支设置为与远程分支完全匹配可以分为两个步骤:
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"的分支与本地仓库中当前检出的分支相匹配。
顺便说一下,你目前所处的情况非常类似于一个常见的情况,即将推送到非裸仓库的当前检出分支。你最近是否向本地仓库推送了代码?如果没有,那就不用担心——其他原因导致这些文件意外修改。否则,你应该知道不建议向非裸仓库推送代码(尤其是当前检出的分支)。

4
谢谢您的提问。您说:“请注意,第一个示例假定远程仓库的名称为“origin”,并且远程仓库中名为“master”的分支与本地仓库中的分支相匹配。”在执行“git reset --hard”之前,我如何确认我的远程仓库名称和分支名称?再次感谢。 - hap497
30
如果您没有显式命名远程仓库,则其名称很可能只是“origin”(默认值)。您可以使用“git remote”获取所有远程仓库的名称列表。然后,您可以使用“git remote <name>”查看哪些分支进行推送/拉取操作(例如,如果您的“master”分支是从名为“origin”的远程仓库中的“master”分支克隆而来,则会显示一行内容,说明“master”与远程“master”合并)。 - Dan Moulding
8
为什么不建议将内容推送到非裸库(特别是当前签出的分支)? - Lee Goddard
47
我相信在拉取完之后,你可以用git reset FETCH_HEAD --hard,同样也是有相同的意义。 - Jean
13
它没有删除我添加的文件。 - Trismegistos
显示剩余22条评论

638

我需要执行(被接受答案中的解决方案):

git fetch origin
git reset --hard origin/master

接着是:

git clean -f

删除本地文件

查看将要被删除的文件(不实际删除):

git clean -n -f

120
此外,如果存在未跟踪的目录,则需使用git clean -d -f指令。 - garg
75
也包括 git clean -fdx - Swapnil Kotwal
20
如果你想要远程分支的完全副本,你需要执行 git clean -ffdx 命令。请注意其中有两个 f。 - Trismegistos
11
git clean -f 是我所需要的关键命令。谢谢! - dgo
21
谨慎使用"clean"命令,它可能会从其他分支中删除被忽略的文件。 - mikoop
显示剩余5条评论

625

首先使用 git reset 命令将本地代码库回滚到之前从远程同步的对应上游分支的 HEAD 状态:

git reset --hard @{u}

指定 @{u} 或其冗长形式 @{upstream} 的优点是不必显式指定远程存储库和分支的名称。在 Windows 或 PowerShell 上,使用双引号指定 "@{u}"

接下来,如有需要,请使用git clean删除未跟踪的文件,也可选使用-x

git clean -df

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

git pull

99
这个答案似乎比被采纳的更好,因为它会动态重置到当前的上游分支而不总是一个静态的分支,比如origin/master - Jon z
4
@GangadharJannu git reset --hard 需要一个提交,否则它不知道要重置到哪里。@{u} 指向一个特定的提交 - 跟踪分支的头部,从你上次执行 git fetch 开始。 - Kristoffer Bakkejord
1
@KristofferBakkejord 感谢您的解释,但即使没有提交哈希,我们也可以执行 git reset --hard,虽然它不会重置到远程分支。 - Buddybear
13
对于那些几乎在这里开了一个新问题的人,如果你从PowerShell使用git,请使用引号(`git reset --hard "@{u}") 。我花了一段时间才弄明白这个。 - MPStoering
1
@MPStoering 在 Windows 上使用引号也可以在 git bash 中正常工作。干杯 - Jason S
显示剩余6条评论

212

git reset --hard origin/{branch-name}

git reset --hard origin/HEAD

不过要小心,硬重置并不容易撤销。最好按照Dan的建议,在重置之前分支复制你的更改。


3
我的回答中有一个错误的建议被 Dan 指出来了,我已经编辑掉了,因为我不想误导任何人。至于 origin/master 或 origin/HEAD 的问题,我认为这取决于你是否真正执行了 fetch 操作。如果你只是克隆了 origin,并且它没有其他分支,这在我看来相当常见,那么它应该可以很好地重置。但是,Dan 当然是正确的。 - Mikael Ohlson
这个不起作用,因为origin/HEAD不一定是你当前分支在origin上最新的提交。请使用以下命令代替:git reset --hard @{u} - Xys

100

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

要达到与擦除项目目录并重新克隆相当的道德效果是:

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

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


15
警告:执行 "git clean -x -d -f" 操作是不可逆的,可能会删除 .gitignore 中忽略的文件和数据。请谨慎操作。 - Akarsh Satija
3
简短一些的命令为:git clean -xdf,等同于 git clean -x -d -f - Kiryl
2
使用 git clean -ffxd 命令可以删除除了代码库中的文件以外的所有内容。 - Trismegistos

69

使用以下命令。这些命令将从本地Git中删除所有未被跟踪的文件。

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

6
这是一个更完整的回复,因为如果没有 git clean -d -f,我们本地目录中仍然会有旧分支的一些内容。谢谢。 - Flavio
4
使用 "git clean -ffxd" 命令可以彻底删除所有内容。 - Trismegistos

49

这个问题涉及两个方面:

  1. 如何将本地分支重置为与远程分支相同的点
  2. 如何清空您的暂存区(以及可能是工作目录),使得git status显示nothing to commit, working directory clean.

一站式答案为:

  1. git fetch --prune (可选) 更新远程仓库的本地快照。后续命令仅针对本地操作。
    git reset --hard @{upstream}将本地分支指针设置到远程分支的快照处,并将索引和工作目录设置为该提交的文件。
  2. git clean -d --force 删除未跟踪的文件和目录,这些文件和目录会妨碍git显示“working directory clean”。

2
@{upstream} 语法要求必须设置 upstream,如果你使用 git checkout <branchname> 命令,则默认会设置。否则,请将其替换为 origin/<branchname> - Robert Siemer
git clean 后添加 -x,可以删除所有未提交的内容(即使是通过 .gitignore 忽略的文件)。 - Robert Siemer

34

假设远程仓库是 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 重置 <branch_name> 分支为刚刚获取的版本。 --hard 选项将工作树中的所有文件更改为与 origin/branch_name 中的文件相匹配。


1
我不确定我在这里理解origin/HEAD,我认为这是不正确的。 - CervEd
1
这就是我一直在寻找的。其他的答案都是通过远程主分支重置,我想知道的是远程当前分支。不过答案相当直接明了。 - undefined

28

您可以获取原始数据并进行重置以解决问题。

 git fetch origin
 git reset --hard origin/main

您可以在重置之前像下面这样保存您的更改,

git stash

在重置后,如果您希望恢复更改,只需运行以下命令即可:

git stash apply

28

我经常会遇到这个问题,而且我已经将Wolfgang提供的脚本概括为适用于任何分支。

我还添加了一个“你确定吗”的提示,以及一些反馈输出。

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# AT 2012-11-09
# see https://dev59.com/U3I-5IYBdhLWcg3w48xP
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

3
有时候,你可能需要使用“git remote”命令来获取远程仓库的名称,而不是默认的“origin”。请注意,翻译后的内容应该保留原意,同时保持语言简洁易懂。 - Yuri Astrakhan
你的脚本逻辑不正确。[ "$REPLY" != "y" ] || 只会跳过下一行 echo "about to auto-commit any changes" 并继续运行脚本的其余部分。 这一行应该改为类似于 [[ "$REPLY" != "y" ]] && { echo "Exiting branch reset"; exit; } - jgshawkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接