如何使用Git根据提交ID回退到特定的提交?

549

使用 git log 命令,可以获得我所做的所有提交记录列表。

commit f5c5cac0033439c17ebf905d4391dc0705dbd5f1
Author: prosseek 
Date:   Fri Sep 3 14:36:59 2010 -0500

    Added and modified the files.

commit c14809fafb08b9e96ff2879999ba8c807d10fb07
Author: prosseek 
Date:   Tue Aug 31 08:59:32 2010 -0500

    Just simple test for core.editor.

... etc ...
  • 如何将代码库还原到特定的提交版本?例如,如果我想回到 commit c14809fafb08b9e96ff2879999ba8c807d10fb07,我该怎么做?

  • 除了这种方法之外,使用Git有更好的方式可以回到特定的提交版本吗?例如,我能否对每个提交版本打上标签以便于通过标签获取它?


1
尽管这个问题实际上比现在标记为重复的那个问题更早,但那个问题有一个更好的答案。http://meta.stackexchange.com/questions/147643/should-i-vote-to-close-a-duplicate-question-even-though-its-much-newer-and-ha/147651#147651 - GS - Apologise to Monica
6
这是一个非常完美的例子,说明了Git有多么烂(引自bwawok的答案):“...然后如果你想把这个提交推送给已经有新历史记录的其他人,它会失败”。如果你不能将其检入远程代码库,那还有什么用处呢?我对Git让简单操作变得如此困难感到非常惊讶。 - jww
3
我已经阅读了一个小时,想知道如何回到之前的提交,但我仍然不知道答案。你说得对,Git让事情变得比应该复杂。 - robben
@robben 重置后强制推送。 - ReinstateMonica3167040
4个回答

851

您是想将存储库回滚到那个状态,还是只是希望本地存储库看起来像那样?

如果您使用reset --hard,它将使您的本地代码和本地历史记录在该提交时就像它一样。但是,如果您想将此推送给具有新历史记录的其他人,则会失败:

git reset --hard c14809fa

如果你运行reset --soft命令,它会将你的HEAD指针移动到之前的位置,但是保留本地文件等内容不变:

git reset --soft c14809fa

那么你想要用这个重置功能做什么呢?

编辑 -

你可以给你的仓库添加“标签”.. 然后回到一个标签。但标签实际上只是快捷方式到sha1。

你可以将其标记为TAG1.. 然后git reset --soft c14809fa, git reset --soft TAG1git reset --soft c14809fafb08b9e96ff2879999ba8c807d10fb07都会做同样的事情。


4
我需要回滚到那个状态。但是知道我可能有“看起来像那样”的选项很好。谢谢你告诉我。顺便问一下,默认的选项是什么?是“硬”还是“软”? - prosseek
2
@prosseek 默认设置为混合模式。 --mixed 重置索引但不重置工作树(即,更改的文件被保留但未标记为提交),并报告未更新的内容。这是默认操作。 请参阅http://www.kernel.org/pub/software/scm/git/docs/git-reset.html。 - bwawok
19
以下是彼得的回答,比这个更有意义。 - Dr. Dan
5
澄清一下:"git reset --soft"并未保留历史记录,因为它会移除重置之后的所有提交记录,并将这些更新提交的文件标记为“Changes to be committed”。我猜这取决于你如何定义“history”。句子“but leave your history etc. the same.”让我误解了该命令不影响任何提交记录,但实际上它会影响。请参考Peter A的回答,了解如何保留撤销提交之后提交的记录。 - jomni
1
这个方法可行,但是我需要用"git push --force"代替平常的"git push"。 - HoldOffHunger
显示剩余7条评论

240

我认为,bwawok的回答在某些方面是错误的:

 

如果你执行

git reset --soft c14809fa

它将使您的本地文件更改为与那时相同,但保留您的历史记录等内容不变。 根据 git-reset手册,“git reset --soft”不会触及索引文件和工作树(但重置头到<commit>,就像所有模式一样)。这将使所有更改的文件处于“Changes to be committed”的状态,就像git status所描述的那样。因此,它将从该分支中“删除”较新的提交。这意味着,在查看旧代码后,您无法轻松地返回到该分支中的最新提交。因此,它与bwawok所描述的相反:本地文件未更改(它们看起来与“git reset --soft”之前完全相同),但是历史记录已修改(在指定提交后截断了分支)。

bwawok答案的命令可能是:

git checkout <commit>
您可以使用此功能查看旧版本:如何查看昨天的代码?
(我知道,我应该将此放在对此答案的评论中,但stackoverflow不允许我这样做!我的声望太低了。)

4
但是 git checkout 是只读的,因此您无法提交旧版本。 - robben
2
@Peter A:在执行了“git reset --soft”和“git checkout”之后,我没有看到我正在工作的文件发生变化。这可能是因为我不在主分支上吗? - user749127
2
另外,您可以执行“git checkout <YOUR_BRANCH>”来返回原始状态,以查看不同的提交。 - Ankit Bhatnagar

52

git reset c14809fafb08b9e96ff2879999ba8c807d10fb07是你要找的命令...


2
不需要输入完整的sha,只需输入一小部分即可。 - bwawok
57
选择并中键粘贴比输入缩写的SHA1还要快! - Cascabel
10
执行git push origin mybranch会导致远程仓库被还原吗? - WestCoastProjects
2
@javadba 如果存在与先前祖先的偏差,则不能不使用“--force”。 - user2864740
git硬重置 "在此输入提交ID":它将回滚到该阶段。 - Lakshay Sharma

26

如果你想强制执行,可以这样做:

git reset --hard c14809fafb08b9e96ff2879999ba8c807d10fb07

将您发送回到Git克隆在提交时的状态


2
在什么情况下需要使用强制操作? - jacoballenwood
2
“在签入时”是什么意思?含糊不清。如果我执行“git reset --hard X”,那么存储库状态是与提交X之前相同还是之后相同... - nyholku
2
git reset --hard X。这将回滚存储库状态,就像提交X之前一样。它将使您的本地代码和本地历史记录与该提交时完全相同。但是,如果您想将其推送到具有不同历史记录的本地主机或远程主机,则会失败。因此,它将成为您存储库的只读版本。 - Malatesh Patil
如果你从未检出过的远程分支进行了检出,并且在执行 git pull 时强制执行合并,而你只想要该分支上 HEAD 处的代码,则需要强制执行此操作。 - cwa

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