如何将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
或者,如果你想在那里做提交,那么在你做的时候继续做一个新的分支:
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-revert的git-scm.com部分.
如果您决定不想还原,则可以还原还原(如此处所述)或重置为还原之前(请参阅上一节).
在这种情况下,您可能还会发现此答案很有用:
如何将HEAD移回以前的位置?(独立头)
- 要恢复当前命令是'git checkout master'
- [@ Rod的评论](http://stackoverflow.com/questions/4114095/git-revert-to-previous-commit-how/7760865#comment11806784_7760865)在`git revert HEAD~3`上作为最好的回归` 3`提交是重要的惯例.
- 你可以使用`git revert --no-commit hash1 hash2 ...`然后在一次提交中提交每一个revert`git commit -m"消息"`
- 你能写出整数吗?喜欢:`git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50`
- @MathiasMadsenStav是的,您当然可以通过完整的SHA1指定提交.我使用缩写哈希来使答案更具可读性,如果你打字输入,你也倾向于使用它们.如果您正在复制和粘贴,请务必使用完整哈希.有关如何使用的完整说明,请参阅[在man git rev-parse中指定修订版](http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html#_specifying_revisions)名称提交.
- 在这种情况下,"发布"意味着什么?
- 我跑'git checkout 0d1d7fc32'暂时回去.现在我该如何回到最新状态?我的最新版本不再出现在'git log'中了
这里有很多复杂而危险的答案,但实际上很简单:
git revert --no-commit 0766c053..HEAD
git commit
这将从HEAD返回到提交哈希的所有内容,这意味着它将在工作树中重新创建该提交状态,就好像每次提交都已经被回溯一样.然后,您可以提交当前树,它将创建一个全新的提交,基本上等同于您"恢复"的提交.
(该--no-commit
标志允许git立即恢复所有提交 - 否则,系统会提示您为该范围内的每个提交发送一条消息,并使用不必要的新提交乱丢您的历史记录.)
这是回滚到先前状态的安全且简单的方法.没有历史被破坏,因此它可以用于已经公开的提交.
- 如果0766c053..HEAD之间的一个提交是合并,那么将弹出一个错误(与没有指定-m一起).这可能有助于那些遇到这种情况:http://stackoverflow.com/questions/5970889/why-does-git-revert-complain-about-a-missing-m-option
- 如果你确实想要进行单独提交(而不是通过一次大提交来恢复所有提交),那么你可以传递`--no-edit`而不是`--no-commit`,这样你就不必编辑每次还原的提交消息.
- `$ git revert --no-commit 53742ae..HEAD`返回`致命:空提交设置已通过`
- @AlexG那是因为你需要在**之前输入一个哈希值**你要回到的那个.在我的例子中,哈希就像:'81bcc9e HEAD {0}; e475924 HEAD {1},...`(来自`git reflog`),我想撤消我在'81bcc9e`中所做的事情,然后我不得不做`git revert e475924..HEAD`
- 要在提交之前查看差异,请使用`git diff --cached`.
- 这没有用; 有一个合并,它弹出一个错误,说没有指定-m选项; 正如在评论中我做了这个git revert -m 1 HEAD,并再次尝试,但它给出了一个错误,说cherrypick或revert正在进行中.我做了cherrypick --quit,它回到了有一个合并的消息,并且没有指定-m
将工作副本还原为最近的提交
要恢复到先前的提交,请忽略任何更改:
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
Credits转到类似的Stack Overflow问题,在Git中恢复为SHA哈希提交?.
- 我做到了,但后来我无法提交并推送到远程存储库.我想要一个特定的旧提交成为HEAD ......
- 这意味着你已经推进了你想要恢复的提交.对于已签出代码并进行操作的人来说,这可能会带来很多问题.因为他们不能顺利地对你的提交进行申请.在这种情况下,更好的做一个git revert.如果你是唯一一个使用回购的人.做一个git push -f(但在做之前要三思而后行)
- 我还要指出,对于软复位解决方案,不是先进行混合复位,最后是硬复位,实际上可以先进行硬复位,如下所示:`git reset --hard 56e05fc; git reset --soft HEAD @ {1}; git commit`.
- @nuton linus自责,git的创造者,批评它过于复杂.他有记录表示他感到"震惊",因为它的复杂性使git变得如此受欢迎
- @boulder_ruby我认为你的意思是Linus Torvalds是git的创造者.但我认为Linus Pauling可能会同意git很复杂.
- 如果您在PowerShell中工作,请在HEAD @ {1}周围添加引号:git reset --soft'HEAD @ {1}'因为花括号有意义
- 遗憾的是版本控制系统使语法对于基本的历史浏览激活非常复杂.
我和其他人的最佳选择是Git重置选项:
git reset --hard <commidId> && git clean -f
这对我来说是最好的选择!它简单,快速,有效!
注意: 如果您与拥有旧提交副本的其他人共享您的分支,则如评论中所述,请勿执行此操作
同样来自评论,如果你想要一个较少的'ballzy'方法,你可以使用
git clean -i
- **强制性警告:如果您与拥有旧提交副本的其他人共享您的分支,请不要这样做**因为使用这样的硬重置将迫使他们必须重新同步他们的工作与新重置科.**对于解决方案,详细说明如何安全地还原提交而不会因硬重置而失去工作,[请参阅此答案](http://stackoverflow.com/a/4114122/456814)**.
- 我第二次@ Cupcake的警告......非常清楚后果.但请注意,如果你真的需要让这些提交永远从历史中消失,那么这个reset + clean方法就可以了,你需要*force*将你修改过的分支推回到任何和所有的遥控器.
- git clean -f DANGER DANGER
- 这会将我的本地副本的头部设置为所需的提交.但后来我无法推动任何变化,因为它在遥控器后面.如果我从遥控器拉出,它最终会回到远程分支上的最新提交处.我如何完全删除(从任何地方)我本地副本上的几个提交已被推送?
- @Ade ..你可以使用`git push -f`标志..但是要小心,它会覆盖遥控器..确保你知道你想要做什么......
在回答之前,让我们添加一些背景,解释这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
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>
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
修改了HEAD
.
- 对git reflog`的极好提示,这正是我所需要的
- @Kokodoko是的,它非常复杂......并且是一个很好的例子,说明专家对刚刚开始的人很少考虑.请参考我的答案,以及我推荐的书.Git不是你可以直观地获取的东西.我绝对可以肯定CodeWizard没有这样做.
- 哎哟! 这一切似乎都非常复杂...难道没有一个简单的命令会让您退后一步吗?就像从项目中的1.1版本回到1.0版本一样?我期望像git stepback_one_commit之类的东西。
如果要"取消提交",擦除最后一次提交消息,并将修改后的文件放回到分段中,则可以使用以下命令:
git reset --soft HEAD~1
-
--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]
然后它将保存您的更改.
- 我在这篇文章中尝试了1/2打的答案,直到我明白了所有其他答案,我的git config在尝试推送时一直给我一个错误。这个答案有效。谢谢!
最好的办法是:
git reset --hard <commidId> && git push --force
这会将分支重置为特定的提交,然后将使用与本地相同的提交上传远程服务器。
请小心使用该--force
标志,因为它会删除所选提交之后的所有后续提交,而没有恢复它们的选项。
我已经尝试了很多方法来恢复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
删除自上次创建的所有新文件提交,因为这是大多数人的期待,我相信恢复到最新提交的时候.
好的,回到以前的git提交很容易......
在不保留更改的情况下还原:
git reset --hard <commit>
通过保留更改来恢复:
git reset --soft <commit>
解释:使用git reset,你可以重置为一个特定的状态,如上所述,它通常使用提交哈希.
但正如你所看到的不同之处在于使用了两个标志,--soft
并且--hard
默认情况下git reset
使用--soft
标志,但是总是使用标志这是一个很好的做法,我解释了每个标志:
- 柔软的
所解释的默认标志,不需要提供它,不会更改工作树,但添加准备提交的所有更改文件,因此您将返回到提交状态,更改为文件将变为未分级.
- 硬
小心这个标志,它重置工作树和跟踪文件的所有更改,一切都将消失!
我还创建了下面的图像,可能发生在使用git的现实生活中:
假设你正在谈论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
我在博客文章中找到了将远程Git仓库删除到特定提交的答案.
- 这个答案与众多其他人的答案有何不同?
- 有关如何解决此问题的大多数其他建议都缺少推送语法。很棒。
除了这个确切的组合,这里没有任何东西对我有用:
git reset --hard <commit_hash>
git push origin <branch_name> --force
这里的关键是强制推送,没有额外的提交/提交消息等.
- 这对我有用,但是你需要小心,因为硬复位后的所有提交历史都会丢失,并且这个动作是不可逆转的.你需要确定你在做什么.
假设您在一个名为~/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 <hash>
超越我.
- 您可以执行`git revert HEAD~3`删除最后3次提交
- @Rod - 不,那不对.该命令将恢复作为HEAD的第三个祖父母(不是最后三个提交)的提交.
- 现在有一种比这样的脚本更简单的**方法,只需使用`git revert --no-commit <start> .. <end>`,因为`git revert`接受一个提交范围新的(或所有?)版本的Git.请注意,范围的起点未包含在恢复中.
- @Rod - 这听起来是对的,肯定是一个丑陋的语法虽然不是吗?我总是找到检查我想要"恢复"的提交,然后提交更直观的提交.
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对Checkout旧提交的解决方案,并使其成为新的提交:
git rm -r .
git checkout <commit> .
git commit
与替代#1类似,这将再现<commit>
当前工作副本中的状态.首先必须这样做,git rm
因为git checkout
不会删除自那以后添加的文件<commit>
.
- @Bogac - 点表示文件路径,在本例中是当前目录,因此假设您正在从工作副本的根目录运行它.
这是一个更简单的方法来回到之前的提交(并让它处于一个不受约束的状态,无论你喜欢什么,都可以使用它):
git reset HEAD~1
所以,不需要提交ID等等:)
有一个命令(不是核心Git的一部分,但它在git-extras包中)专门用于恢复和暂存旧提交:
git back
根据手册页,它也可以这样使用:
# Remove the latest three commits
git back 3
完成所有更改后,当您推送所有这些命令时,您可能必须使用:
git push -f ...
而且不仅如此git push
.
- **强制性警告:如果您与拥有旧提交副本的其他人共享您的分支,请不要这样做**因为使用这样的强制推送会迫使他们重新同步他们的工作.**对于解决方案,详细解释如何安全地恢复提交而不会因强制推动而失去工作,[请参阅此答案](http://stackoverflow.com/a/4114122/456814)**.
- 有时这就是你想要的.示例:已提交并将多个提交推送到错误的分支(分支A).在挑选到分支B之后,我希望从分支A中删除这些提交.我不想恢复,因为当分支A和B合并在一起时,稍后将应用恢复.在分支A中执行重置--hard <commitId>后跟强制推送从分支中删除这些提交,同时在分支B中保留它们.我可以逃避这一点,因为我知道没有其他人在分支A上开发.
您可以自己完成所有这些初始步骤,然后再回到git repo.
-
$ git log -n 4
如果您希望git存储库到先前的提交
git pull --all
git reset --hard HEAD~1
git push --force
恢复到最近的提交并忽略所有本地更改:
git reset --hard HEAD
选择所需的提交,然后进行检查
git show HEAD
git show HEAD~1
git show HEAD~2
直到你得到所需的提交.为了使HEAD指向那个,做
git reset --hard HEAD~1
或git reset --hard HEAD~2
或什么的.
- **强制性警告:如果您与拥有旧提交副本的其他人共享您的分支,请不要这样做**因为使用这样的硬重置将迫使他们必须重新同步他们的工作与新重置科.**对于解决方案,详细说明如何安全地还原提交而不会因硬重置而失去工作,[请参阅此答案](http://stackoverflow.com/a/4114122/456814)**.
如果情况紧急,你只想以快速而肮脏的方式做提问者的问题,假设你的项目在"我的项目"目录下:
-
.../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
然后,您的系统上有两个版本...您可以检查或复制或修改先前提交中感兴趣的文件或其他任何内容.你可以完全放弃"我的项目 - 复制"下的文件,如果你已经确定新的工作无处可去......
很明显,如果你想继续执行项目的状态而不实际丢弃工作,因为这个检索到的提交是重新命名你的目录:删除包含检索到的提交的项目(或给它一个临时名称)并重命名你的"我的项目 - 将"目录复制回"我的项目".然后可能很快就会做另一次提交.
Git是一个出色的创作,但你不能只是"随时拿起它":试图解释它的人也经常假设其他VCS [版本控制系统]的先验知识,并且过早地深入研究,并且犯下其他罪行,比如使用可互换的术语来"退出" - 这种方式有时似乎几乎可以使初学者感到困惑.
为了节省很多压力,你必须要读一本关于Git的书 - 我推荐"使用Git进行版本控制".如果你能信任我(或者更确切地说,我的伤疤),当我说"有",它遵循你还不如做NOW.Git的大部分复杂性来自分支然后重新合并.但是从你的问题来看,人们没有理由为科学致盲.
特别是如果,例如,这是一个绝望的情况,你是Git的新手!
PS:另一个想法:将(现在)将Git存储库("repo")保存在除工作文件之外的目录中实际上非常简单.这意味着您不必使用上述快速和脏的解决方案来复制整个Git存储库.请在此处使用--separate-git-dir 查看 Fryer的答案.但是要注意:如果你有一个你没有复制的"单独目录"存储库,并且你进行了硬复位,那么重置提交之后的所有版本将永远丢失,除非你有绝对应该的,定期备份您的存储库,最好是其他地方的云(例如Google Drive).
要保持从先前提交到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 stash
git stash clear
它直接清除自上次提交以来您所做的所有更改.
PS:它有一点问题; 它还会删除您最近存储的所有存储更改.在大多数情况下,我猜这应该不重要.
我相信有些人可能会想要知道如何回滚他们在他们的主人身上做出的改变 - 即抛弃一切并返回原点/主人,在这种情况下,执行此操作:
git reset --hard origin/master
https://superuser.com/questions/273172/how-to-reset-master-to-origin-master
恢复最近的提交:
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将保留那些"撤消"提交中的所有更改作为本地修改.
在新的本地分支中恢复修订
如上所述,在您的HEAD
分支上使用reset命令是一个非常激烈的操作:它将删除在指定修订之后的任何提交(在此分支上).如果你确定这是你想要的,一切都很好.
但是,如果您希望保持当前的HEAD分支不受影响,还有一种更安全的方法.由于"分支"在Git中非常便宜和容易,我们可以轻松地创建一个从旧版本开始的新分支:
git checkout -b old-project-state 0ad5a7a6
通常,checkout命令用于仅切换分支.但是,提供-b参数,您还可以让它创建一个新分支(在此示例中名为old-project-state).如果您不希望它从当前的HEAD版本开始,您还需要提供一个提交哈希 - 我们要恢复的旧项目修订版.
您现在有了一个名为old-project-state的新分支,它反映了项目的旧版本 - 无需触及甚至删除任何其他提交或分支.
想法:您基本上想用之前提交的状态替换当前的工作树状态,然后从中创建一个提交。最好不要更改被忽略的文件。方法如下:
-
git rm -r --cached . && git clean -f -d
-
git checkout 0d1d7fc3 .
-
git add --all && git commit -m "revert to 0d1d7fc3"
起初我认为Yarins 的答案是最好的,但它不适用于合并提交。这个解决方案确实如此。
此外,它不会从历史记录中删除任何内容(推送或推送)。它产生一个干净的提交,代表我们想要恢复到的状态。
* 通过从工作树中删除未跟踪但未被忽略的文件(在.gitignore 中指定的文件)。工作树是空的,除了我们想要保留的被忽略的文件(如果没有为 指定-x
选项clean
)
** 指定路径时(此处.
:),结帐将单独保留 HEAD。
Revert是回滚提交的命令.
git revert <commit1> <commit2>
样品:
git revert 2h3h23233
它能够从HEAD中获取范围,如下所示.这里1表示"还原最后一次提交".
git revert HEAD~1..HEAD
然后呢 git push
尝试重置为所需的提交 -
git reset <COMMIT_ID>
(检查COMMIT_ID使用git log
)
这会将所有已更改的文件重置为未添加状态.
现在你可以通过checkout
所有未添加的文件
git checkout .
检查git log
以验证您的更改.
UPDATE
如果你有一个并且只在你的回购中提交,请尝试
git update-ref -d HEAD
当你的提交被远程推送时,你需要删除它们.让我假设你的分支正在发展,它被推到原点.
您首先需要从原点中删除develop:
git push origin :develop (note the colon)
然后你需要开发到你想要的状态,让我假设提交哈希是EFGHIJK:
git reset --hard EFGHIJK
最后,推动再次发展:
git push origin develop
我有类似的问题,并希望恢复到早期的提交.在我的情况下,因为我使用过,所以我没有被提交更新的提交Hard
.
我就这样做了:
git reset --hard CommitId && git clean -f
这将在本地存储库上恢复,此处使用git push -f
后将更新远程存储库.
git push -f
如果你想纠正上次提交中的一些错误,那么一个好的选择就是使用git commit --amend命令.如果任何引用都没有指向最后一次提交,那么这将起到作用,因为它创建一个与最后一次提交具有相同父级的提交.如果没有对最后一次提交的引用,它将被简单地丢弃,并且此提交将是最后一次提交.这是在不恢复提交的情况下纠正提交的好方法.但它有其自身的局限性.
在GitKraken你可以这样做:
- 右键单击要重置的提交,选择:重置为此提交/硬盘:
- 再次右键单击提交,选择:当前分支名称/推送:
- 单击强制推送:
OBS.:您需要小心,因为硬重置后的所有提交历史都会丢失,并且此操作是不可逆转的.你需要确定你在做什么.
用于回滚(或恢复):
- git revert --no-commit"commit-code-to-remove"HEAD(例如git revert --no-commit d57a39d HEAD)
- git commit
- git push
尝试以上两个步骤,如果你发现这是你想要的那么git push.
如果你发现错误的话:
首先,获取在某个日期标识提交的字符串,执行:
git rev-list -n 1 --before="2009-07-27 13:37" origin/master
它打印提交标识符,获取字符串(例如XXXX)并执行:
git checkout XXXX
又一个最简单的解决方案; 你必须改变分支才能做到这一点,但之后你可以运行:
git branch -f <<branchname>> 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
- 噢,为什么OP的问题有这么多不同的答案!?不应该退一步是一个简单的过程吗?
使用SourceTree可以轻松完成.只需右键单击您正在寻找的提交,然后从菜单中选择"Checkout".
由于某种原因,我无法手动恢复我,所以这就是我最终如何做到这一点.
- 检查出我想要的分支,复制它.
- 检查出最新的分支机构.
- 将我想要的分支内容复制到最新分支的目录中,覆盖更改并提交.
git reflog
选择git reflog的HEAD的数量,你想要恢复和执行的操作(对于这个例子,我选择12):
git reset HEAD@{12} --hard
将分支恢复到任何特定提交的最简单方法,您无法更改我找到的历史记录:
- 签出您希望还原的提交或分支.
- 编辑.git/HEAD并将ref更改为要还原到的分支.
如:
echo 'ref: refs/heads/example' > .git/HEAD
如果你然后执行git status,你应该看到你所在的分支和你想要恢复的分支之间的所有变化.
如果一切都很好,你可以承诺.你也可以使用git diff revert..example来确保它是一样的.
如果您想暂时还原更改,因为
- 有人提交了代码,它破坏了构建或破坏了您正在使用的功能
您可以使用git log搜索上次工作提交然后运行
git rebase --onto <commitId>
当远程分支再次工作时,您可以
git pull --rebase
对于临时更改,此方法优于git checkout,因为您未处于分离状态.
重置分阶段更改和提交
该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
. 它只是不需要文件或路径即可工作。
您可以--soft
与git reset
. 它将存储库重置为您指定的提交并暂存所有这些更改。您已经暂存的任何更改都不会受到影响,工作树中的更改也不会受到影响。
最后,您可以使用--mixed
重置工作树而无需暂存任何更改。这也会取消暂存任何已暂存的更改。
恢复提交
有时我们会犯错误。不应该共享的提交被推送到公共存储库,提交具有无法修复且需要撤消的错误,或者您可能不再需要该代码。
这些情况都需要git revert
. 该git revert
命令会执行您可能期望的操作。它通过对历史应用反向提交来还原单个提交。
有时您需要还原多次提交才能完全撤消更改。您可以使用-no-commit
,或者您可以使用-n
告诉 Git 执行还原,但不要提交更改。
这使您可以将所有还原提交合并为一个提交,这在您需要还原跨越多个提交的功能时非常有用。确保您以相反的顺序还原提交 - 首先是最新的提交。
否则,您可能会通过尝试恢复尚不存在的代码来混淆 Git。