如何将 Git 存储库恢复到以前的提交?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4114095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I revert a Git repository to a previous commit?
提问by Crazy Serb
How do I revert from my current state to a snapshot made on a certain commit?
如何从当前状态恢复到某个提交时的快照?
If I do git log
, then I get the following output:
如果我这样做git log
,那么我会得到以下输出:
$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date: Thu Nov 4 18:59:41 2010 -0400
blah blah blah...
commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date: Thu Nov 4 05:13:39 2010 -0400
more blah blah blah...
commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date: Thu Nov 4 00:55:06 2010 -0400
And yet more blah blah...
commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date: Wed Nov 3 23:56:08 2010 -0400
Yep, more blah blah.
How do I revert to the commit from November 3, i.e. commit 0d1d7fc
?
我如何从 11 月 3 日恢复到提交,即 commit 0d1d7fc
?
回答by Cascabel
This depends a lot on what you mean by "revert".
这在很大程度上取决于您所说的“恢复”是什么意思。
Temporarily switch to a different commit
暂时切换到不同的提交
If you want to temporarily go back to it, fool around, then come back to where you are, all you have to do is check out the desired commit:
如果你想暂时回到它,鬼混,然后回到你所在的地方,你所要做的就是检查所需的提交:
# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32
Or if you want to make commits while you're there, go ahead and make a new branch while you're at it:
或者,如果您想在那里进行提交,请继续创建一个新分支:
git checkout -b old-state 0d1d7fc32
To go back to where you were, just check out the branch you were on again. (If you've made changes, as always when switching branches, you'll have to deal with them as appropriate. You could reset to throw them away; you could stash, checkout, stash pop to take them with you; you could commit them to a branch there if you want a branch there.)
要回到原来的位置,只需再次查看您所在的分支。(如果您进行了更改,一如既往地在切换分支时,您将必须适当地处理它们。您可以重置以将它们扔掉;您可以将它们藏匿、结帐、藏匿流行以随身携带;您可以提交如果您想在那里开设分支机构,请将它们转移到那里的分支机构。)
Hard delete unpublished commits
硬删除未发布的提交
If, on the other hand, you want to really get rid of everything you've done since then, there are two possibilities. One, if you haven't published any of these commits, simply reset:
另一方面,如果您想真正摆脱从那时起所做的一切,则有两种可能性。一,如果您尚未发布任何这些提交,只需重置:
# 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.
If you mess up, you've already thrown away your local changes, but you can at least get back to where you were before by resetting again.
如果你搞砸了,你已经扔掉了你的本地更改,但你至少可以通过再次重置回到之前的位置。
Undo published commits with new commits
使用新提交撤消已发布的提交
On the other hand, if you've published the work, you probably don't want to reset the branch, since that's effectively rewriting history. In that case, you could indeed revert the commits. With Git, revert has a very specific meaning: create a commit with the reverse patch to cancel it out. This way you don't rewrite any history.
另一方面,如果您已经发布了作品,您可能不想重置分支,因为这实际上是在重写历史。在这种情况下,您确实可以还原提交。对于 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
The git-revert
manpageactually covers a lot of this in its description. Another useful link is this git-scm.com section discussing git-revert.
该git-revert
手册页实际上涵盖在其描述中有很多这一点。另一个有用的链接是讨论 git-revert 的 git-scm.com 部分。
If you decide you didn't want to revert after all, you can revert the revert (as described here) or reset back to before the revert (see the previous section).
如果您最终决定不想还原,则可以还原还原(如此处所述)或重置回还原之前(请参阅上一节)。
You may also find this answer helpful in this case:
How to move HEAD back to a previous location? (Detached head)
在这种情况下,您可能还会发现此答案很有帮助:
How to move HEAD back to a previous location? (分离的头)
回答by Yarin
Lots of complicated and dangerous answers here, but it's actually easy:
这里有很多复杂而危险的答案,但实际上很简单:
git revert --no-commit 0766c053..HEAD
git commit
This will revert everything from the HEAD back to the commit hash, meaning it will recreate that commit state in the working tree as ifevery commit since had been walked back. You can then commit the current tree, and it will create a brand new commit essentially equivalent to the commit you "reverted" to.
这会将 HEAD 中的所有内容恢复为提交哈希,这意味着它将在工作树中重新创建该提交状态,就像此后的每个提交都已被退回一样。然后您可以提交当前树,它将创建一个全新的提交,本质上等同于您“恢复”到的提交。
(The --no-commit
flag lets git revert all the commits at once- otherwise you'll be prompted for a message for each commit in the range, littering your history with unnecessary new commits.)
(该--no-commit
标志让 git 一次还原所有提交 - 否则,系统会提示您为范围内的每个提交输入一条消息,从而使您的历史记录充满不必要的新提交。)
This is a safe and easy way to rollback to a previous state. No history is destroyed, so it can be used for commits that have already been made public.
这是回滚到先前状态的一种安全且简单的方法。没有历史被破坏,所以它可以用于已经公开的提交。
回答by boulder_ruby
Rogue Coder?
流氓编码器?
Working on your own and just want it to work? Follow these instructions below, they've worked reliably for me and many others for years.
自己工作,只是想让它工作?按照下面的这些说明进行操作,它们多年来一直为我和许多其他人可靠地工作。
Working with others? Git is complicated. Read the comments below this answer before you do something rash.
与他人合作?Git很复杂。在你做一些鲁莽的事情之前,阅读这个答案下面的评论。
Reverting Working Copy to Most Recent Commit
将工作副本恢复到最近提交
To revert to a previous commit, ignoring any changes:
要恢复到先前的提交,忽略任何更改:
git reset --hard HEAD
where HEAD is the last commit in your current branch
其中 HEAD 是当前分支中的最后一次提交
Reverting The Working Copy to an Older Commit
将工作副本恢复到较旧的提交
To revert to a commit that's older than the most recent commit:
要恢复到比最近提交更旧的提交:
# 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
Credits go to a similar Stack Overflow question, Revert to a commit by a SHA hash in Git?.
积分转到类似的堆栈溢出问题,通过 Git 中的 SHA 哈希恢复到提交?.
回答by Pogrindis
The best option for me and probably others is the Git reset option:
对我和其他人来说最好的选择是 Git 重置选项:
git reset --hard <commidId> && git clean -f
This has been the best option for me! It is simple, fast and effective!
这对我来说是最好的选择!它简单、快速、有效!
** Note:** As mentioned in comments don't do this if you're sharing your branch with other people who have copies of the old commits
** 注意:** 如评论中所述,如果您与拥有旧提交副本的其他人共享您的分支,请不要这样做
Also from the comments, if you wanted a less 'ballzy' method you could use
同样从评论中,如果你想要一个不那么“ballzy”的方法,你可以使用
git clean -i
回答by CodeWizard
Before answering let's add some background, explaining what this HEAD
is.
在回答之前,让我们添加一些背景知识,解释一下这HEAD
是什么。
First of all what is HEAD?
First of all what is HEAD?
HEAD
is simply a reference to the current commit (latest) on the current branch. There can only be a single HEAD
at any given time (excluding git worktree
).
HEAD
只是对当前分支上的当前提交(最新)的引用。HEAD
在任何给定时间只能有一个(不包括git worktree
)。
The content of HEAD
is stored inside .git/HEAD
, and it contains the 40 bytes SHA-1 of the current commit.
的内容HEAD
存储在 中.git/HEAD
,它包含当前提交的 40 字节 SHA-1。
detached HEAD
detached HEAD
If you are not on the latest commit - meaning that HEAD
is pointing to a prior commit in history it's called detached HEAD
.
如果您不在最新的提交上——这意味着它HEAD
指向历史中的先前提交,则称为detached HEAD
.
On the command line it will look like this - SHA-1 instead of the branch name since the HEAD
is not pointing to the the tip of the current branch:
在命令行上,它看起来像这样 - SHA-1 而不是分支名称,因为HEAD
它没有指向当前分支的尖端:
A few options on how to recover from a detached HEAD:
关于如何从分离的 HEAD 中恢复的一些选项:
git checkout
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
This will checkout new branch pointing to the desired commit. This command will checkout to a given commit.
这将签出指向所需提交的新分支。此命令将检出给定的提交。
At this point you can create a branch and start to work from this point on:
此时您可以创建一个分支并从这一点开始工作:
# 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
git reflog
You can always use the reflog
as well. git reflog
will display any change which updated the HEAD
and checking out the desired reflog entry will set the HEAD
back to this commit.
您也可以随时使用reflog
。git reflog
将显示更新HEAD
并检出所需引用日志条目的任何更改将设置HEAD
回此提交。
Every time the HEAD is modified there will be a new entry in the reflog
每次修改 HEAD 时都会有一个新条目 reflog
git reflog
git checkout HEAD@{...}
This will get you back to your desired commit
这会让你回到你想要的提交
git reset HEAD --hard <commit_id>
git reset HEAD --hard <commit_id>
"Move" your head back to the desired commit.
“移动”你的头回到所需的提交。
# 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.
- Note: (Since Git 2.7) you can also use the
git rebase --no-autostash
as well.
- 注意:(从 Git 2.7 开始)您也可以使用
git rebase --no-autostash
。
This schema illustrates which command does what. As you can see there reset && checkout
modify the HEAD
.
这个模式说明了哪个命令做什么。如您所见,reset && checkout
修改HEAD
.
回答by Stephen Ostermiller
If you want to "uncommit", erase the last commit message, and put the modified files back in staging, you would use the command:
如果您想“取消提交”,删除最后的提交消息,并将修改后的文件放回暂存状态,您可以使用以下命令:
git reset --soft HEAD~1
--soft
indicates that the uncommitted files should be retained as working files opposed to--hard
which would discard them.HEAD~1
is the last commit. If you want to rollback 3 commits you could useHEAD~3
. If you want to rollback to a specific revision number, you could also do that using its SHA hash.
--soft
表示未提交的文件应作为工作文件保留,否则--hard
将丢弃它们。HEAD~1
是最后一次提交。如果你想回滚 3 次提交,你可以使用HEAD~3
. 如果你想回滚到一个特定的修订号,你也可以使用它的 SHA 哈希来做到这一点。
This is an extremely useful command in situations where you committed the wrong thing and you want to undo that last commit.
在您提交错误的事情并且您想撤消上次提交的情况下,这是一个非常有用的命令。
Source: http://nakkaya.com/2009/09/24/git-delete-last-commit/
回答by kiran boghra
You can do this by the following two commands:
您可以通过以下两个命令执行此操作:
git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f
It will remove your previous Git commit.
它将删除您之前的 Git 提交。
If you want to keep your changes, you can also use:
如果要保留更改,还可以使用:
git reset --soft [previous Commit SHA id here]
Then it will save your changes.
然后它将保存您的更改。
回答by Roman Minenok
I have tried a lot of ways to revert local changes in Git, and it seems that this works the best if you just want to revert to the latest commit state.
我尝试了很多方法来恢复 Git 中的本地更改,如果您只想恢复到最新的提交状态,这似乎最有效。
git add . && git checkout master -f
Short description:
简短的介绍:
- It will NOT create any commits as
git revert
does. - It will NOT detach your HEAD like
git checkout <commithashcode>
does. - It WILL override all your local changes and DELETE all added files since the last commit in the branch.
- It works only with branches names, so you can revert only to latest commit in the branch this way.
- 它不会像
git revert
那样创建任何提交。 - 它不会像
git checkout <commithashcode>
那样分离你的头。 - 它将覆盖您所有的本地更改并删除自分支中的最后一次提交以来添加的所有文件。
- 它仅适用于分支名称,因此您只能通过这种方式恢复到分支中的最新提交。
I found a much more convenient and simple way to achieve the results above:
我找到了一种更方便和简单的方法来实现上述结果:
git add . && git reset --hard HEAD
where HEAD points to the latest commit at you current branch.
HEAD 指向您当前分支的最新提交。
It is the same code code as boulder_ruby suggested, but I have added git add .
before git reset --hard HEAD
to erase all new files created since the last commit since this is what most people expect I believe when reverting to the latest commit.
这是相同的代码,代码boulder_ruby建议,但我已经加入git add .
之前 git reset --hard HEAD
删除的所有新建文件自上次提交,因为这是大多数人的期待,我相信恢复到最新提交的时候。
回答by Alireza
OK,going back to a previous commit in Git is quite easy...
好的,回到以前的 Git 提交是很容易的......
Revert back without keepingthe changes:
在不保留更改的情况下恢复:
git reset --hard <commit>
Revert back with keepingthe changes:
恢复并保留更改:
git reset --soft <commit>
Explanation:using git reset
, you can reset to a specific state. It's common using it with a commit hash as you see above.
说明:使用git reset
,可以重置为特定状态。如上所示,将它与提交哈希一起使用是很常见的。
But as you see the difference is using the two flags --soft
and --hard
, by default git reset
using --soft
flag, but it's a good practice always using the flag, I explain each flag:
但是正如您所看到的,区别在于使用两个标志,--soft
并且--hard
默认情况下git reset
使用--soft
标志,但始终使用标志是一个好习惯,我解释了每个标志:
--soft
- 柔软的
The default flag as explained, not need to provide it, does not change the working tree, but it adds all changed files ready to commit, so you go back to the commit status which changes to files get unstaged.
所解释的默认标志,不需要提供它,不会改变工作树,但它会添加所有准备提交的已更改文件,因此您返回到提交状态,对文件的更改未暂存。
--hard
- 难的
Be careful with this flag. It resets the working tree and all changes to tracked files and all will be gone!
小心这个标志。它会重置工作树和对跟踪文件的所有更改,一切都将消失!
I also created the image below that may happen in a real life working with Git:
我还创建了下面的图像,它可能在使用 Git 的现实生活中发生:
回答by markreyes
Assuming you're talking about master and on that respective branch (that said, this could be any working branch you're concerned with):
假设您正在谈论 master 和相应的分支(也就是说,这可能是您关注的任何工作分支):
# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master
I found the answer from in a blog post (now no longer exists)
我在一篇博客文章中找到了答案(现在不再存在)
Note that this is Resetting and Forcing the change to the remote, so that if others on your team have already git pulled, you will cause problems for them. You are destroying the change history, which is an important reason why people use git in the first place.
请注意,这是重置并强制更改远程,因此如果您团队中的其他人已经 git pull,您将给他们带来问题。您正在破坏更改历史记录,这是人们首先使用 git 的重要原因。
Better to use revert (see other answers) than reset. If you're a one man team then it probably doesn't matter.
最好使用还原(请参阅其他答案)而不是重置。如果你是一个单人团队,那么这可能无关紧要。