如何从错误的git push -f origin master恢复?


Answers:


54

Git通常不会丢弃任何东西,但是从中恢复可能仍然很棘手。

如果您有正确的来源,则可以使用该--force选项将其推入遥控器。除非您告知,否则Git不会删除任何分支。如果您实际上丢失了提交,请查看此有关恢复提交的有用指南。如果您知道想要的提交的SHA-1,那么可能就可以了。

最好的事情:备份所有内容,然后查看本地存储库中仍然存在的内容。如果可能,在遥控器上执行相同的操作。使用git fsck,看看你是否能恢复的东西,最重要的不运行git gc

最重要的是,--force除非您真的很认真,否则不要使用该选项。


64
您很可能只需要查看reflog即可确定远程分支最初所在的位置。例如,git reflog show remotes/origin/master。您应该可以在那里看到您的推送;前一行中的提交是您弄乱之前的位置。然后,您只需将该修订(带有--force)推到原始位置,然后回到原来的位置即可!
卡斯卡贝尔

@大卫:哦。您没有在问题中提到没有回购协议。(当然,这是您永远都不想做的事情。)但是,如果您具有推送到的文件系统访问权限,那么仍然可以在其中进行所有这些操作。
卡斯卡贝尔

1
@戴维:Yikes。最好将当前目录作为提示的一部分来避免这种情况。
卡斯卡贝尔

1
@Jefromi我认为您说的是实际的答案:即使使用旧版本(git fetch很长时间没有编辑),您也可以显示GitHub方面的reflog并进行恢复!
nh2 2012年

1
@Jefromi的答案在哪里?我没有在此评论线程之外看到此页面上提到的用户。
Don McCurdy

47

如果您知道提交哈希,这很简单,只需重新创建分支即可。

5794458...b459f069 master -> master (forced update)

删除远程分支:

git push origin :master

然后使用以下命令重新创建分支:

git checkout 5794458
git branch master
git push origin master

28

解决方案已经在这里提到

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

谢谢,这对我有用。我无权删除母版,因此批准的评论失败。
安迪

是的,git reflog show remotes/origin/master如果有必要使用git reflog(如上面@Cascabel所述)
约德

2
这是正确的答案,感谢您链接到正确的答案。
Noitidart

6

如果您不在强制推送来自的本地回购中,则在原始/主级别上无法恢复。但是,如果您有幸使用GitHubGitHub for Enterprise,可以查看REST API并检索作为补丁的丢失提交,例如:

  1. 列出事件并查找长号提交sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. 下载丢失的提交并在json路径.files [] / patch中检索相关补丁。

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. 在本地申请并再次推送

git apply patch.patch && git commit -m“恢复的提交” && git push原始主机


4

如果先前的推送不是来自本地仓库,则恢复丢失的提交甚至找出丢失的提交的另一种方法是查看CI机器。

如果您有一份应该在每次提交(或一系列连续的提交)之后测试master分支的工作,则可以查看一下它最近一次测试的内容。那就是您需要还原的提交。

CI机器甚至可以保留该存储库的本地克隆,您可以从该克隆中执行此恢复。

来源:可能是持续交付:通过构建,测试和部署自动化来发布可靠的软件(Addison-Wesley签名系列(Fowler))


3

是的,您可以在之后恢复提交 git push -f your_branch

来自Doc的文字

修剪早于指定时间的条目。如果未指定此选项,则到期时间将从配置设置gc.reflogExpire中获取,该设置默认为90天。--expire =所有修剪条目,无论其年龄如何;--expire =从不关闭对可达条目的修剪(但请参阅--expire-unreachable)。

因此,您可以执行以下操作:

1- git reflog

在此处输入图片说明

2-您选择要恢复的Head_Number git reset –hard HEAD@{HEAD-NUMBER}

在此处输入图片说明

3-您可以通过以下方式查看此头上的所有提交 git cherry -v branch_name

4-最后你应该强行推 git push -f branch_name

要么

1-从您的GIT客户端(接口)获取SHA的数量

git reset --hard commit_SHA

2推力

git push -f your_branch

希望这可以帮助


2

我撤消了仅对一个文件的最后一次推送时所做的相同的事情。最终回到存储库的原始状态。我在Linux上拥有本地副本时使用了Linus上的git命令。幸运的是,该副本仍然完好无损。

我所做的只是(疯狂地复制了几个本地仓库后):

git add .
git status

(它说起源/主控先完成68次提交,好吧……这些都是我删除的所有提交)

git remote set-url origin <GIT_SSH_URL>
git push

一切都恢复了我进行强力推动之前的方式。要记住的最重要的事情是永远不要进行git checkout。在您用力推动之后。但是最佳实践是禁用推选项。我再也不会使用它了。学到了我的教训!


0

在这里您可以阅读决策https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

第二个帮助了我。这些命令我做错了

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

在执行这些命令后,我丢失了三个提交。为了恢复它们,我看了看我错误地执行“ git pull”的终端,并且看到那里的输出像

60223bf ... 0b258eb分支->起源/分支

第二个哈希0b258eb正是我需要的。所以,我拿了这个哈希并产生命令

git push --force origin 0b258eb:some-branch

0

对于像我这样的处境非常糟糕的人(例如,如果您bad object在运行时遇到错误git reset --hard):

我写了一个名为treesaver的脚本,作为最后的手段,它从GitHub API提取所有文件。使用方法如下:

  1. 克隆treesaver脚本并对其cd进行克隆。
  2. SHA通过访问找到要还原的树的字符串 https://api.github.com/repos/<your_username_or_org>/<repo>/events
  3. payload与您的推送事件对应的属性中,找到commit您想要还原的事件,然后单击url
  4. 在下面commit.tree,复制treeurl
  5. 运行python3 main.py <tree_url> <path_to_save_to>

例如,就我而言,我将运行:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

当然,欢迎公关。

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.