如何将 Git 代码仓库恢复为上一次提交的版本?

如何从当前状态恢复到某个提交上的快照?

如果我做git log,那么我得到以下输出:

$ git logcommit a867b4af366350be2e7c21b8de9cc6504678a61b`Author: Me Date:   Thu Nov 4 18:59:41 2010 -0400
blah blah blah...
commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4Author: Me Date:   Thu Nov 4 05:13:39 2010 -0400
more blah blah blah...
commit 0766c053c0ea2035e90f504928f8df3c9363b8bdAuthor: Me Date:   Thu Nov 4 00:55:06 2010 -0400
And yet more blah blah...
commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50Author: Me Date:   Wed Nov 3 23:56:08 2010 -0400
Yep, more blah blah.

如何从11月3日恢复到提交,即提交0d1d7fc

9283419 次浏览

这在很大程度上取决于你所说的“恢复”是什么意思。

暂时切换到不同的提交

如果你想暂时回到它,胡闹,然后回到你所在的地方,你所要做的就是检查所需的提交:

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

或者,如果您想在那里进行提交,请在您到达时创建一个新分支:

git checkout -b old-state 0d1d7fc32

要回到原来的位置,只需再次签出你所在的分支。(如果你做了更改,就像切换分支时一样,你必须根据需要处理它们。你可以重置以将它们丢弃;你可以隐藏、结帐、隐藏弹出以带走它们;如果你想要那里的分支,你可以将它们提交到那里的分支。)

硬删除未发布的提交

另一方面,如果你想真正摆脱从那时起所做的一切,有两种可能性。第一,如果你没有发布任何这些提交,只需重置:

# 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 stashgit reset --hard 0d1d7fc32git 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,恢复有一个非常具体的含义:使用反向补丁创建提交以取消它。这样你就不会重写任何历史记录。

# 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 (non inclusive of first hash):git revert 0d1d7fc..a867b4a
# Reverting a merge commitgit 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 didgit commit

#0 manpage在其描述中实际上涵盖了很多内容。另一个有用的链接是这git-scm.com讨论git恢复的部分

如果您决定最终不想恢复,您可以恢复恢复(如此处所述)或重置回恢复之前(请参阅上一节)。

在这种情况下,您可能会发现这个答案很有用:
如何将HEAD移回以前的位置?(分离的头)&撤消提交

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

fe60adeba6436ed8f4cc5f5c0b20df7ac9d932190c27ecfdab3cbb08a448659aa61764ad80533a1bf85007f35a23a7f29fa14b3b47c8b2ef3803d542e9ec660ba9c06317888f901e3a5ad833d49632836a80768d44ccc2107ce410c4e28c7147b382cd8f9cf6c21f5adfac3732c76c1194bbe6a330fb83e3fff2336bf8690fbfb2b4890a96549dc58bf548a51f7082f3f52880cb49bc37c40531fc478823b4f5e9b317d36a9d1db88bd34831a32de327244df36af6ea0e7208cf22fba17952fb162a01afb26de806137a681351037a2204f088a8d8f0db6e1f9179ca

创建Bash外壳脚本来恢复它们:

#!/bin/bashcd /path/to/working/copyfor i in `cat ~/commits-to-revert.txt`dogit revert $i --no-commitdone

这会将所有内容恢复到以前的状态,包括文件和目录的创建和删除,将其提交到您的分支并保留历史记录,但您将其恢复到相同的文件结构。为什么Git没有git revert --to <hash>超出我的范围。

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

git add . && git checkout master -f

简短描述:

  • 它不会像git revert那样创建任何提交。
  • 它不会像git checkout <commithashcode>那样分离你的头。
  • 它将覆盖所有本地更改并删除自分支中上次提交以来添加的所有文件。
  • 它只适用于分支名称,因此您只能以这种方式恢复到分支中的最新提交。

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

git add . && git reset --hard HEAD

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

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

盗贼编码器?

自己工作,只是想让它工作?按照下面的说明,它们多年来一直为我和许多其他人可靠地工作。

与他人合作?Git很复杂。阅读此答案下方的评论,考虑其他答案,并在您轻率行事之前与您的团队讨论。

将工作副本恢复到最近的提交

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

git reset --hard HEAD

其中HEAD是当前分支中的最后一次提交

将工作副本恢复到较旧的提交

要恢复到比最近一次提交更早的提交:

# Resets index to former commit; replace '56e05fced' with your commit codegit reset 56e05fced
# Moves pointer back to previous HEADgit reset --soft HEAD@{1}
git commit -m "Revert to 56e05fced"
# Updates working copy to reflect the new commitgit reset --hard
# Push your changes to respective branchgit push -f

学分转到类似的Stack Overflow问题,在Git中恢复到SHA哈希的提交?

有一个命令(不是核心Git的一部分,但它在临时演员包中)专门用于恢复和暂存旧提交:

git undo

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

# Remove the latest three commitsgit undo 3

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

git push -f ...

不只是git push

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

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

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


**注意:**如注释中所述,如果您与拥有旧提交副本的其他人共享您的分支,请不要这样做

同样从评论中,如果你想要一个不那么“疯狂”的方法,你可以使用

git clean -i

这里有很多复杂而危险的答案,但实际上很容易:

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

这将把从HEAD到提交哈希的所有内容都恢复回来,这意味着它将在工作树好像中重新创建该提交状态,然后你可以提交当前树,它将创建一个全新的提交,基本上等同于你“恢复”到的提交。

--no-commit标志允许git一次恢复所有提交-否则将提示您为范围内的每个提交提供消息,从而在您的历史记录中乱扔不必要的新提交。)

这是一个安全和简单的方法来回滚到以前的状态。没有历史记录被销毁,因此它可以用于已经公开的提交。

选择您需要的提交,并检查它

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

直到你得到所需的提交。要使头指向,做

git reset --hard HEAD~1

git reset --hard HEAD~2或者别的什么。

如果您想“取消提交”,擦除最后一条提交消息,并将修改后的文件放回暂存,您可以使用命令:

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

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

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

Jefromi解决方案的其他替代品

Jefromi的解决方案肯定是最好的,你绝对应该使用它们。然而,为了完整起见,我还想展示这些其他替代解决方案,它们也可以用于恢复提交(从你创建一个新的提交,撤消以前提交中的更改的意义上说,就像git revert所做的那样)。

需要明确的是,这些替代方案不是恢复提交的最佳方式Jefromi的解决方案是,但我只想指出,您也可以使用这些其他方法来实现与git revert相同的事情。

替代方案1:硬复位和软复位

这是Charles Bailey对在Git中恢复到SHA哈希的提交?的解决方案的一个非常轻微的修改版本:

# Reset the index to the desired commitgit reset --hard <commit>
# Move the branch pointer back to the previous HEADgit reset --soft HEAD@{1}
# Commit the changesgit commit -m "Revert to <commit>"

这基本上是通过使用以下事实来工作的:软重置将使上一次提交的状态保留在index/staging-Area中,然后您可以提交。

替代方案2:删除当前树并替换为新树

这个解决方案来自svick对签出旧的提交并使其成为新的提交的解决方案:

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

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

您可以通过以下两个命令执行此操作:

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

它将删除您之前的Git提交。

如果您想保留更改,还可以使用:

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

然后它会保存您的更改。

我相信有些人可能会遇到这个问题,想知道如何回滚他们在主服务器上所做的已提交的更改-即扔掉所有内容并返回原始/主服务器,在这种情况下,这样做:

git reset --hard origin/master

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

在回答之前,让我们添加一些背景,解释这个HEAD是什么。

首先,什么是HEAD?

HEAD只是对当前分支上当前提交(最新)的引用。在任何给定时间(不包括git worktree)只能有一个HEAD

HEAD的内容存储在.git/HEAD中,它包含当前提交的40字节SHA-1哈希。


detached HEAD

如果您不在最新的提交上-这意味着HEAD指向历史上的先前提交,则称为#1

说明分离HEAD概念的图表

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

在终端中运行git签出HEAD^0


关于如何从分离的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

这将签出指向所需提交的新分支。此命令将签出到给定的提交。

此时,您可以创建一个分支并从此开始工作:

# 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 commitgit checkout -b <branch name>

git reflog

您也可以始终使用refloggit reflog 将显示更新HEAD的任何更改,并签出所需的reflg条目将HEAD设置回此提交。

每次修改HEAD时,reflog中都会有一个新条目

git refloggit checkout HEAD@{...}

这会让你回到你想要的状态。

在终端中运行git reflg


git reset HEAD --hard <commit_id>

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 stashgit reset --hard 0d1d7fc32git 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.

这个模式说明了哪个命令做什么。正如您所看到的,reset && checkout修改了HEAD

显示暂存区和检查HEAD的图表

由于某种原因,我无法手动恢复我的,所以我最终这样做了。

  1. 检查了我想要的分支,复制了它。
  2. 查看最新的分支。
  3. 将我想要的分支的内容复制到最新分支的目录中,覆盖更改并提交。

如果情况是紧急一,你只是想做提问者以快速而肮脏的方式问的事情,假设你的项目在一个名为“我的项目”的目录下:


又快又脏:根据具体情况,快速和肮脏实际上可能非常好。我这里的解决方案是不是用潜伏在. git/目录下的git存储库深处的文件不可逆转地替换您工作目录中的文件,使用极其聪明和恶魔般强大的git命令,其中有很多。你不必做这样的深海潜水来恢复可能看起来是灾难性的情况,并且在没有足够专业知识的情况下尝试这样做可能会被证明是致命的


  1. 复制整个目录并将其称为其他名称,例如“我的项目-复制”。假设您的git存储库(“repo”)文件位于“我的项目”目录下(它们的默认位置,位于名为“. git”的目录下),您现在将复制您的工作文件和repo文件。

  2. 在目录“我的项目”中执行此操作:

     .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]

这将使“我的项目”下的存储库的状态恢复到你提交时的状态(“提交”意味着你工作文件的快照)。自“resetted”提交以来的所有提交将在“我的项目”下永远丢失,但是…“我的项目-复制”下的存储库中的他们仍然会在场,因为你复制了所有这些文件-包括存储库中的文件,在… /.git/.

然后,您的系统上有两个版本……您可以检查、复制或修改前一次提交中感兴趣的文件。如果您已经决定自恢复的提交以来的新工作无处可去,您可以完全丢弃“我的项目-复制”下的文件……

如果你想在不实际丢弃工作的情况下继续项目的状态,因为这个检索到的提交是再次重命名你的目录:删除包含检索到的提交的项目(或给它一个临时名称)并将你的“我的项目-复制”目录重命名回“我的项目”。然后也许试着理解这里的一些其他答案,可能很快就会做另一个提交。

Git是一个出色的创造,但绝对没有人能够“随机应变”:试图解释它的人也假设其他VCS[版本控制系统]的先验知识,并且太早太深地钻研,并犯下其他可怕的罪行,比如使用可互换的术语来“检查”-有时看起来几乎是故意混淆初学者的方式。

为了给自己省去很多压力,可以从我的伤疤中吸取教训。你几乎必须读一本关于Git的书——我建议你阅读《The Book》,Pro Git第二版:可免费下载等。从git中央。2014年出版,但截至2022年初,仍然是最好的。尽早这样做:从现在开始,Git注定要成为你生活的一部分。如果你这样做了,请记住,Git的大部分复杂性来自分支然后重新合并:第2本书实际上非常温和地介绍了这个核心方面,但你可以在第一次阅读的任何一本书中跳过这些部分。从你的问题开始有人们没有理由用科学蒙蔽你的双眼

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

PS:(轻微的警告)另一个想法:(现在)实际上很简单地将Git repo保存在包含工作文件的目录之外的目录中。这意味着你不会使用上述快速和肮脏的解决方案复制整个Git存储库。请参阅Fryer使用--separate-git-dir这里的答案。考虑到这一点,被警告:如果你有一个你不复制的“单独目录”存储库,并且你进行了硬重置,重置提交后的所有版本真的将永远丢失永远,除非你有,你绝对应该,定期备份你的存储库,最好是云端(例如googleDrive)等地。

在“备份到云”这个主题上,下一步是在GitHub或(在我看来更好)GitLab上开一个账户(当然是免费的)。然后,你可以定期执行git push命令来使你的云存储库“正确地”更新。但同样,谈论这个可能为时过早:git push必须配置,可能因为完全令人困惑的技术原因而无法工作,涉及学习远程存储库(“来源”等)。因此,在你了解之前,一种快速而肮脏的基于云的备份方法可能是可取的。同样,第3本书介绍了远程存储库的工作方式,并非常温和和合理地与您的本地存储库相关联。

如果你想纠正上一次提交中的一些错误,一个好的选择是使用修改提交命令。如果最后一次提交没有被任何引用指向,这将起到作用,因为它创建了一个与最后一次提交具有相同父级的提交。如果没有对最后一次提交的引用,它将被简单地丢弃,这次提交将是最后一次提交。这是一个在不恢复提交的情况下纠正提交的好方法。然而,它有自己的局限性。

要保留对HEAD的上一次提交的更改并移动到上一次提交,请执行以下操作:

git reset <SHA>

如果上一次提交HEAD时不需要更改,只是丢弃所有更改,请执行以下操作:

git reset --hard <SHA>

Revert是回滚提交的命令。

git revert <commit1> <commit2>

样本:

git revert 2h3h23233

它能够像下面这样从HEAD获取范围。这里1表示“恢复上次提交”。

git revert HEAD~1..HEAD

然后做:

git push

为了从一些意外更改中彻底清理编码器的目录,我们使用了:

git add -A .git reset --hard HEAD

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

还有一个最简单的解决方案;你必须更改分支才能做到这一点,但之后你可以运行:

git branch -f <<branchname>> 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

这里有一个更简单的方法可以返回到以前的提交(并使其处于未提交状态,可以随心所欲地处理它):

git reset HEAD~1

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

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

git stashgit stash clear

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

PS:它有一个小问题;它还删除了您最近存储的所有存储更改。我想在大多数情况下这应该无关紧要。

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

# Reset local master branch to November 3rd commit IDgit reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
# Reset remote master branch to November 3rd commit IDgit push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

我在一篇博客文章中找到了答案(现在已经不存在了)

请注意,这是重置和强制更改远程,这样如果您团队中的其他人已经拉取了git,您将为他们带来问题。您正在破坏更改历史记录,这是人们首先使用git的一个重要原因。

最好使用恢复(参见其他答案)而不是重置。如果你是一个人的团队,那么这可能并不重要。

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

git reset --hard HEAD
git reflog

选择git reFlog的HEAD(s)的数量,您要恢复并执行(对于这个例子,我选择12):

git reset HEAD@{12} --hard

对于回滚(或恢复):

1. git revert --no-commit "commit-code-to-remove" HEAD(e.g. git revert --no-commit d57a39d HEAD)2. git commit3. git push

试试上面的两个步骤,如果你发现这是你想要的,那么git push

如果你发现有问题,做:

git revert --abort

当您的提交被远程推送时,您需要删除它们。让我假设您的分支是开发,它被推送到起源上。

您首先需要从起源中删除开发

git push origin :develop (note the colon)

然后你需要开发到你想要的状态,让我假设提交哈希是EFGHIJK:

git reset --hard EFGHIJK

最后,再次推送开发

git push origin develop

您可以自己完成所有这些初始步骤并推回到Git存储库。

  1. 使用git pull --all命令从比特桶中提取最新版本的存储库。

  2. 从您的终端使用-n 4运行Git log命令。-n之后的数字决定了从本地历史记录中最近一次提交开始的日志中的提交数。

    $ git log -n 4
  3. 使用git reset --hard HEAD~N重置存储库历史记录的头部,其中N是您要返回头部的提交次数。在以下示例中,头部将被设置为一次提交,即存储库历史记录中的最后一次提交:

  4. 使用git push --force将更改推送到Git存储库以强制推送更改。

如果您希望Git存储库之前提交:-

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

首先,获取标识某个日期提交的字符串,执行:

git rev-list -n 1 --before="2009-07-27 13:37" origin/master

它打印提交标识符,获取字符串(例如XXXX)并执行:

git checkout XXXX

尝试重置到所需的提交:

git reset <COMMIT_ID>

要检查COMMIT_ID使用:

git log

这会将所有更改的文件重置为未添加状态。

现在您可以通过checkout所有未添加的文件

git checkout .

要验证您的更改,请使用:

git log

更新

如果您的repo中有唯一提交,请尝试

git update-ref -d HEAD

使用源树可以更容易地完成。只需右键单击您正在寻找的提交并从菜单中选择“结帐”。

在此输入图片描述

OK,在Git中返回到以前的提交非常容易…

返回不保持更改:

git reset --hard <commit>

返回与保持更改:

git reset --soft <commit>

说明:使用git reset,您可以重置为特定状态。如上所述,将其与提交哈希一起使用很常见。

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


--软

默认标志如上所述,不需要提供它,不更改工作树,但它添加了所有已更改的文件准备提交,因此您将返回到提交状态,对文件的更改将被取消。


--硬

小心这个标志。它会重置工作树和对跟踪文件的所有更改,所有更改都将消失!


我还创建了下面的图片,这可能发生在使用Git的现实生活中:

Git重置为提交

如果您想临时恢复更改,因为

  • 有人提交了破坏构建或破坏您正在使用的功能的代码

您可以使用git log搜索最后一个工作提交,然后运行:

git rebase --onto <commitId>

当远程分支再次工作时,您可以

git pull --rebase

对于临时更改,此方法优于git checkout,因为您不处于分离状态。

我发现将分支恢复到任何特定提交的最不复杂的方法是:

  1. 检查您希望恢复的提交或分支。
  2. 编辑. git/HEAD并将ref更改为要恢复到的分支。

例如:

echo 'ref: refs/heads/example' > .git/HEAD

如果然后执行git status,您应该会看到您所在的分支与您希望恢复到的分支之间的所有更改。

如果一切看起来都很好,您可以提交。您也可以使用git diff revert… example来确保它是相同的。

小心!如果用户错误地提交了错误的提交,此命令可能会导致丢失提交历史记录。总是有一些额外的git备份如果你犯了错误,还有什么地方比你安全一点。:)

我也遇到过类似的问题,想恢复到之前的提交。在我的情况下,我对保留较新的提交不感兴趣,因此我使用了Hard

我是这样做的:

git reset --hard CommitId && git clean -f

这将在本地存储库上恢复,在这里使用git push -f后将更新远程存储库。

git push -f

例如,如果您想完全忽略下一个图像中名称为enforce non-group manage policies的提交

在此处输入图片描述

你会跑

git reset --hard dd52eb9 && git clean -f

其次是

git push -f

之后,你不会在那里看到提交(enforce non-group manage policies

在此处输入图片描述

GitKraken中,您可以这样做:

  1. 右键单击要重置的提交,选择:重置到此提交/硬

    在此处输入图像描述

  2. 再次右键单击提交,选择:当前分支名称/推送

    在此处输入图像描述

  3. 点击强制推送

    在此处输入图像描述

观察:你需要小心,因为硬重置后的所有提交历史都丢失了,这个动作是不可逆的。你需要确定你在做什么。

重置分阶段的更改和提交

git reset命令允许您更改存储库的HEAD-您的工作树指向的最新提交。它修改暂存区或暂存区和工作树。

Git能够完全按照您想要的方式制作提交,这意味着您有时需要撤消对使用git add暂存的更改的更改。您可以通过调用git reset HEAD <file to change>来做到这一点。

您有两个选项可以完全删除更改。git checkout HEAD <file(s) or path(s)>是撤消对暂存区域和工作树的更改的快速方法。但是,请小心使用此命令,因为它会删除对工作树的所有更改。

Git不知道这些更改,因为它们从未提交过。一旦您运行此命令,就无法恢复这些更改。

您可以使用的另一个命令是git reset --hard。它对您的工作树同样具有破坏性-任何未提交的更改或分阶段更改在运行后都会丢失。运行git reset -hard HEAD与git checkout HEAD做同样的事情。它只是不需要文件或路径即可工作。

您可以将--softgit reset一起使用。它将存储库重置为您指定的提交并暂存所有这些更改。您已经暂存的任何更改都不会受到影响,工作树中的更改也不会受到影响。

最后,您可以使用--mixed重置工作树而无需暂存任何更改。这也取消了暂存的任何更改。

恢复提交

有时我们会犯错误:一个不应该共享的提交被推送到公共存储库,一个提交有一个无法修复的bug需要撤消,或者你不再需要那个代码了。

这些情况都需要git revertgit revert命令正是您所期望的。它通过向历史应用反向提交来恢复单个提交。

有时您需要恢复几次提交才能完全撤消更改。您可以使用-no-commit,也可以使用-n告诉Git执行恢复,但不要提交更改。

这允许您将所有恢复提交合并到一个提交中,如果您需要恢复跨越多个提交的功能,这很有用。确保您以相反的顺序恢复提交-首先是最新的提交。

否则,您可能会通过尝试还原尚不存在的代码来混淆Git。

想法:您基本上想要将当前的工作树状态替换为之前提交的状态,然后从中创建提交。最好不要更改被忽略的文件。以下是方法:

  1. Emtpy工作树*。

     git rm -r --cached . && git clean -f -d
  2. 使工作树处于我们想要的状态**。

     git checkout 0d1d7fc3 .
  3. 创建恢复提交。

     git add --all && git commit -m "revert to 0d1d7fc3"

起初我认为雅林的回答是最好的,但它不适用于合并提交。这个解决方案确实如此。

此外,它不会从历史记录中删除任何内容(推送或上推)。它生成一个干净的提交,代表我们要恢复到的状态。


*通过从工作树中删除未跟踪但未忽略的文件(在. gitignore中指定的文件)。除了我们想要保留的忽略文件外,工作树为空(如果没有指定clean-x选项)

**当指定路径时(这里:.),签出会单独离开HEAD。

有许多答案提供删除最后一次提交。然而,这里询问如何删除特定的提交,在这种情况下,它是删除最后三次提交,在11月3日返回提交。

你可以用rebase做到这一点。简单地做:

git rebase -i HEAD~4

这将列出您最近的四个提交。

现在您可以选择删除提交。您可以使用drop文本执行此操作。

  • 只需在键盘上点击i,然后在要删除写drop而不是默认pick的提交旁边

  • 在键盘上,点击exit:wq

要确保删除提交,请编写:

git log

您将看到您保存为Drop的提交被删除。

要将这些更改推送到您的远程分支,请编写:

git push --force

最好的方法是:

git reset --hard <commidId> && git push --force

这会将分支重置为特定的提交,然后将使用与本地相同的提交上传远程服务器。

小心--force标志,因为它删除了选定提交后的所有后续提交,而没有恢复它们的选项。