问题 如何将Git存储库还原为先前的提交
如何从当前状态恢复为在某个提交时创建的快照?
如果我做 git log
,然后我得到以下输出:
$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <me@me.com>
Date: Thu Nov 4 18:59:41 2010 -0400
blah blah blah...
commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <me@me.com>
Date: Thu Nov 4 05:13:39 2010 -0400
more blah blah blah...
commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <me@me.com>
Date: Thu Nov 4 00:55:06 2010 -0400
And yet more blah blah...
commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <me@me.com>
Date: Wed Nov 3 23:56:08 2010 -0400
Yep, more blah blah.
如何从11月3日恢复到提交,即提交 0d1d7fc
?
12848
2017-11-06 16:58
起源
答案:
这很大程度上取决于“恢复”的含义。
暂时切换到其他提交
如果你想暂时回到它,傻瓜,然后回到你所在的位置,你所要做的就是检查所需的提交:
# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32
或者,如果你想在那里做出提交,那么在你做的时候继续做一个新的分支:
git checkout -b old-state 0d1d7fc32
要回到原来的位置,只需查看您再次访问的分支。 (如果你做了更改,就像转换分支时一样,你必须在适当的时候处理它们。你可以重置它们扔掉它们;你可以藏匿,结账,存放pop以带走它们;你可以提交如果你想要那里的分支,他们到那里的一个分支。)
硬删除未发布的提交
另一方面,如果你想真正摆脱自那时以来所做的一切,那么有两种可能性。一,如果您还没有发布任何这些提交,只需重置:
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
如果你陷入困境,你已经抛弃了你的本地变化,但你至少可以通过重新设置来回到原来的位置。
使用新提交撤消已发布的提交
另一方面,如果您已发布作品,则可能不希望重置分支,因为这有效地重写了历史记录。在这种情况下,您确实可以还原提交。使用Git,revert有一个非常具体的含义:使用反向补丁创建一个提交以取消它。这样您就不会重写任何历史记录。
# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053
# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD
#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053
# Reverting a merge commit
git revert -m 1 <merge_commit_sha>
# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .
# Then commit. Be sure and write a good message describing what you just did
git commit
该 git-revert
手册页 实际上在其描述中涵盖了很多内容。另一个有用的链接是 这个git-scm.com节讨论了git-revert。
如果您决定不想还原,则可以还原还原(如此处所述)或重置为还原之前(请参阅上一节)。
在这种情况下,您可能会发现此答案很有用:
如何将HEAD移回以前的位置? (独立头)
7841
2017-11-06 17:04
将工作副本还原为最近的提交
要恢复到先前的提交,请忽略任何更改:
git reset --hard HEAD
其中HEAD是当前分支中的最后一次提交
将工作副本还原为较旧的提交
要恢复到比最近提交更早的提交:
# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced
# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}
git commit -m "Revert to 56e05fced"
# Updates working copy to reflect the new commit
git reset --hard
积分转到类似的Stack Overflow问题, 在Git中恢复由SHA哈希提交?。
1262
2017-08-21 06:19
这里有很多复杂而危险的答案,但实际上很简单:
git revert --no-commit 0766c053..HEAD
git commit
这将从HEAD返回到提交哈希的所有内容,这意味着它将在工作树中重新创建该提交状态 仿佛 从那以后的每一次承诺都被退了回来。然后,您可以提交当前树,它将创建一个全新的提交,基本上等同于您“恢复”的提交。
(该 --no-commit
flag允许git立即恢复所有提交 - 否则,系统会提示您为该范围内的每个提交发送一条消息,并使用不必要的新提交乱丢您的历史记录。)
这是一个 回滚到以前状态的安全简便方法。没有历史被破坏,因此它可以用于已经公开的提交。
1221
2018-02-12 04:18
我和其他人的最佳选择是Git重置选项:
git reset --hard <commidId> && git clean -f
这对我来说是最好的选择!它简单,快速,有效!
注意 : 如评论中所述,如果您与拥有旧提交副本的其他人共享您的分支,则不会这样做
同样来自评论,如果你想要一个较少'ballzy'的方法,你可以使用
git clean -i
153
2017-10-22 11:53
如果要“取消提交”,擦除最后一次提交消息,并将修改后的文件放回到分段中,则可以使用以下命令:
git reset --soft HEAD~1
--soft
表示未提交的文件应保留为与之对应的工作文件 --hard
哪会丢弃它们。
HEAD~1
是最后一次提交。如果你想回滚3个提交,你可以使用 HEAD~3
。如果要回滚到特定的修订版号,也可以使用其SHA哈希来执行此操作。
在您提交了错误的内容并且想要撤消上次提交的情况下,这是一个非常有用的命令。
资源: http://nakkaya.com/2009/09/24/git-delete-last-commit/
103
2018-03-04 17:25
在回答之前,让我们添加一些背景,解释一下这个 HEAD
是。
First of all what is HEAD?
HEAD
只是对当前分支上当前提交(最新)的引用。只能有一个 HEAD
在任何给定时间(不包括 git worktree
)。
的内容 HEAD
存储在里面 .git/HEAD
,它包含当前提交的40字节SHA-1。
detached HEAD
如果你不是最近的提交 - 意思是 HEAD
指向历史上的先前提交它被称为 detached HEAD
。

在命令行上它看起来像这样 - SHA-1而不是分支名称 HEAD
没有指向当前分支的尖端:

关于如何从分离的HEAD中恢复的几个选项:
git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back
这将检查指向所需提交的新分支。此命令将签出到给定的提交。
此时,您可以创建一个分支,并从这一点开始工作:
# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>
# Create a new branch forked to the given commit
git checkout -b <branch name>
你可以随时使用 reflog
同样。 git reflog
将显示更新的任何更改 HEAD
并检查所需的reflog条目将设置 HEAD
回到这个提交。
每次修改HEAD时,都会有一个新条目 reflog
git reflog
git checkout HEAD@{...}
这将使您回到所需的提交

“移动”你的头回到所需的提交。
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
- 注意: (自Git 2.7起)你也可以使用
git rebase --no-autostash
同样。
此架构说明了哪个命令执行的操作。正如你在那里看到的那样 reset && checkout
修改 HEAD
。

102
2018-02-05 21:56
我已经尝试了很多方法来恢复Git中的本地更改,如果你只想恢复到最新的提交状态,这似乎是最好的。
git add . && git checkout master -f
简短的介绍:
- 它不会创建任何提交
git revert
确实。
- 它不会像你那样分离你的头部
git checkout <commithashcode>
确实。
- 它将覆盖所有本地更改并删除自分支中最后一次提交以来所有添加的文件。
- 它仅适用于分支名称,因此您只能以这种方式恢复分支中的最新提交。
我找到了一种更方便,更简单的方法来实现上述结果:
git add . && git reset --hard HEAD
其中HEAD指向您当前分支的最新提交。
它与boulder_ruby建议的代码相同,但我已添加 git add .
之前 git reset --hard HEAD
擦除自上次提交以来创建的所有新文件,因为这是大多数人在恢复到最新提交时所期望的。
96
2017-07-29 11:01
您可以通过以下两个命令执行此操作:
git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f
它将删除您之前的Git提交。
如果您想保留更改,还可以使用:
git reset --soft [previous Commit SHA id here]
然后它将保存您的更改。
76
2017-12-12 06:52
假设您在名为的文本文件中有以下提交 ~/commits-to-revert.txt
(我用了 git log --pretty=oneline
得到他们)
fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca
创建一个 巴什 用于还原每个脚本的shell脚本:
#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
git revert $i --no-commit
done
这会将所有内容还原回以前的状态,包括文件和目录创建以及删除,将其提交到您的分支并保留历史记录,但是您将其还原为相同的文件结构。为什么Git没有 git revert --to <hash>
超出我的范围。
51
2017-10-13 21:51
Jefromi解决方案的额外替代品
Jefromi的解决方案 绝对是最好的,你一定要使用它们。但是,为了完整起见,我还想展示这些其他替代解决方案,这些解决方案也可以用来恢复提交(从某种意义上说,你) 创建一个新的提交,撤消先前提交中的更改,就像什么 git revert
一样)。
要明确这些替代方案 不是恢复提交的最佳方式, Jefromi的解决方案是,但我只是想指出,你也可以使用这些其他方法来实现同样的目的 git revert
。
备选方案1:硬重置和软重置
这是Charles Bailey解决方案的略微修改版本 在Git中恢复由SHA哈希提交?:
# Reset the index to the desired commit
git reset --hard <commit>
# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}
# Commit the changes
git commit -m "Revert to <commit>"
这基本上可以通过使用软重置将使先前提交的状态保留在索引/暂存区域中的事实来实现,然后您可以提交该区域。
备选方案2:删除当前树并替换为新树
这个解决方案来自svick的解决方案 签出旧提交并使其成为新提交:
git rm -r .
git checkout <commit> .
git commit
与替代#1类似,这再现了状态 <commit>
在当前的工作副本中。有必要这样做 git rm
首先因为 git checkout
不会删除自那以后添加的文件 <commit>
。
48
2018-02-29 08:40
这里有一个 更简单 返回到先前提交的方式(并使其处于未通信状态,无论你喜欢什么,都可以使用它):
git reset HEAD~1
所以,不需要提交ID等等:)
45
2018-05-10 17:21