回滚到公共回购中的旧Git提交


802

我该如何回滚到git中的特定提交?

有人可以给我的最佳答案是使用git revertX次,直到达到所需的提交。

假设我想恢复为20提交的旧提交,我必须运行20次。

有没有更简单的方法可以做到这一点?

我不能使用reset,因为此存储库是公共的。


1
git revert <commit>不起作用?
miku 2010年

8
如我的问题所述,如果我想恢复到20提交之前的功能,这的确对我没有帮助。
大卫2010年

7
这个问题已经相当不错这里回答stackoverflow.com/questions/4114095/...
user7610

4
不清楚“回滚”是什么意思。这是否意味着您要暂时将工作副本切换到特定版本?还是要永久地将存储库的历史还原到某个修订版本?

1
您应该接受一个答案,并可能会对您喜欢的任何其他答案投反对票。
Nabil Kadimi 2014年

Answers:


1193

尝试这个:

git checkout [revision] .

[revision]提交哈希在哪里(例如:)12345678901234567890123456789012345678ab

最后不要忘了.,非常重要。这会将更改应用于整个树。您应该在git项目根目录中执行此命令。如果您在任何子目录中,那么此命令仅更改当前目录中的文件。然后提交,你应该很好。

您可以通过以下方式撤消该操作

git reset --hard 

它将删除工作目录和登台区域中的所有修改。


7
@AlexReisner您当前所在目录的末尾那段时间,不一定是整个git项目,对吗?如果您想将更改应用到整个项目,如果您当前不在git项目的根目录下,您是否会像在'git add:/'中那样使用':/'?
MSpreij

10
注意:如果从那以后您已经向项目中添加了新文件,则不会删除它们。因此,当您进行构建时(取决于您的平台),仍然可能会出错。删除新文件,一切顺利。
TheWestIsThe ...

6
@MSpreij您应该在git项目根目录中执行此命令。如果您在任何子目录中,那么此命令仅更改当前目录中的文件。
volatilevar

3
可以在另一个目录中克隆项目并使用git checkout [revision]很好。返回特定的修订版本,然后将其与其他目录中的相同项目进行比较。节省大量时间。
多纳托

4
该死的,我忘了“。” 我对存储库有什么损害?
猫头鹰

196

要回滚到特定提交:

git reset --hard commit_sha

要回滚10次提交,请执行以下操作:

git reset --hard HEAD~10

如果您不想重写历史记录,可以使用以下帖子中的“ git revert”

如何将Git存储库还原到先前的提交?


4
这种方法与“ git checkout [修订版]”之间的唯一区别。后者保留修订。
deeshank 2014年

53
这个答案是错误的,因为OP特别指出“我无法使用重置,因为此回购是公开的”
Yarin 2014年

4
如果repo是公共的,我认为不使用强制推送(git push -f)就无法回滚公共存储库上的提交,因为这会影响回滚之前已经进行了更改的人员。因此,重置也可以在公共仓库的本地沙箱中使用。
娜迦·基兰

4
很好,这避免了头分离!正是我想要的。
网络僧侣

1
就我而言,这是可行的,然后在您测试了回归等之后,使用“ git pull”快退到头。
彼得·奎林

86

好吧,我想问题是,“回滚”是什么意思?如果不能,reset因为它是公开的,并且您希望保持提交历史记录完整,那是否意味着您只是希望工作副本能够反映特定的提交?使用git checkout和提交哈希。

编辑:正如评论中指出的那样,git checkout如果不指定分支就使用将使您处于“无分支”状态。使用git checkout <commit> -b <branchname>结帐成一个分支,或者git checkout <commit> .结账进当前的分支。


这是否会使您进入奇怪的“当前不在任何分支”状态?您如何提交更改以完成回滚?
Alex Reisner,2010年

好吧,我只是建议使用git checkout-他可以自由签到他希望的任何分支(当前分支或新分支)。我将更新我的答案,这样就不会造成歧义。

2
我试过了,但是我不认为这是正确的方法,因为它会留下停滞的文件。这不会删除不在最后一次提交中的文件。
大卫2010年

3
如果您在工作目录中并且仍在主目录中,则需要git reset删除那些您不想这样做的文件。尝试将其放入一个单独的分支中:git checkout <commit> -b <branchname>该分支中将没有停滞的文件。

2
使用的问题checkout是它不会删除上一次提交中添加的文件。

42

原始海报指出:

有人可以给我的最佳答案是使用git revertX次,直到达到所需的提交。

假设我想恢复为20提交的旧提交,我必须运行20次。

有没有更简单的方法可以做到这一点?

我无法使用重置,因为此回购是公开的。

不必使用git revertX次。git revert可以接受提交范围作为参数,因此您只需使用一次即可还原一定范围的提交。例如,如果您想还原最近的20次提交:

git revert --no-edit HEAD~20..

提交范围HEAD~20..是的缩写HEAD~20..HEAD,表示“从HEAD提交的 20 父级开始,然后将所有提交还原到HEAD”。

假设所有这些都不是合并提交,它将还原最后20次提交。如果存在合并提交,那么您将无法在一个命令中全部还原它们,需要使用以下命令分别还原它们:

git revert -m 1 <merge-commit>

还要注意,我已经git revert使用git版本1.9.0 使用范围进行了测试。如果您使用的是git的旧版本,则使用带有git revert或不能的范围。

在这种情况下,git revert优先于git checkout

请注意,与使用的答案git checkout不同,git revert 实际上会删除您要还原的任何提交中添加的所有文件,这使之成为还原一系列修订版本的正确方法。

文献资料


注意:这使用还原的更改创建一个新的提交。非常适合OP的问题。但是请确保这就是您想要的。(上面链接到的git-revert doc中的示例非常好。)如果您想调查以前的提交(即,在选择要还原的提交之前),请使用其他答案中提到的checkout选项,同时要记住其他人的评论关于删除的文件。
SherylHohman

@SherylHohman恢复到先前的提交不会创建新的提交。我无法想象你在这里的意思。

27

第1步:获取提交列表:

git log

您将在此示例中获得列表:

[Comp:Folder User$ git log
commit 54b11d42e12dc6e9f070a8b5095a4492216d5320
Author: author <author@gmail.com>
Date:   Fri Jul 8 23:42:22 2016 +0300

This is last commit message

commit fd6cb176297acca4dbc69d15d6b7f78a2463482f
Author: author <author@gmail.com>
Date:   Fri Jun 24 20:20:24 2016 +0300

This is previous commit message

commit ab0de062136da650ffc27cfb57febac8efb84b8d
Author: author <author@gmail.com>
Date:   Thu Jun 23 00:41:55 2016 +0300

This is previous previous commit message
...

步骤2:复制所需的提交哈希并将其粘贴以进行结帐:

git checkout fd6cb176297acca4dbc69d15d6b7f78a2463482f

就这样。


11
git read-tree -um @ $commit_to_revert_to

会做的。这是“ git checkout”,但不更新HEAD。

您可以达到相同的效果

git checkout $commit_to_revert_to
git reset --soft @{1}

如果您更喜欢将便捷命令串在一起。

这些使您的工作树和索引处于所需状态,您只需git commit完成操作即可。


这是唯一一种有魅力的简单方法!我从头检查了一下,运行了此命令,它成功删除了我们引入的添加文件并还原了所有更改。优秀的。
kamranicus

6

要HEAD分离模式吗?

如果您希望将X时间回退到带有DETACHED HEAD的某个提交(这意味着您什么都不会弄乱),那么请务必使用以下命令:

(用您希望返回的提交数替换X)

git checkout HEAD~X

IE浏览器回退一次提交:

git checkout HEAD~1

1
我会删除...难以置信的部分...似乎是个人的,也有人在上面的评论中以及@ken的回答中提到了它。
meJustAndrew

@meJustAndrew在SO上有这么多答案,这只会使人感到困惑,这很烦人。
莫里森

一个简单直接的答案。
Ammad

2

假设您在一天左右的时间内从事一个项目。您会注意到一项功能仍在给您错误。但是您不知道所做的更改导致了错误。因此,您必须钓鱼以前的工作提交。要还原为特定的提交,请执行以下操作:

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 .

好的,这样提交就可以为您工作。没有更多的错误。您指出了问题所在。现在您可以返回到最新提交:

git checkout 792d9294f652d753514dc2033a04d742decb82a5 .

并在导致错误之前检出特定文件(在我的情况下,我使用示例Gemfile.lock):

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 -- /projects/myproject/Gemfile.lock

这是处理在提交中创建的错误而又不意识到错误的一种方法。


2

您可以在GitHub / BitBucket / Gitlab的commits部分中找到与每个提交相关的提交ID。非常简单,假设您的提交ID为5889575,那么如果您想返回到代码的这一部分,则只需键入

git checkout 5889575 .

这将带您到达代码中的那个时间点。


1

我不确定更改了什么,但是如果没有option,我将无法检出特定的提交--detach。对我有用的完整命令是: git checkout --detach [commit hash]

要从分离状态恢复,我必须检出本地分支: git checkout master


mastergit reset --hardgit checkout -- .

0

这是一个例子

    cd /yourprojects/project-acme 


    git checkout efc11170c78 .
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.