首页 文章

如何恢复多个git提交?

提问于
浏览
681

我有一个git存储库,看起来像这样:

A -> B -> C -> D -> HEAD

我希望分支的头部指向A,即我希望B,C,D和HEAD消失,我希望头部与A同义 .

听起来我可以尝试改变(不适用,因为我推动了之间的变化),或者还原 . 但是如何恢复多个提交?我一次还原一个吗?订单重要吗?

12 回答

  • 27

    这些都不适合我,所以我有三个提交要求(最后三次提交),所以我做了:

    git revert HEAD
    git revert HEAD~2
    git revert HEAD~4
    git rebase -i HEAD~3 # pick, squash, squash
    

    像魅力一样工作:)

  • 1

    首先要确保您的工作副本未被修改 . 然后:

    git diff HEAD commit_sha_you_want_to_revert_to | git apply
    

    然后只是提交 . 不要忘记记录恢复的原因 .

  • 4

    与Jakub的答案类似,这使您可以轻松选择要还原的连续提交 .

    # revert all commits from B to HEAD, inclusively
    $ git revert --no-commit B..HEAD  
    $ git commit -m 'message'
    
  • 50

    为此,您只需使用revert命令,指定要恢复的提交范围 .

    考虑到你的例子,你必须这样做(假设你在分支'master'):

    git revert master~3..master
    

    这将在您的本地创建一个新的提交,使用B,C和D的反向提交(意味着它将撤消这些提交引入的更改):

    A <- B <- C <- D <- BCD' <- HEAD
    
  • 172

    在我看来,一个非常简单和干净的方式可能是:

    回到A

    git checkout -f A
    

    点主人的头到现在的状态

    git symbolic-ref HEAD refs/heads/master
    

    保存

    git commit
    
  • 19

    如果要暂时还原功能的提交,则可以使用以下一系列命令 .

    Here is how it works

    git log --pretty = oneline | grep'feature_name'| cut -d'' - f1 | xargs -n1 git revert --no-edit

  • 85

    干净的方式,我发现有用

    git revert --no-commit HEAD~3..
    

    此命令仅使用一次提交恢复最后3次提交 .

    也不会重写历史记录 .

  • -4

    这是Jakub答案中提供的解决方案之一的扩展

    我面临的情况是,我需要回滚的提交有点复杂,其中几个提交是合并提交,我需要避免重写历史记录 . 我无法使用一系列 git revert 命令,因为我最终遇到了添加的回归更改之间的冲突 . 我最终使用了以下步骤 .

    首先,检查目标提交的内容,同时将HEAD留在分支的顶端:

    $ git checkout -f <target-commit> -- .
    

    (确保 <target-commit> 被解释为提交而不是文件; . 指向当前目录 . )

    然后,确定在回滚的提交中添加了哪些文件,因此需要删除:

    $ git diff --name-status --cached <target-commit>
    

    添加的文件应该在行的开头显示“A”,并且不应存在其他差异 . 现在,如果需要删除任何文件,请暂存这些文件以进行删除:

    $ git rm <filespec>[ <filespec> ...]
    

    最后,提交reversion:

    $ git commit -m 'revert to <target-commit>'
    

    如果需要,请确保我们恢复到所需的状态:

    $git diff <target-commit> <current-commit>
    

    应该没有差异 .

  • 5

    我只是回答了 . 其他所有问题都与如何正确还原和保存历史有关 . 这个问题说“我希望分支的负责人指向A,即我想要B,C,D和HEAD到 disappear ,我希望头部与A同义” .

    git checkout <branch_name>
    git reset --hard <commit Hash for A>
    git push -f
    

    我学到了很多阅读Jakub的帖子,但该公司的一些人(可以通过推送到我们的“测试”分支而没有Pull-Request)推动了5次糟糕的提交,试图修复并修复并修复了他5次提交之前的错误 . 不仅如此,还接受了一两个Pull请求,现在已经很糟糕了 . 所以忘掉它,我找到了最后一个好的提交(abc1234)并且只运行了基本脚本:

    git checkout testing
    git reset --hard abc1234
    git push -f
    

    我告诉在这个回购中工作的其他5个人,他们最好记录他们在过去几个小时内的变化以及最新测试中的Wipe / Re-Branch . 故事的结局 .

  • 1004

    扩展我在评论中写的内容

    一般规则是您不应该重写(更改)您已发布的历史记录,因为有人可能将其工作基于它 . 如果您重写(更改)历史记录,则会出现合并其更改以及更新这些更改的问题 .

    所以解决方案是创建一个你想要摆脱的新提交 reverts changes . 您可以使用git revert命令执行此操作 .

    您有以下情况:

    A <-- B  <-- C <-- D                                               <-- master <-- HEAD
    

    (此处的箭头指的是指针的方向:提交时的“父”引用,分支头(分支引用)情况下的顶部提交,以及HEAD引用的分支名称) .

    您需要创建的内容如下:

    A <-- B  <-- C <-- D <-- [(BCD)^-1]                   <-- master <-- HEAD
    

    其中“[(BCD)^ - 1]”表示恢复提交B,C,D中的更改的提交 . 数学告诉我们(BCD)^ - 1 = D ^ -1 C ^ -1 B ^ -1,所以您可以使用以下命令获取所需的情况:

    $ git revert --no-commit D
    $ git revert --no-commit C
    $ git revert --no-commit B
    $ git commit -m "the commit message"
    

    替代解决方案是提交A的checkout内容,并提交此状态:

    $ git checkout -f A -- .
    $ git commit -a
    

    那么你会遇到以下情况:

    A <-- B  <-- C <-- D <-- A'                       <-- master <-- HEAD
    

    提交A'与提交A具有相同的内容,但是是不同的提交(提交消息,父项,提交日期) .

    solution by Jeff Ferland, modified by Charles Bailey基于相同的想法,但使用git reset

    $ git reset --hard A
    $ git reset --soft @{1}  # (or ORIG_HEAD), which is D
    $ git commit
    
  • 0

    在共享存储库上恢复一组提交的简单方法(人们使用并且您希望保留历史记录)是将 git revert 与git rev-list 结合使用 . 后者将为您提供一个提交列表,前者将自行恢复 .

    有两种方法可以做到这一点 . 如果您希望在单个提交中恢复多个提交,请使用:

    for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done
    

    这将恢复您需要的一组提交,但是将所有更改保留在工作树上,您应该照常提交它们 .

    另一个选择是每个还原的更改都有一个提交:

    for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done
    

    例如,如果你有一个提交树

    o---o---o---o---o---o--->    
    fff eee ddd ccc bbb aaa
    

    要将更改从eee还原为bbb,请运行

    for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
    
  • 42
    git reset --hard a
    git reset --mixed d
    git commit
    

    这将立刻成为所有人的回复 . 给出一个好的提交消息 .

相关问题