无法在 git reset --soft HEAD^ 后进行推送

13

刚才我提交并推送了一些东西(是的,我在推送时犯了错误),但我决定应该“撤销”或“回退”。所以我被告知在我的本地执行git reset --soft HEAD^,我想这样会创建一个“撤销”提交,一旦提交,就好像这个更改从未发生过一样。我不介意更改记录在历史记录中,那只是我想象中的情况。

无论如何,这样做之后,我再次提交,然后当我尝试推送时,出现了非快进式错误。现在,我知道我在重置时搞砸了什么,我的树和起源树现在“不匹配”,但我想知道如何解决这个问题。现在,我只想回到重置之前的时间,这样我就可以通过手动取出更改并提交来手动撤销更改,除非有人可以推荐正确的撤销已推送提交的方法,我指的不是要从日志中删除历史记录。

4个回答

16
虽然我的回答超出了您的问题,但我认为这实际上是您想要做的事情。
您使用了“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分支),并确保在团队中有开放交流
开发人员通常会使用此模式来进行所谓的周五下午提交,其中您希望在周末之前保存您的工作以防硬件故障(但在周一返回到预提交状态)。
*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”相比,以这种方式操作的优点在于避免了额外的提交。重置将有两个提交,而这种方法将没有(没有额外的提交)。使用“git reset”的优点是它不会重写历史记录,因此更加安全,特别是如果您不确定自己在做什么时。通常情况下,存储库被配置为不允许您对主分支进行此操作 - 请在分支上进行修复并创建拉取请求。因为如果您已经阅读了上面的链接,则在主分支上重写历史记录将产生严重后果(除非您是唯一克隆该代码的人)。

8
如果我正确理解您的问题,您可以尝试以下操作:
(我假设这是您的“主”分支,并且您正在推送到“origin”)
与远程同步以达到相同状态。
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

5

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

如果你只想取消刚才执行的git reset --soft,你可以在reflogs中查找以前的HEAD提交ID。

 $ git reflog
 $ git reset --soft formerCommit

然后你可以准备使用git revert


谢谢,这与IRC上的某人告诉我的类似,但它相当令人困惑,所以我将采用rnicholson的答案进行文档记录。 - Jorge Israel Peña
1
我之前不熟悉 git reflog。非常酷。学到了新东西。这可能是更好的解决方案,因为它将我的答案的前三个步骤压缩成一个命令。 - rnicholson
我也无法理解这个是如何工作的,我以为 $ git reset --soft formerCommit 之后会回到先前的状态,实际上 HEAD 指向了之前的提交,但是当我尝试推送新更改时,我遇到了与问题中相同的错误,因为 HEAD 已经分叉,所以我不明白其中的优势在哪里? - Arpan Banerjee
1
@ArpanBanerjee 任何将HEAD移动的重置都会导致强制推送。 - VonC

0

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


谢谢,这很有道理,尽管考虑到它并没有真正解决我的问题,这可能更好地作为一条评论。还是谢谢。 - Jorge Israel Peña

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接