当前位置 : 首页 » 互动问答 » 正文

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

分类 : 互动问答 | 发布时间 : 2010-11-07 00:58:14 | 评论 : 30 | 浏览 : 4452136 | 喜欢 : 6184

如何从当前状态恢复为在某个提交上创建的快照?

If I do git log,然后我得到以下输出:

 $ git log
提交a867b4af366350be2e7c21b8de9cc6504678a61b`
作者:我<me@me.com>
日期:星期四11月4日18:59:41 2010 -0400

等等等等等等...

提交25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
作者:我<me@me.com>
日期:星期四11月4日05:13:39 2010 -0400

更多等等等等......

提交0766c053c0ea2035e90f504928f8df3c9363b8bd
作者:我<me@me.com>
日期:星期四11月4日00:55:06 2010年 -  0400年

还有更多等等......

提交0d1d7fc32e5a947fbd92ee598033d85bfc445a50
作者:我<me@me.com>
日期:11月3日星期三23:56:08 2010 -0400

是的,更多等等等等。

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

回答(30)

  • 1楼
  • 这很大程度上取决于你所说的“revert”。

    暂时切换到另一个提交

    如果你想暂时回到它,傻瓜,然后回到原来的地方,你需要的只是do是检查所需的提交:

    #这将分离你的HEAD,也就是说,让你没有检出分支:
    git checkout 0d1d7fc32
    

    或者如果你想在那里进行提交,请在你做的时候继续创建一个新的分支:

     git checkout -b old-state 0d1d7fc32
    

    要回到原来的位置,只需查看您再次访问的分支。 (如果你做了更改,就像转换分支时一样,你必须在适当的时候处理它们。你可以重置它们扔掉它们;你可以藏匿,结账,存放pop以带走它们;你可以提交如果你想要一个分支那里,他们到那里的一个分支。)

    硬删除未发布的提交

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

    #这将破坏任何本地修改。
    #如果您想要保留未提交的作品,请不要这样做。
    git reset --hard 0d1d7fc32
    
    #或者,如果有工作需要保留:
    git stash
    git reset --hard 0d1d7fc32
    git stash pop
    #这将保存修改,然后在重置后重新应用该修补程序。
    #如果你修改过的东西,你可能会遇到合并冲突
    #自您重置的提交后更改。
    

    如果你陷入困境,你已经抛弃了你的本地更改,但你至少可以通过重新设置来回到原来的位置。

    用新提交撤消已发布的提交

    另一方面如果您已经发布了这项工作,您可能不想重置分支,因为这有效地重写了历史记录。在这种情况下,您确实可以还原提交。使用Git,revert有一个非常具体的含义:使用反向补丁创建一个提交以取消它。这样您就不会重写任何历史记录。

    #这将创建三个单独的恢复提交:
    git revert a867b4af 25eee4ca 0766c053
    
    #它也需要范围。这将恢复最后两次提交:
    git revert HEAD~2..HEAD
    
    #Similarly,您可以使用提交哈希值恢复一系列提交:
    git还原a867b4af..0766c053
    
    #恢复合并提交
    git revert -m 1 <merge_commit_sha>
    
    #要获得一个,你可以使用`rebase -i`来压扁它们
    #或者,你可以手动完成(确保在回购的顶层做到这一点)
    #将索引和工作树置于所需状态,而不更改HEAD:
    git checkout 0d1d7fc32。
    
    #然后提交。一定要写一个好消息来描述你刚刚做了什么
    git commit
    

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

    如果你决定你不想恢复,你可以恢复恢复(如这里所述)或重置回到之前恢复(参见上一节)。

    在这种情况下,您可能也会发现这个答案很有用:
    如何将HEAD移回以前的位置? (独立头)

  • 2楼
  • 将工作副本还原为最近提交

    要还原为先前的提交,请忽略所有更改:

     git reset --hard HEAD
    

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

    将工作副本还原为较旧的提交

    要还原为比最近提交更早的提交:

    #将索引重置为以前的提交;用您的提交代码替换'56e05fced'
    git reset 56e05fced
    
    #将指针移回前一个HEAD
    git reset --soft HEAD @ {1}
    
    git commit -m“还原到56e05fced”
    
    #更新工作副本以反映新提交
    git reset --hard
    

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

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

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

    这会将HEAD中的所有内容还原为提交哈希值,这意味着它将在工作树中重新创建提交状态as if每次提交以来都已经退回。然后,您可以提交当前树,它将创建一个全新的提交,基本上等同于您“恢复”的提交。

    (The - no-commit 标志允许git立即恢复所有提交 - 否则,系统会提示您为该范围内的每个提交发送一条消息,并使用不必要的新提交乱丢您的历史记录。)

    This is a 回滚到以前状态的安全且简单的方法。没有历史记录被破坏,因此它可以用于已经公开的提交。

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

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

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


    Note : 正如评论中所提到的那样,如果你与拥有旧提交副本的其他人共享你的分支,那么就不要这样做

    同样来自评论,如果你想减少'ballzy'方法你可以使用

    git clean -i

  • 5楼
  • 在回答之前,让我们添加一些背景,解释一下这个HEAD is.

    首先是什么是HEAD?

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

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


    分离的HEAD

    如果你没有进行最新的提交 - 意味着HEAD指向历史记录中的先前提交,它被称为分离的HEAD .

    Enter image description here

    在命令行上它将如下所示 - SHA-1而不是分支名称,因为HEAD没有指向当前分支的尖端:

    Enter image description here


    关于如何从分离的HEAD中恢复的一些选项:


    git checkout

     git checkout <commit_id>
    git checkout -b <新分支> <commit_id>
    git checkout HEAD~X // x是返回的提交数
    

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

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

     #Checkout给定的提交。
    #这样做会导致`分离的HEAD`表示`HEAD`
    #没有指向最新的,所以你需要结帐分支
    #以便能够更新代码。
    git checkout <commit-id>
    
    #创建一个分叉到给定提交的新分支
    git checkout -b <分支名称>
    

    git reflog

    您始终可以使用reflog as well. git reflog将显示更新HEAD的任何更改,并且检出所需的reflog条目会将HEAD设置回此提交。

    每次修改HEAD时,都会是reflog

     git reflog中的新条目
    git checkout HEAD @ {...}
    

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

    Enter image description here


    git reset HEAD --hard <commit_id>

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

    #这将破坏任何本地修改。
    #如果您想要保留未提交的作品,请不要这样做。
    git reset --hard 0d1d7fc32
    
    #或者,如果有工作需要保留:
    git stash
    git reset --hard 0d1d7fc32
    git stash pop
    #这将保存修改,然后在重置后重新应用该修补程序。
    #如果你修改过的东西,你可能会遇到合并冲突
    #自您重置的提交后更改。
    
    • Note: (自Git 2.7 )你也可以使用 git rebase --no-autostash as well.

    这个模式说明了哪个命令做了什么。你可以看到 reset && checkout modify the HEAD.

    Enter image description here

  • 6楼
  • 如果你想“取消提交”,删除最后一次提交消息,并将修改后的文件放回到分段中,你可以使用命令:

     git reset --soft HEAD~1
    
    • --soft表示未提交的文件应保留为与--hard相对的工作文件,这将丢弃它们。
    • HEAD~1是最后一次提交。如果要回滚3次提交,可以使用HEAD~3。如果要回滚到特定的修订版号,也可以使用其SHA哈希来执行此操作。

    这是一个非常有用的命令,在您提交错误的内容并且想要撤消上次提交时。

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

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

     git add。 && git checkout master -f
    

    简短描述:

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

    我找到了一种更方便,更简单的方法来实现上述结果:< notranslate> git add。 && git reset --hard HEAD

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

    它与boulder_ruby建议的代码相同,但我添加了

    来擦除自上次提交以来创建的所有新文件,因为这是最人们希望我相信在恢复到最新提交时。git add . before git reset --hard HEAD git reset --hard HEAD

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

     git reset --hard [之前的提交SHA ID]
    git push origin [分支名称] -f
    

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

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

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

    然后它将保存您的更改。

  • 9楼
  • 假设您在名为〜/ commits-to-revert.txt (I used git log --pretty = oneline 的文本文件中进行以下提交以获取它们)

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

    Create a Bash用于还原每个脚本的shell脚本:

    #!/ bin / bash
    cd / path / to / working / copy
    我在`cat~ / commits-to-revert.txt`中
    做
        git revert $ i --no-commit
    DONE
    

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

  • 10楼
  • Jefromi解决方案的替代品

    Jefromi的解决方案绝对是最好的,你绝对应该使用它们。但是,为了完整起见,我还想展示这些其他替代解决方案,这些解决方案也可用于恢复提交(在某种意义上,你创建一个新的提交撤消先前提交中的更改,就像git revert does).

    要清楚,这些替代不是最好的方法还原提交, Jefromi的解决方案是,但我只想指出您也可以使用这些其他方法来实现同样的事情,因为git revert.

    备选方案1:硬重置和软重置

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

     #将索引重置为所需的提交
    git reset --hard <commit>
    
    #将分支指针移回上一个HEAD
    git reset --soft HEAD @ {1}
    
    #提交更改
    git commit -m“恢复为<commit>”
    

    这基本上是通过使用软重置将在索引/暂存区域中保留先前提交的状态的事实来实现的,然后您可以提交。

    备选2:删除当前树并替换为New One

    此解决方案来自svick对 Checkout旧提交的解决方案,并使其成为新提交:

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

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

  • 11楼
  • Here is a 更简单返回上一次提交的方式(让它处于一种不受约束的状态,无论你喜欢什么,都可以使用它):

     git reset HEAD~1
    

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

  • 12楼
  • OK,回到之前的git提交非常简单...

    恢复而不保留更改:

     git reset --hard <commit>
    

    恢复保持更改:

     git reset --soft <commit>
    

    Explain:使用git reset,您可以重置为特定状态,如上所述,它通常使用提交哈希。

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


    --soft

    默认标志,如解释,而不是需要提供它,不会更改工作树,但添加准备提交的所有更改文件,因此您将返回到提交状态,该更改为文件的未提交状态。


    --hard

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


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

    git reset to a commit

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

     #Revert local master branch to November 3rd commit ID
    git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
    
    #将远程主分支恢复为11月3日的提交ID
    git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master
    

    我在博客文章中发现了答案将远程Git repo删除到特定提交.

  • 14楼
  • 除了这个确切的组合之外,这里没有任何东西对我有用:

     git reset --hard <commit_hash>
    git push origin <branch_name> --force
    

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

  • 15楼
  • 完成所有更改后,当您推送所有这些命令时,您可能必须使用:

     git push -f ...
    

    不仅如此git push.

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

    git back
    

    Per the man page,它也可以这样使用:

    #删除最新的三个提交
    git back 3
  • 17楼
  • 选择所需的提交,并通过

     git show HEAD进行检查
    git show HEAD~1
    git show HEAD~2
    

    直到您获得所需的提交。要使HEAD指向,请执行

     git reset --hard HEAD~1
    

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

  • 18楼
  • Revert to 最近提交并忽略所有本地更改:

     git reset --hard HEAD
  • 19楼
  • 要保持从先前提交到HEAD的更改并移至上一次提交,请执行:

     git reset <SHA>
    

    如果从先前提交到HEAD不需要更改并且只丢弃所有更改,请执行:

     git reset --hard <SHA>
  • 20楼
  • 为了完全清除编码器目录中的一些意外更改,我们使用了:

     git add -A。
    git reset --hard HEAD
    

    Just git reset --hard HEAD 将摆脱修改,但它不会摆脱“新”文件。在他们的情况下,他们意外地随机拖动了一个重要的文件夹,所有这些文件被Git视为新文件,所以 reset --hard 没有修复它。通过预先运行 git add -A。,它使用git显式跟踪它们,以便通过重置来消除。

  • 21楼
  • 这是直接重置为最近提交

     git stash的另一种方法
    git stash clear
    

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

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

  • 23楼
  • 您可以自己完成所有这些初始步骤并返回到git repo。

    1. 使用以下方法从Bitbucket中提取最新版本的存储库 git pull --all command.

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

      $ git log -n 4

    3. 使用 git reset --hard HEAD~N 重置存储库历史记录的头部N是您想要退回的提交数。在下面的示例中,头部将被设置为一个 提交,到存储库历史记录中的最后一次提交:

    4. 使用 git push --force 将更改推送到git repo以强制推送 更改。

    如果你想要git存储库到之前的提交

     git pull --all
    git reset --hard HEAD~1
    git push --force
  • 24楼
  • Revert是回滚提交的命令。

     git revert <commit1> <commit2>
    

    Sample:

    git revert 2h3h23233

    它能够从HEAD中获取范围,如下所示。这里1说“恢复最后一次提交。”

    git revert HEAD~1..HEAD

    然后再做git push

  • 25楼
  • 如果情况是urgent one,并且您只想以快速和脏的方式执行提问者所要求的,假设您的项目位于“我的项目”目录下:

    1. 复制整个目录并将其称为其他内容,例如“我的项目 - 复制”

    2. Do:

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

    您的系统上有两个版本...您可以检查或复制或修改先前提交中感兴趣的文件或其他任何内容。你可以完全丢弃“我的项目 - 复制”下的文件,如果你已经决定新的工作无处可去......

    如果你想继续进行项目的状态而不实际丢弃工作,这是显而易见的事情因为这个检索到的提交是再次重命名你的目录:删除包含检索到的提交的项目(或给它一个临时名称)并将你的“我的项目 - 复制”目录重命名回“我的项目”。然后可能很快就会做另一次提交。

    Git是一个出色的创作,但你不能只是“随时拿起它”:也试图解释它的人经常假设其他VCS的先验知识[版本控制系统]并且过早地钻研太深,并犯下其他罪行,比如使用可互换的术语来“退出” - 这种方式有时似乎几乎可以使初学者感到困惑。

    为了节省很多压力,你必须要读一本关于Git的书 - 我建议“用Git进行版本控制”。如果你说“必须”时你可以相信我(或者更确切地说是我的伤疤),那么你可能会这样做NOW。 Git的大部分复杂性来自分支然后重新合并。但是从你的问题来看,没有理由为什么人们应该用科学来炫耀你.

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

    PS:另一个想法:将Git存储库(“repo”)保存在除工作文件之外的目录中(实际上)非常简单。这意味着你不必使用上面的快速和脏的解决方案来复制整个Git存储库。请参阅Fryer使用--separate-git-dir here. Be warned的答案,但是:如果您有一个“单独目录”存储库,您不复制,并且您执行硬重置,则重置提交后的所有版本将会永远丢失,除非您有绝对应该定期备份您的存储库,最好是其他地方的云(例如 Google Drive)。

  • 26楼
  • 尝试重置为所需的提交 -

    git reset <COMMIT_ID>

    (检查COMMIT_ID使用git log)

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

    现在您可以checkout all un-通过

    git checkout。

    Check git log添加文件以验证您的更改。

    UPDATE

    如果您的回购中有一个而不是提交,请尝试

    git update-ref -d HEAD

  • 27楼
  • 当你的提交被远程推送时,你需要删除它们。让我假设您的分支正在发展并且它被推到原点。

    您首先需要从原点删除develop:

     git push origin:develop(注意冒号)
    

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

     git reset --hard EFGHIJK
    

    最后,再次推动发展:

     git push origin develop
  • 28楼
  • 如果要在上次提交中更正某些错误,则可以使用 git commit --amend命令。如果任何引用都没有指向最后一次提交,那么这将起到作用,因为它创建一个与最后一次提交具有相同父级的提交。如果没有对最后一次提交的引用,它将被简单地丢弃,并且此提交将是最后一次提交。这是在不恢复提交的情况下纠正提交的好方法。但它有其自身的局限性。

  • 29楼
  • Caution!如果用户错误地提交了错误的提交,则此命令可能导致丢失提交历史记录。总是有你的git的额外备份   如果你犯错误,还有其他地方,比你更安全一些。   :)

    我有类似的问题,并希望恢复到早期的提交。在我的情况下,我没有进行更新的提交,因此我使用Hard.

    这就是我做的方式:

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

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

     git push -f
  • 30楼
  • 首先,在某个日期获取标识提交的字符串,执行:

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

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

     git checkout XXXX

相关阅读:

Why should I use core.autocrlf=true in Git?

Force "git push" to overwrite remote files

Update Git branches from master

Undo a Git merge that hasn't been pushed yet

How can I delete a file from git repo?

Git fetch remote branch

How do you clone a Git repository into a specific folder?

Reset or revert a specific file to a specific revision using Git?

View the change history of a file using Git versioning

Difference between "git add -A" and "git add ."