如何将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

这很大程度上取决于你“回复”的含义。

暂时切换到另一个提交

如果你想暂时回到它,愚弄周围,然后回到你所在的位置,你所要做的就是检查所需的提交:

 # This will detach your HEAD, that is, leave you with no branch checked out: git checkout 0d1d7fc32 

或者,如果你想在那里提交提交,请继续在你创build分支的同时创build一个新的分支:

 git checkout -b old-state 0d1d7fc32 

要回到你所在的位置,只需查看你所在的分支。 (如果你已经做了改变,就像往常一样,在切换分支的时候,你必须适当地处理它们,你可以重新设置它们,你可以隐藏,结帐,隐藏popup来把它们带走;你可以提交他们到那里的一个分支,如果你想在那里的分支。)

硬删除未公布的提交

另一方面,如果你想真正摆脱自那时以来所做的一切,那么有两种可能性。 一,如果你还没有发表任何这些提交,只需重置:

 # 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. 

如果你搞砸了,你已经抛弃了你的本地变化,但你至less可以通过重新设置回到原来的位置。

撤销已发布的提交新提交

另一方面,如果你已经发表了这个作品,你可能不想重置这个分支,因为这实际上是在重写历史。 在这种情况下,你确实可以恢复提交。 使用Git,恢复有一个非常具体的含义:用反向补丁创build一个提交来取消它。 这样你就不会重写任何历史。

 # 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 。

如果您决定完全不想还原,则可以恢复(如此处所述)还原或者还原之前(请参阅上一节)。

你也可以在这种情况下find这个答案有帮助:
如何将HEAD移回到之前的位置? (分离头)

将工作副本还原到最近的提交

要恢复到以前的提交,忽略任何更改:

 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 

积分去一个类似的堆栈溢出问题, 恢复到在SHA提交的SHA哈希?

这里有许多复杂而危险的答案,但实际上很简单:

 git revert --no-commit 0766c053..HEAD git commit 

这将从HEAD恢复到提交散列,这意味着它将在工作树中重新创build提交状态, 就好像每一次提交都已经被回退​​一样。 然后你可以提交当前的树,它会创build一个全新的提交,基本上等于你“恢复”的提交。

--no-commit标志让git立即恢复所有提交 – 否则系统会提示你input一个消息给范围内的每个提交,用不必要的新提交丢掉你的历史logging。)

这是回滚到以前状态安全和简单的方法 。 没有历史被破坏,所以它可以用于已经公开的提交。

对我和其他人来说最好的select是Git重置选项:

 git reset --hard <commidId> && git clean -f 

这对我来说是最好的select! 它简单,快速,有效!


注意: 正如评论中提到的,如果你与其他拥有旧提交副本的人分享你的分支,不要这样做

从评论中也可以看出,如果你想要一个更less的“低调”的方法,你可以使用

git clean -i

我已经尝试了很多方法来恢复Git中的本地更改,而且如果您只想恢复到最新的提交状态,似乎这种方法效果最好。

 git add . && git checkout master -f 

简短的介绍:

  • 它不会像git revert那样创build任何提交。
  • 它不会像git checkout <commithashcode>那样分离你的HEAD。
  • 它将覆盖所有本地更改并删除自分支上次提交以来所有添加的文件。
  • 它只适用于分支机构的名称,所以你可以这样恢复到分支机构的最新提交。

我发现了一个更方便简单的方法来实现上述结果:

 git add . && git reset --hard HEAD 

HEAD指向您当前分支处的最新提交。

它与boulder_rubybuild议的是相同的代码,但是我添加了git add .git reset --hard HEAD之前 – git reset --hard HEAD擦除自上次提交以来创build的所有新文件,因为这是大多数人所期望的,当恢复到最新的提交时,我相信。

如果你想“取消提交”,删除最后一个提交信息,并把修改过的文件放回到分段,你可以使用下面的命令:

 git reset --soft HEAD~1 
  • --soft表示未提交的文件应保留为与--soft相反的工作文件, --hard将丢弃它们。
  • HEAD~1是最后一次提交。 如果你想回滚3提交,你可以使用HEAD~3 。 如果你想回滚到一个特定的版本号,你也可以使用它的SHA哈希来做到这一点。

这是一个非常有用的命令,在你犯了错误的事情,你想撤消最后一次提交的情况下。

资料来源: http : //nakkaya.com/2009/09/24/git-delete-last-commit/

您可以通过以下两个命令来完成此操作:

 git reset --hard [previous Commit SHA id here] git push origin [branch Name] -f 

它会删除以前的Git提交。

如果你想保留你的改变,你也可以使用:

 git reset --soft [previous Commit SHA id here] 

然后它将保存您的更改。

在回答之前,让我们添加一些背景,说明这是什么头。

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

 git checkout <commit_id> git checkout -b <new branch> <commit_id> git checkout HEAD~X // x is the number of commits t go back 

这将检出指向所需提交的新分支。
这个命令将签出一个给定的提交。
在这一点上,你可以创build一个分支,并从这一点开始工作。

 # 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> 

git reflog

您也可以随时使用reflog
git reflog将显示更新HEAD任何更改,并检出所需的reflog条目将把HEAD回此提交。

每当HEAD被修改时, reflog都会有一个新的条目

 git reflog git checkout HEAD@{...} 

这会让你回到你想要的提交

在这里输入图像描述


git reset HEAD --hard <commit_id>

“移动”你的头回到所需的提交。

 # 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修改头。

在这里输入图像描述

假设你在一个名为~/commits-to-revert.txt的文本文件中有下面的提交(我用git log --pretty=oneline来获取它们)

 fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219 0c27ecfdab3cbb08a448659aa61764ad80533a1b f85007f35a23a7f29fa14b3b47c8b2ef3803d542 e9ec660ba9c06317888f901e3a5ad833d4963283 6a80768d44ccc2107ce410c4e28c7147b382cd8f 9cf6c21f5adfac3732c76c1194bbe6a330fb83e3 fff2336bf8690fbfb2b4890a96549dc58bf548a5 1f7082f3f52880cb49bc37c40531fc478823b4f5 e9b317d36a9d1db88bd34831a32de327244df36a f6ea0e7208cf22fba17952fb162a01afb26de806 137a681351037a2204f088a8d8f0db6e1f9179ca 

创build一个Bash shell脚本来恢复它们中的每一个:

 #!/bin/bash cd /path/to/working/copy for i in `cat ~/commits-to-revert.txt` do git revert $i --no-commit done 

这会将一切恢复到之前的状态,包括文件和目录创build以及删除,将其提交到您的分支,并保留历史logging,但是您已将其恢复为相同的文件结构。 为什么Git没有git revert --to <hash>超出了我的意思。

Jefromi的解决scheme的额外替代品

Jefromi的解决scheme绝对是最好的,你一定要使用它们。 然而,为了完整起见,我还想要展示这些其他可以用来恢复提交的替代解决scheme(就像你创build一个新的提交,撤销之前提交的更改 ,就像git revert一样) 。

要清楚的是,这些替代方法并不是恢复提交的最佳方法 , Jeutti的解决scheme是 ,但我只想指出,您也可以使用这些其他方法来实现与git revert相同的function。

scheme1:硬复位和软复位

这是Charles Bailey解决scheme的一个非常略微修改的版本,可以恢复到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>" 

这基本上是通过使用软重置会使索引/登台区域中的前一个提交的状态保持不变,然后您可以提交的。

scheme2:删除当前树并replace为新树

这个解决scheme来自svick的解决scheme来签出旧的提交,并使其成为一个新的提交 :

 git rm -r . git checkout <commit> . git commit 

与备选#1类似,这会再现当前工作副本中的<commit>状态。 有必要首先执行git rm因为git checkout不会删除自<commit>添加的文件。

这里有一个更简单的方法可以回到之前的提交(并且处于一个无限制的状态,无论你喜欢做什么):

 git reset HEAD~1 

所以,不需要提交id等:)

假设你在谈论master和那个分支(也就是说,这可能是你关心的任何工作分支):

 # Revert local master branch to November 3rd commit ID git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50 # Revert remote master branch to November 3rd commit ID git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master 

我在博客中find答案删除远程Git仓库到特定的提交

有一个命令(不是核心Git的一部分,但它在git-extras包中)专门用于还原和暂存旧提交:

 git back 

根据手册页 ,也可以这样使用:

 # Remove the latest three commits git back 3 

在所有更改之后,当您推送所有这些命令时,您可能必须使用:

 git push -f ... 

而不只是git push

select你需要的提交,并检查它

 git show HEAD git show HEAD~1 git show HEAD~2 

直到你得到所需的提交。 为了使HEAD指向这一点,做

 git reset --hard HEAD~1 

或者git reset --hard HEAD~2或其他。

好吧,回到以前在git中的提交是很容易的…

恢复而不保留更改:

 git reset --hard <commit> 

保持更改恢复:

 git reset --soft <commit> 

解释一下:使用git reset,你可以重置到一个特定的状态,通常使用它提交散列,就像你上面看到的那样。

但是正如你看到的区别是使用了两个标志--soft--hard ,默认的git reset使用--soft标志git reset ,但是总是使用标志是一个很好的做法,我解释了每个标志:


– 柔软的

如上所述的默认标志,不需要提供它,不会改变工作树,但添加所有的变更文件准备好提交,所以你回到提交状态,其中更改文件得到unstaged。


– 硬

小心这个标志,它会重置工作树,所有跟踪文件的变化都将消失!


我也创build了下面的图像可能发生在现实生活中使用git:

git重置为提交

为了保持从前一个提交到HEAD的更改并移到前一个提交,请执行以下操作:

 git reset <SHA> 

如果以前提交到HEAD时不需要更改,只需放弃所有更改,请执行以下操作:

 git reset --hard <SHA> 

为了从一些意外的变化中完全清除编码器的目录,我们使用了:

 git add -A . git reset --hard HEAD 

只是git reset --hard HEAD将摆脱修改,但它不会摆脱“新”的文件。 在他们的情况下,他们不小心把一个重要的文件夹随机地拖到了一个地方,所有这些文件都被Git视为新的,所以reset --hard并没有修复它。 通过运行git add -A . 事先用git明确地跟踪它们,被重置清除。

我相信有些人可能会问这个问题,想知道如何回滚他们在主人身上所做的改变 – 也就是扔掉所有东西,然后回到原点/主点,在这种情况下,请执行以下操作:

 git reset --hard origin/master 

https://superuser.com/questions/273172/how-to-reset-master-to-origin-master

这是直接重置为最近提交的一种方法

 git stash git stash clear 

它直接清除自上次提交以来所做的所有更改。

PS:有一点问题; 它也会删除您最近储存的所有储存变更。 我猜在大多数情况下应该不重要。

恢复到最近的提交并忽略所有本地更改

 git reset --hard HEAD 

Revert是回滚提交的命令。

 git revert <commit1> <commit2> 

样品:

git revert 2h3h23233

它可以从下面的HEAD范围。 这里1表示“恢复上次提交”。

git revert HEAD~1..HEAD

然后做git push

如果情况紧急 ,你只是想快速而肮脏地提出问题,假设你的项目在目录“我的项目”下:

  1. 复制整个目录并将其称为别的东西,比如“我的项目 – 复制”

  2. 做:

     git reset --hard [first-4-letters&numbers-of-commit's-SHA] 

然后,您的系统上有两个版本…您可以检查或复制或修改前一个提交中感兴趣的文件或其他文件。 如果你已经决定新的工作没有进展,你可以完全放弃“我的项目 – 复制”下的文件。

如果你想继续进行项目的状态而不实际丢弃工作,那么显而易见的事情就是重新命名你的目录:删除包含检索到的提交的项目(或者给它一个临时的名字)并且重命名你的“我的项目 – 复制“目录回到”我的项目“。 那么很可能会很快做另一个提交。

Git是一个出色的创造,但是你不能只是“随时挑选它”:那些试图解释它的人也经常假设其他VCS [版本控制系统]的先前知识,并钻研得太深,并犯下其他罪行,比如使用可互换的术语来“检查” – 以有时似乎混淆初学者的方式出现。

为了节省自己很多的压力,你必须要阅读一本关于Git的书 – 我推荐“使用Git进行版本控制” 。 而当我说“必须”的时候,如果你能相信我(或者说我的疤痕),那么现在就可以做到了。 Git的大部分复杂性来自分支,然后重新合并。 但是从你的问题来看, 人们应该用科学让你失望,这是没有道理的

特别是,如果这是一个绝望的情况,你是Git的新手!

PS:另外一个想法是:将(现在的)Git仓库(“repo”)保存在非工作文件的目录中是非常简单的。 这意味着你不必使用上面的快速和肮脏的解决scheme来复制整个Git仓库。 在这里查看Fryer使用–separate-git-dir的答案。 不过要注意的是:如果你有一个你不复制的“单独目录”版本库,而且你做了一个硬重置,重置提交之后的所有版本都将永远丢失,除非你有,定期备份您的存储库,最好到其他地方的云(如谷歌驱动器 )。

如果你想纠正一些错误在上次提交一个好的select将使用git commit –amend命令。 如果最后一个提交没有被任何引用指向,那么这个技巧就会起作用,因为它使用与上次提交相同的父级创build一个提交。 如果没有对最后一个提交的引用,它将被简单地丢弃,并且这个提交将是最后的提交。 这是纠正提交而不恢复提交的好方法。 然而它有它自己的局限性。

又一个最简单的解决scheme; 你必须改变分支来做到这一点,但之后你可以运行:

 git branch -f <<branchname>> 0d1d7fc32e5a947fbd92ee598033d85bfc445a50 

You can complete all these initial steps yourself and push back to git repo.

  1. Pull the latest version of your repository from Bitbucket using the git pull --all command.

  2. Run the git log command with -n 4 from your terminal. The number after the -n determines the number of commits in the log starting from the most recent commit in your local history.

    $ git log -n 4

  3. Reset the head of your repository's history using the git reset --hard HEAD~N where N is the number of commits you want to take the head back. In the following example the head would be set back one commit, to the last commit in the repository history:

  4. Push the change to git repo using git push --force to force push the change.

If you want git repository to a previous commit

 git pull --all git reset --hard HEAD~1 git push --force 

As your commits are pushed remotely, you need to remove them. Let me assume your branch is develop and it is pushed over origin.

You first need to remove develop from origin:

 git push origin :develop (note the colon) 

Then you need to get develop to the status you want, let me assume the commit hash is EFGHIJK:

 git reset --hard EFGHIJK 

Lastly, push develop again:

 git push origin develop 

I couldn't revert mine manually for some reason so here is how I ended up doing it.

  1. Checked out the branch I wanted to have, copied it.
  2. Checked out the latest branch.
  3. Copied the contents from the branch I wanted to the latest branch's directory overwriting the changes and committing that.
 git reflog 

Choose the number of the HEAD(s) of git reflog, where you want revert to and do (for this example I choose the 12):

 git reset HEAD@{12} --hard 

For rollback (or to revert):

  1. git revert –no-commit "commit-code-to-remove" HEAD (eg git revert –no-commit d57a39d HEAD)
  2. git commit
  3. git push

Try above two steps, and if you find this is what you want then git push.

If you find something wrong do:

git revert –abort