【问题标题】:Can't Push After git reset --soft HEAD^git reset --soft HEAD^ 后无法推送
【发布时间】:2011-01-02 06:12:57
【问题描述】:

刚才我提交并推送了一些我决定应该“还原”或“撤消”的东西(是的,我在推送上的错误)。所以我被告知要在我的最后发出git reset --soft HEAD^,我认为这会以某种方式创建一个“还原”提交,一旦提交就会使它就像从未发生过变化一样。我不介意改变的历史是否存在,这正是我想象的会发生的事情。

无论如何,在完成之后我再次提交,然后当我尝试推动时,我得到了非快进错误。现在,我知道我在重置时搞砸了,我的树和起源树的某些东西现在“不匹配”,但我想知道如何解决这个问题。现在我只想回到我发出重置之前的时间,这样我就可以通过手动取出更改然后提交来手动恢复更​​改,除非其他人可以推荐恢复推送提交的正确方法,并且通过我并不是说历史必须从日志或任何东西中消失。

【问题讨论】:

    标签: git version-control revert


    【解决方案1】:

    虽然我的回答超出了您的要求,但我认为这实际上是您打算做的。

    您使用git reset --soft HEAD^ 撤消了您所做的提交。这会将工作副本返回到您提交之前的状态(因为HEAD 指向您当前的提交,而HEAD^ 指向之前的提交(假设只有一个父级)。

    但是现在当您git push 时,您会被告知:

     ! [rejected]            <branch> -> <branch>e (non-fast-forward)
    error: failed to push some refs to 'ssh://<remote server>/<remote path>'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    这是说提交没有对齐,它是为了防止你犯错误。错误消息有点误导,您不想按照它的建议去做(拉动以使您的分支同步)。由于您的意图,您只能知道不要这样做。

    您可以通过--force(或-f)(*)轻松解决此问题:

    git push --force
    

    您可能需要再次设置上游:

    git push --force --set-upstream origin <branch>
    

    请注意,如果其他人已经撤消了您的工作,这将产生后果,因为会有不同的提交进行相同的更改(可能)。见https://www.kernel.org/pub/software/scm/git/docs/user-manual.html#problems-With-rewriting-history

    为防止出现任何问题,请只推送到您的分支(而不是某些公共分支 - 例如开发人员将所有功能分支合并到的 development 分支)并确保开放式沟通 在你的团队中。

    开发人员通常会将此模式用于我所说的 Frid​​ay Afternoon 提交,您希望在周末之前保存您的工作以防硬件故障(但返回到星期一的预提交状态)。

    *Friday*
    
    git add --all  # To add all files whether they are tracked or not
    git commit -m "Friday afternoon commit"
    git --set-upstream push      # --set-upstream is for if the branch doesn't exist on the remote server
    
    *Monday*
    
    git reset --soft HEAD^
    git push -f --set-upstream origin <branch>
    

    与另一个答案中讨论的git revert 相比,这样做的好处是避免了额外的提交。重置将有 2 次提交,这种方式将没有(没有额外的)。 git reset 的优点是它不会重写历史记录,因此更安全,尤其是在您不确定自己在做什么的情况下。

    (*) 通常存储库被配置为不允许您这样做以掌握 - 修复分支并创建拉取请求。因为如果你已经阅读了上面的链接,在 master 上重写历史将会产生严重的后果(除非你是唯一一个克隆过该代码的人)。

    【讨论】:

      【解决方案2】:

      如果我正确理解您的问题,您可以尝试以下方法:

      (我假设这是您的“主”分支,而您正在推动“原点”)

      与您的遥控器同步以达到相同的状态。

      git remote update
      git checkout master
      git merge origin/master
      

      现在恢复你的提交

      git revert HEAD (or where ever the commit you want to revert is now)
      git commit -av
      

      与您的遥控器同步

      git push
      

      【讨论】:

        【解决方案3】:

        现在我只想回到我发出重置之前的时间

        如果你只想取消你刚刚做的git reset --soft,你可以在reflogs中查找之前的HEAD commit id

         $ git reflog
         $ git reset --soft formerCommit
        

        然后你就可以准备你的git revert

        【讨论】:

        • 谢谢,这类似于 IRC 上的某个人告诉我要做的事情,但它非常令人困惑,所以我将使用 rnicholson 的答案来进行记录。
        • 我不熟悉 git reflog。很酷。学到了一些新东西。这可能是一个更好的解决方案,因为它浓缩了我对一个命令的回答的前 3 个步骤。
        • 我也无法理解,这是怎么回事,我以为$ git reset --soft formerCommit之后我会回到之前的状态,确实head指向了之前的提交,但是当我试图推送时新的变化我遇到了与问题相同的错误,因为头部已经分歧,所以我不明白这样做的好处是什么?
        • @ArpanBanerjee 任何移动 HEAD 的重置都会导致强制推送。
        【解决方案4】:

        您想使用 git revert HEAD 创建一个新的提交,以撤消 HEAD 上的提交。相反,您只是将 HEAD 移回当前 HEAD 之前的提交。

        【讨论】:

        • 谢谢,这是有道理的,尽管作为评论可能会更好,因为它并不能真正解决我的问题。不过还是谢谢。
        猜你喜欢
        • 2014-08-25
        • 2021-10-22
        • 2019-08-30
        • 2021-10-28
        • 2021-05-14
        • 2012-06-09
        • 1970-01-01
        • 2012-04-05
        相关资源
        最近更新 更多