如何将Git仓库回滚(reset)到特定的提交?

798

我克隆了一个 Git 仓库,然后尝试将其回滚到开发过程中的特定提交。对于在该点之后添加到存储库的所有内容,我都不关心,因此我想从我的本地源代码中省略所有后续更改。

然而,当我尝试在 GUI 工具中回滚时,它并不会更新我的本地文件系统-我总是最终得到项目的最新源代码。

有什么正确的方法只获取存储库的某个历史提交作为源,并省略以后的所有更新?


3
git reset --hard aabb3434:撤销当前分支上的所有本地改动,并将HEAD指向提交aabb3434。git push origin branch --force:强制推送本地分支到远程仓库中的同名分支,以覆盖远程分支的提交历史。 - Kanan Farzali
在stackoverflow上最有用的问题往往最有可能因为重复而被关闭。 - undefined
4个回答

1264
git reset --hard <tag/branch/commit id>

注意:

  • git reset 不带 --hard 选项会重置提交历史,但不会重置文件。使用 --hard 选项会同时重置工作树中的文件。(原作者

  • 如果你想提交此状态,以使远程仓库也指向回滚的提交,请执行:git push <reponame> -f。(原作者


4
在执行了 "git reset --hard <commit-id>"(回退到前2个版本),在执行 "git push -f origin master" 时,我收到了 "remote: error: denying non-fast-forward refs/heads/master (you should pull first)" 的提示。这是我的代码库,我想要重新拿回控制权 :) - peterk
18
请在您的git push命令的末尾尝试使用“--force”。 - Arcolye
6
请确保您同时指定了分支名称。 - eipark
2
在服务器端,存储库有一个配置选项,用于允许非快进式推送使用--force。请参考man git-config并检查存储库中的.git/config文件,以查看denyNonFastForwards = true。 - kauppi
4
第二个选项对我没有起作用:我不得不执行 git push -f <remoterepo> master 来恢复远程仓库。但是,请注意,使用 -f 开关后,恢复提交后的提交也会在远程仓库上丢失!(这正是我想要的,但其他人可能希望保留历史记录)。 - Kounavi
显示剩余9条评论

426

更新:

由于跟踪分支的创建和推送方式发生了变化,我不再建议重命名分支。现在我建议如下操作:

复制当前状态的分支:

git branch crazyexperiment

(执行git branch <name>命令会让你仍然停留在当前分支。)

使用git reset将当前分支重置为所需的提交:

git reset --hard c2e7af2b51

(将c2e7af2b51替换为您想要回退的提交。)

当您决定您的疯狂实验分支不包含任何有用的内容时,您可以使用以下命令删除它:

git branch -D crazyexperiment

当你开始使用修改历史的git命令(reset,rebase)时,创建备份分支以备不时之需是很好的习惯。随着经验的增加,你可能会发现这并非必要。如果你修改了历史记录,但没有创建备份分支,可以尝试使用git reflog。即使没有分支或标签指向它们,Git也会保存提交一段时间。
git branch -m crazyexperiment

检查您的好提交:

git checkout c2e7af2b51

在这里创建你的新主分支:
git checkout -b master

现在,如果您想稍后查看它,仍然可以保留您的疯狂实验,但是您的主分支已回到您最后一个已知的好状态,准备添加。如果您真的想放弃您的实验,可以使用:

git branch -D crazyexperiment

32
谢谢 - 这可能不是发帖者要求的,但对我来说减少了很多焦虑感。 - Matt Parker
9
处理远程代码仓库(如Github)时,由于非快进问题,您可能需要执行“git push -f origin master”命令,以使主分支看起来与指定的提交相同。但是,这种方法比重置更加清晰整洁。 - jcalvert
1
git reset --hard并不是特别危险的操作。几乎所有可用的git教程都将其介绍为撤销自己树中更改的正确方法,至少在中级功能中如此。如果你不小心进入了未知状态/HEAD,总有git reflog可以告诉你HEAD的历史记录,无论分支如何。从中选择一个适当的commitid,然后从它创建分支或使用git reset --hard。 - kauppi
3
你是不是会在将更改推回远程仓库时出现问题呢? - HaveAGuess
2
哎呀,应该是 git branch --set-upstream master <remote>/<branch>git branch --set-upstream crazyexperiment <remote>/<branch> - auspicious99
显示剩余5条评论

14

如果您倾向使用git gui,您也可以使用gitk。

右键单击要返回的提交,选择“将主分支重置到此处”。然后在下一个菜单中选择hard模式。


1
当服务器(stash)禁止强制推送时,无法工作。无法重置回去。 - maxweber
git硬重置 "在此输入提交ID":它将回滚到该阶段。 - Lakshay Sharma

1
当你说“GUI工具”时,我假设你正在使用Git For Windows。
重要的是,如果你还没有这样做,我强烈建议创建一个新分支来完成这个任务。这样你的主分支就可以保持不变,而你可以测试你的更改。
使用GUI工具,你需要像在视图右侧的历史记录中一样“回滚此提交”。然后你会注意到所有不想要的文件都被作为要提交的更改显示在左侧。 现在你需要右键单击所有未提交的文件上面的灰色标题,然后选择“忽略更改”。这将使你的文件恢复到此版本中的原始状态。

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