如何将Git存储库还原为以前的提交?

git git-checkout git-reset git-revert 落落 | 2020-02-02 19:35:06


如何将当前状态还原为在特定提交时生成的快照?
如果我执行了
git log
,则会得到以下输出:
$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me
Date: Thu Nov 4 18:59:41 2010 -0400
blah blah blah...
commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me
Date: Thu Nov 4 05:13:39 2010 -0400
more blah blah blah...
commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me
Date: Thu Nov 4 00:55:06 2010 -0400
And yet more blah blah...
commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me
Date: Wed Nov 3 23:56:08 2010 -0400
Yep, more blah blah.

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






30 答案



这在很大程度上取决于您所说的“恢复”。
临时切换到不同的提交
如果您想暂时返回到它,四处游荡,然后返回到您所在的位置,您所要做的就是检查所需的提交:
# 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有一个非常具体的含义:用reverse补丁创建一个commit来取消它。这样,您就不会重写任何历史记录。
# 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
# 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-scm.com中讨论git revert的部分。
如果您最终决定不想还原,则可以还原还原(如本文所述)或重置回还原之前(请参阅上一节)。
在这种情况下,您可能也会发现此答案很有帮助:
如何将头移回以前的位置?(分离的头部)

2020-02-02 19:35:18
小草


这里有很多复杂而危险的答案,但实际上很简单:
git revert --no-commit 0766c053..HEAD
git commit

这将把所有内容从头还原到提交散列,这意味着它将在工作树中重新创建该提交状态,就好像每次提交都被退回一样。然后,您可以提交当前树,它将创建一个全新的提交,基本上等同于您“还原”到的提交。
(通过
--no-commit
标志,git可以一次还原所有提交—否则,将提示您为该范围内的每个提交发送一条消息,将不必要的新提交丢弃在历史记录中。)
这是一种安全而简单的回滚到以前状态的方法。不会销毁任何历史记录,因此可以将其用于已公开的提交。

2020-02-02 19:35:18
新月冰冰


流氓编码员?
自己工作,只想让它工作?按照下面的说明,他们已经为我和许多其他人可靠地工作了多年。
与其他人一起工作?Git很复杂。在您鲁莽行事之前,请阅读下面的注释。
将工作副本还原为最新提交
还原为以前的提交,忽略任何更改:
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

信用进入类似的堆栈溢出问题,在Git中通过SHA散列还原为提交?.

2020-02-02 19:35:18
酱香茄子


对我和其他人来说,最好的选择是Git重置选项:
git reset --hard  && git clean -f

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

**注意:**如注释中所述,如果您与其他拥有旧提交副本的人共享分支,请不要这样做
也可以从注释中共享,如果您希望使用一种不太“圆滑”的方法,可以使用
git clean -i

2020-02-02 19:35:18
chaos


在回答之前,让我们添加一些背景知识,解释一下这个
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 :这将签出指向所需提交的新分支。此命令将签出到给定的提交。
此时,您可以创建分支并从此开始工作:
# 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
# Create a new branch forked to the given commit
git checkout -b

git reflog

您也可以始终使用
reflog
git reflog
将显示更新了
HEAD
的任何更改,并且签出所需的reflog条目将设置
HEAD
返回此提交。
每次修改头时,都会在
reflog中有一个新条目让您返回到所需的提交

git reset HEAD --hard 

“将”您的头移回所需的提交。
# 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

2020-02-02 19:35:18
SingleGaming


如果要“取消提交”,请删除最后一条提交消息,并将修改后的文件放回暂存中,您可以使用以下命令:
git reset --soft HEAD~1

--soft
指示应将未提交的文件保留为工作文件,而不是将其丢弃的
--hard

HEAD~1
是最后一次提交。如果要回滚3个提交,可以使用
HEAD~3
。如果你想回滚到一个特定的修订号,你也可以使用它的SHA散列来完成。
这是一个非常有用的命令,当你提交了错误的东西,并且你想撤销最后的提交。
来源:http://nakkaya.com/2009/09/24/git delete last commit/

2020-02-02 19:35:18
孤狼


您可以通过以下两个命令来执行此操作:
git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

它将删除您以前的Git提交。
如果要保留更改,您还可以使用:
git reset --soft [previous Commit SHA id here]

然后它将保存您的更改。

2020-02-02 19:35:18
中出之道


我尝试了很多方法来还原Git中的本地更改,如果您只想还原到最新的提交状态,这似乎是最有效的。
git add . && git checkout master -f

简短描述:
它不会像
git revert
那样创建任何提交。
它不会像
git checkout 
那样分离您的头。
它将覆盖您的所有本地更改并删除自分支中上次提交以来添加的所有文件。
它只对分支名称起作用,因此您可以这样只能还原到分支中的最新提交。
我找到了一种更方便、更简单的方法来实现上述结果:
git add . && git reset --hard HEAD

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

2020-02-02 19:35:18
萌萌俺の嫁


好的,返回git中的前一个提交非常容易……
不保留更改就返回:
git reset --hard 

保留更改就返回:
git reset --soft 

解释:使用git reset可以重置到特定状态,如上面所示,它通常与提交散列一起使用。
但正如您所看到的,区别在于使用两个标志
--soft
--hard
,默认情况下使用
git reset
标志,但始终使用标志是一个好的实践,我解释每个标志:
--soft
如所述的默认标志,不需要提供,不需要提供更改工作树,但添加所有准备提交的更改文件,以便返回到“提交”状态,即对文件的更改未保存。
--hard
小心这个标志,它会重置工作树,所有对跟踪文件的更改都将消失!
我还创建了下面的图像,这可能发生在现实生活中使用git时:

2020-02-02 19:35:18
蛙控Z

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

  [代码] < /PRE> > BR>我从博客帖子中找到答案(现在不再存在)。BR>注意这是重置并迫使改变到远程,这样如果你的团队中的其他人已经拉了枪,你会给他们带来麻烦的。您正在破坏更改历史,这是人们首先使用git的一个重要原因。
最好使用revert(请参阅其他答案)而不是reset。
如果你是一个人的团队,那么这可能无关紧要。

2020-02-02 19:35:18
Ash


除了这个精确的组合之外,这里没有什么对我有用的:
git reset --hard 
git push origin --force

这里的键是强制推送,没有额外的提交/提交消息等。

2020-02-02 19:35:18
boreas


假设您在名为
~/commits-to-revert.txt
的文本文件中有以下提交(我使用
git log --pretty=oneline
来获取它们)
fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

创建Bash 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 
超出了我的理解范围。

2020-02-02 19:35:18
广濑康穗


除了Jefromi的解决方案之外,Jefromi的解决方案绝对是最好的,您一定要使用它们。但是,为了完整起见,我还想展示这些其他的替代解决方案,它们也可以用于恢复提交(从某种意义上说,您创建了一个新的提交来撤消以前提交中的更改,就像
git revert
所做的那样)。
要清楚,这些替代方案并不是恢复提交的最佳方式,Jefromi的解决方案是,但我只想指出,您也可以使用这些其他方法来实现与
git revert

替代方案1:硬重置和软重置
这是Charles Bailey的解决方案的一个稍加修改的版本,以在Git中还原为SHA散列提交?:
# Reset the index to the desired commit
git reset --hard
# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}
# Commit the changes
git commit -m "Revert to "

这基本上是通过以下事实工作的:软重置将保留索引/暂存区域中暂存的上一个提交的状态,然后您可以提交该状态。
备选方案2:删除当前树并替换为新树
此解决方案来自svick的签出旧提交并使其成为新提交:
git rm -r .
git checkout .
git commit

类似于备选方案1,这会在当前工作副本中复制
的状态。必须先执行
git rm
,因为
git checkout
不会删除自
之后添加的文件

2020-02-02 19:35:18
虔诚者


这里有一种更简单的方法返回到以前的提交(并使其处于未提交状态,可以随意处理):
git reset HEAD~1

因此,不需要提交id等等:)

2020-02-02 19:35:18
Miku.Moetsune


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

在每个手册页中,它也可以这样使用:
# Remove the latest three commits
git back 3

2020-02-02 19:35:18
Nagato


在所有更改之后,当您按下所有这些命令时,您可能必须使用:
git push -f ...

而不仅仅是
git push

2020-02-02 19:35:18
雑音ミク


您可以自己完成所有这些初始步骤并返回git repo。
使用
git pull --all
命令从Bitbucket中提取存储库的最新版本。
从终端中使用-n 4运行git log命令。-n之后的数字确定从本地历史记录中最新提交开始的日志中提交数。
$ git log -n 4

使用
git reset --hard HEAD~N
重置存储库历史记录的头,其中n是要收回头的提交数。在下面的例子中,head将被设置为一个commit,返回到存储库历史记录中的最后一个commit:
使用
git push --force
强制将更改推送到git repo。
如果您希望git存储库执行前一个commit
git pull --all
git reset --hard HEAD~1
git push --force

2020-02-02 19:35:18
上白澤慧音


还原到最新提交并忽略所有本地更改:
git reset --hard HEAD

2020-02-02 19:35:18
液祸


选择所需提交,并通过
git show HEAD
git show HEAD~1
git show HEAD~2

进行检查,直到获得所需提交。要使头部指向这一点,请执行
git reset --hard HEAD~1

git reset --hard HEAD~2
或其他操作。

2020-02-02 19:35:18
魔人アーチャー


如果情况紧急,而你只想按照提问者的要求快速而肮脏地做,假设你的项目在一个名为“我的项目”的目录下:快速而肮脏:根据情况,快速而肮脏实际上可能非常好。我在这里的解决方案并不是用从隐藏在.git/目录下的git存储库深处拖拽/提取的文件不可逆转地替换工作目录中的文件,这些文件使用了极其聪明和强大的git命令,其中有很多。你不必做这样的深海潜水来恢复看起来可能是灾难性的情况,如果没有足够的专业知识尝试这样做可能是致命的。假设您的git存储库(“repo”)文件位于“我的项目”目录下(它们的默认位置,位于名为“.git”的目录下),现在您已经复制了工作文件和repo文件。
在“我的项目”目录中执行此操作:
.../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]

这将使“我的项目”下的repo状态返回到提交时的状态(“提交”表示工作文件的快照)。从那以后所有的承诺都将在“我的计划”下永远消失,但是。。。它们仍然会出现在repo的“我的项目-副本”下,因为您复制了所有这些文件-包括…/.git/
下的文件,然后您的系统上有两个版本。。。您可以检查、复制或修改以前提交的感兴趣文件或其他文件。如果您已经决定了新的工作,因为恢复的提交将不起作用,那么您可以完全放弃“我的项目-副本”下的文件。。。
如果您希望在不实际放弃工作的情况下继续执行项目的状态,那么很明显的一件事是再次重命名您的目录:删除包含检索到的提交的项目(或给它一个临时名称),并将您的“my project-copy”目录重命名回“my project”。然后,也许试着理解这里的其他一些答案,也许很快就会做另一个承诺。
Git是一个杰出的创造,但绝对没有人能够“随机应变”地去理解它:同样,那些试图解释它太多的人往往会假设事先了解了其他VCS[版本控制系统],并且研究得太深太快,而且犯下其他罪行,比如使用可互换的术语“结帐”,这种方式有时看起来几乎是故意要迷惑初学者的。
为了减轻你的压力,从我的伤疤中学习。你必须读一本关于Git的书-我推荐“用Git进行版本控制”。早做而不是晚做。如果你这么做了,记住Git的大部分复杂性来自分支,然后再合并:你可以跳过任何书中的那些部分。从你的问题来看,人们没有理由用科学来蒙蔽你。
尤其是,例如,如果这是一个绝望的情况,你是一个新手与吉特!
PS:另一个想法是:实际上(现在)将Git repo保存在工作文件所在目录之外的目录中非常简单。这意味着您不必使用上述快速脏解决方案复制整个Git存储库。请使用此处的
--separate-git-dir
查看Fryer的答案。不过,请注意:如果您有一个未复制的“单独目录”存储库,并且您进行了硬重置,则重置提交之后的所有版本都将永远丢失,除非您按照您绝对应该的方式定期备份存储库,最好是在云端(例如Google Drive)和其他地方。
关于“备份到云端”这一主题,下一步是在GitHub或GitLab(在我看来更好)开立一个帐户(当然是免费的)。然后,您可以定期执行
git push
命令,使您的云回购“正常”更新。但是,再说一遍,谈论这个可能太早了。

2020-02-02 19:35:18
郁闷的小强


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

如果前一次提交到HEAD不需要更改,只需放弃所有更改,请执行以下操作:
git reset --hard 

2020-02-02 19:35:18
aiaifer


为了彻底清除编码器目录中的一些意外更改,我们使用了:
git add -A .
git reset --hard HEAD

只需
git reset --hard HEAD
即可删除修改,但不会删除“新”文件。在他们的案例中,他们意外地将一个重要文件夹随机拖到某个地方,所有这些文件都被Git视为新文件,因此一个
reset --hard
无法修复它。通过预先运行
git add -A .
,它可以显式地使用git跟踪所有这些数据,并通过重置将其清除。

2020-02-02 19:35:18
围观的茶几君


这是直接重置为最近提交的另一种方法,它直接清除自上次提交以来所做的所有更改。
PS:它有一个小问题;它还删除最近存储的所有存储更改。我想这在大多数情况下都无关紧要。

2020-02-02 19:35:18
无敌林克


我相信有些人可能会问这个问题,想知道如何回滚他们在主服务器中所做的已提交的更改—即扔掉所有内容,返回到origin/master,在这种情况下,请执行以下操作:
git reset --hard origin/master

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

2020-02-02 19:35:18


还原最近的提交:
git reset --hard HEAD

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

还原到旧的提交:
还原旧版本的最快方法是使用
reset
命令:
# Resets index to former commit
git reset 56e05fced
# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}
# Updates working copy to reflect the new commit
git reset --hard

这将把HEAD分支还原到指定的版本。此版本之后的所有提交都将被有效撤消;您的项目与当时的项目完全相同。
reset命令带有两个选项,其中一个更有趣的选项是
--soft
标志。如果您使用它而不是
--hard
,Git将保留这些“未完成”提交中的所有更改作为本地修改。
还原新本地分支中的修订
如上所述,在
头上使用reset命令是一个相当激烈的操作:它将删除指定修订之后的任何提交(在此分支上)。如果你确定这是你想要的,一切都很好。
不过,还有一种更安全的方法,以防你宁愿不碰你现在的总分支。由于“分支”在Git中是如此便宜和容易,我们可以轻松地创建一个新的分支,该分支从旧版本开始:
git checkout -b old-project-state 0ad5a7a6

通常,checkout命令只用于切换分支。但是,通过提供-b参数,您还可以让它创建一个新分支(在本例中命名为old project state)。如果您不希望它从当前的HEAD修订版开始,您还需要提供一个commit散列-我们要还原的旧项目修订版。
您现在有一个名为old project state的新分支,它反映了您的项目的旧版本-而无需触摸甚至删除任何其他commit或分支。

2020-02-02 19:35:18
伊澄酱,


Revert是回滚提交的命令。
git revert   

示例:
git revert 2h3h23233

它可以从下面的头部获取范围。这里1表示“还原上次提交”。
git revert HEAD~1..HEAD

然后执行
git push

2020-02-02 19:35:18
慕枫


尝试重置为所需的提交-
git reset 

(要检查提交ID,请使用
git log

这将重置所有已更改的文件为未添加状态。
现在您可以通过
git checkout .

检查
git log
来验证更改。
更新
如果您的回购中只有一个提交,请尝试
git update-ref -d HEAD

2020-02-02 19:35:18
鬼畜果酱


当您的提交被远程推送时,您需要删除它们。让我假设您的分支正在开发,并且它被推到了源位置上。
您首先需要删除源位置上的开发:
git push origin :develop (note the colon)

然后您需要得到所需的开发状态,让我假设提交哈希是EFGHIJK:
git reset --hard EFGHIJK

最后,再次推开发:
git push origin develop

2020-02-02 19:35:18
碎云流转


小心!如果用户错误地提交了错误的提交,此命令可能会导致丢失提交历史记录。一定要有一个额外的git备份,一些
在其他地方,以防你犯错误,比你安全一点。
:)
我有类似的问题,想恢复到以前的提交。在我的例子中,我没有被设置为保存更新的提交,因此我使用了
Hard

这就是我的方法:
git reset --hard CommitId && git clean -f

在使用
git push -f
之后,这将在本地存储库上还原,并更新远程存储库。
git push -f

2020-02-02 19:35:18
卡门有希


如果您想在最后一次提交时更正一些错误,一个好的替代方法是使用git commit--amend命令。如果最后一次提交没有被任何引用指向,这将起到关键作用,因为它创建了一个与最后一次提交具有相同父级的提交。如果没有对最后一次提交的引用,则它将被丢弃,并且此提交将是最后一次提交。这是在不恢复提交的情况下更正提交的好方法。然而,它有自己的局限性。

2020-02-02 19:35:18
W.W.


World is powered by solitude
备案号:湘ICP备19012068号