撤消“ git push”


591

这是我在应该稳定的分支上所做的工作...

% git rebase master
First, rewinding head to replay your work on top of it...
Fast-forwarded alpha-0.3.0 to master.
% git status
# On branch alpha-0.3.0
# Your branch is ahead of 'origin/alpha-0.3.0' by 53 commits.
#
nothing to commit (working directory clean)
% git push
Fetching remote heads...
  refs/
  refs/heads/
  refs/tags/
  refs/remotes/
'refs/heads/master': up-to-date
updating 'refs/heads/alpha-0.3.0'
  from cc4b63bebb6e6dd04407f8788938244b78c50285
  to   83c9191dea88d146400853af5eb7555f252001b0
    done
'refs/heads/unstable': up-to-date
Updating remote server info

后来我才意识到那是个错误。我想撤消整个过程,并将alpha-0.3.0分支还原为原来的样子。

我该怎么办?



4
情况并非完全相同,撤消rebase是本地存储库方案,撤消git push涉及远程存储库,并且根据您具有的访问权限可能更棘手。
CB Bailey

斯汀-你是对的-我可能应该猜到。我认为所有来自的受祝福的存储库更多是一个管理任务,因此属于这里,一般的客户端git是一个stackoverflow问题。
赛勒斯(Cyrus)

快速澄清-我猜测如果您通过部分哈希值引用git commit ,则git会假设您正在谈论的哈希以该字符串开头的提交?
Gershom

Answers:


942

您需要确保此存储库中没有其他用户正在提取不正确的更改或尝试在要删除的提交之上构建,因为您将要倒带历史记录。

然后,您需要“强制”推送旧参考。

git push -f origin last_known_good_commit:branch_name

还是你的情况

git push -f origin cc4b63bebb6:alpha-0.3.0

您可能已经receive.denyNonFastForwards在远程存储库上进行了设置。如果是这种情况,那么您会得到一个错误,其中包括短语[remote rejected]

在这种情况下,您将必须删除并重新创建分支。

git push origin :alpha-0.3.0
git push origin cc4b63bebb6:refs/heads/alpha-0.3.0

如果这不起作用-可能是因为您已receive.denyDeletes设置,则必须直接访问存储库。然后,在远程存储库中,您必须执行类似以下管道命令的操作。

git update-ref refs/heads/alpha-0.3.0 cc4b63bebb6 83c9191dea8

16
完美且经过充分说明的回复-非常感谢。对于任何偶然发现此问题的人,出于学术原因,我尝试了前两种方法,并且都有效-显然,如果第一种方法可行,那是最干净的方法。如果我让你比查尔斯高十倍,我会的。:)
赛勒斯(Cyrus)

139
为了快速参考,此处的第一行是git push -f origin last_known_good_commit:branch_name
philfreo 2011年

5
git push -f origin cc4b63bebb6:alpha-0.3.0 =>这帮助了我,请注意alpha-0.3.0是分支名称,cc4b63bebb6是我们希望恢复使用的提交ID。因此,执行此命令后,我们将进入cc4b63bebb6提交ID。
kumar

22
如果您在共享存储库中工作,则此解决方案非常危险。作为最佳实践,应将所有提交到共享的远程仓库的提交视为“不可变的”。使用'git的恢复',而不是:kernel.org/pub/software/scm/git/docs/...
Saboosh

1
jww-与其他所有功能相比,git是可用的功能最丰富,最有效的源代码控制工具。每个团队使用它的方式都不同。值得度过一个周末玩一个新的存储库并经历所有常见情况。一旦花了一些时间使用它,开发的压力就会大大减轻。
user1491819

165

我相信您也可以这样做:

git checkout alpha-0.3.0
git reset --hard cc4b63bebb6
git push origin +alpha-0.3.0

这与最后一种方法非常相似,不同之处在于您不必在远程仓库中乱搞。


9
这对我也同样有效,但是值得注意的是,这将“重写”遥控器上的历史记录。这可能是您想要的,但可能不是!
汤姆(Tom)

3
为这个答案+1确实帮了我大忙。我还想添加(并使事情变得清楚),提交ID(位于“ --hard”参数之后)应该是要将分支重置为的任何提交的ID。
Michael Dautermann 2012年

1
很好地重写历史记录……任何可以撤消更改的人,我只是确保他们做了一次更改,git reset --hard [commit_id]所以我们不会弄乱时空连续体。
外星人生命表格

9
“ git push origin + alpha-0.3.0”中的+是什么?
jpierson

1
@jpierson +强制进行推送,类似于-f(但略有不同:stackoverflow.com/a/25937833/1757149)。如果没有它,如果尝试尝试git push origin alpha-0.3.0,将失败:Updates were rejected because the tip of your current branch is behind
A__18年

106

git revert 比此处建议的某些方法危险性小:

prompt> git revert 35f6af6f77f116ef922e3d75bc80a4a466f92650
[master 71738a9] Revert "Issue #482 - Fixed bug."
 4 files changed, 30 insertions(+), 42 deletions(-)
prompt> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
prompt>

用您自己的提交替换35f6af6f77f116ef922e3d75bc80a4a466f92650


2
如何提供35f6af6f77f116ef922e3d75bc80a4a466f92650 ID?如果您能解释的话,这个答案会更好。
Volomike

2
@Volomike(以及未来的Googling开发人员),此问题描述了许多获取方法:SO上的版本控制和哈希问题
Jaime

这是正确的答案,因为使用“ git reset”,您将无法进行推送(更新被拒绝,因为当前分支的尖端位于其远程副本的后面),或者您需要强制执行并非真正干净的拉取。
Thomas Decaux 2014年

这为我工作。但是,请小心,因为还原将还原本地文件中的所有更改。
user1941537

我选择了这种方法多次,但是我也使用git rebase -i <id-before-last-good-commit>进行交互式的基准调整,并按照此处的建议清理历史记录stackoverflow.com/questions/5189560/…
Ernesto Allely


32

一种不丢失所需更改的方法:

git reset cc4b63b 
git stash
git push -f origin alpha-0.3.0
git stash pop

然后,您可以选择要推送的文件


19

另一种方法是:

  1. 创建另一个分支
  2. 使用“ git checkout”检出该分支上的先前提交
  3. 推动新分支。
  4. 删除旧分支并推动删除(使用 git push origin --delete <branch_name>
  5. 将新分支重命名为旧分支
  6. 再次推动。

2
当您在回购中已经有错误的提交时,这看起来是一个真正的解决方案
Illarion Kovalchuk 2012年


11

撤消多次提交git reset --hard 0ad5a7a6(仅提供提交SHA1哈希)

撤消上一次提交

git reset --hard HEAD〜1(对上一次提交的更改将被删除)git reset --soft HEAD〜1(对上一次提交的更改将作为未提交的本地修改提供)


9

方案1:如果您要撤消上一次提交,请说8123b7e04b3,下面是命令(这对我有用):

git push origin +8123b7e04b3^:<branch_name>

输出如下所示:

Total 0 (delta 0), reused 0 (delta 0)
To https://testlocation/code.git
 + 8123b7e...92bc500 8123b7e04b3^ -> master (forced update)

附加信息: 场景2:在某些情况下,您可能希望通过上一个命令还原刚刚撤消的操作(基本上是撤消撤消操作),然后使用以下命令:

git reset --hard 8123b7e04b3

输出:

HEAD is now at cc6206c Comment_that_was_entered_for_commit

更多信息在这里:https : //github.com/blog/2019-how-to-undo-almost-anything-with-git


方案1应该是可接受的答案,因为问题未指定要删除的提交。接受的答案只会删除最后的提交。该答案将删除所有提交。
多米尼克·塞里萨诺

0

现有的答案是正确的,但是,如果需要撤消pushbut ,该怎么办:

  1. 您想要将提交保留在本地,或者想要保留未提交的更改
  2. 您不知道您刚刚推送了多少个提交

使用此命令将更改还原为参考:

git push -f origin refs/remotes/origin/<branch>@{1}:<branch>

-2

如果要忽略刚刚推送到远程分支中的最后一个提交:这不会删除该提交,而只是通过将git指针移至更早的提交(由HEAD ^或HEAD ^ 1引用)来忽略它。

git push origin +HEAD^:branch

但是,如果您已经推送了此提交,而其他人已经撤消了分支。在这种情况下,不希望重写分支的历史记录,而应该还原此提交:

git revert <SHA-1>
git push origin branch

1
是!使用github时,这就像一个魅力。谢谢。
cukabeka

问题是关于“推送”的,然后它涉及Remote分支。不移动HEAD一次提交,这意味着忽略上次提交的提交,只需执行以下操作:git push origin + HEAD ^:your_branch
mkebri
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.