手一抖就敲了 git push -f,刷新远程仓库一看,代码乱了套,刚才同事提交的功能好像没了 —— 心里咯噔一下,冷汗都下来了,这可咋整?撤销操作能行吗?别急,小编前阵子就犯过这错,折腾了半天才弄明白咋恢复,今天就把方法拆解开,不管你是本地有记录还是啥都没了,都能找到招儿,一起往下看吧!
基础问题:撤销到底在撤销啥?
先得弄明白,git push -f 之后的 “撤销”,其实不是真的把 “强制推送” 这个动作删掉,而是把远程仓库的代码恢复到推送之前的状态。就像你不小心把共享文档改乱了,撤销就是把文档还原成昨天的版本,而不是让 “改乱” 这事没发生过。
为啥能撤销呢?因为 Git 这东西特鸡贼,不管你咋折腾,只要提交过的代码,一般都会留个 “备份”,藏在版本历史里。咱们要做的,就是找到那个 “备份”,再把它放回去。
那要是不撤销会咋样?轻的话,同事发现代码没了,得花时间重写;重的话,要是丢的是关键功能代码,可能影响项目进度,严重的还得全组加班找回来 —— 小编上次就因为这事儿,被组长盯着加了两天班,可别学我。
场景问题:不同情况,咋找恢复的 “线索”?
情况 1:本地还能找到推送前的版本(最幸运的情况)
如果你刚推完没多久,本地还没删记录,那恢复起来最简单。
- 第一步:找版本号。打开命令行,敲
git reflog
,这命令能列出你本地所有操作,像个 “操作日志本”。找 “git push -f” 前面那行,后面跟着的长串字母数字(比如 a1b2c3d)就是推送前的版本号,记下来,前 7 位就行。 - 第二步:切到那个版本。敲
git checkout 版本号
,比如git checkout a1b2c3d
,这时候你本地代码就回到推送前了,赶紧看看对不对。 - 第三步:推回远程。确认没问题,敲
git push origin 你的分支名 --force
—— 哎,这里又用了 –force?没办法,因为远程现在是被你改乱的版本,得再强制推一次正确的回去。但这次别怕,你推的是正确版本啊。
小编提醒:这步做完,最好去远程仓库看看,确认代码回来了再松口气。
情况 2:本地记录被清了,咋办?
有时候清理过本地缓存,git reflog
里找不到记录了,别慌,远程仓库可能还有 “痕迹”。
- 第一步:找远程的历史。敲
git ls-remote --tags origin
,这命令能列出远程仓库的标签和版本号,慢慢翻,找你觉得可能是正确版本的号。 - 第二步:拉取那个版本。敲
git fetch origin 版本号:新分支名
,比如git fetch origin a1b2c3d:recover-branch
,意思是把远程的 a1b2c3d 版本拉到本地新分支 recover-branch 里。 - 第三步:检查并推送。切到新分支看看代码对不对,对的话就
git push origin 新分支名
,再合并回主分支就行。
这方法慢点,但总比没招儿强,小编上次本地记录没了,就是这么扒拉回来的。
情况 3:啥记录都没了,只能求助 “外援”
要是上面两招都不管用,就得找团队里的人帮忙了。
- 问问同事:有没有人最近拉过远程仓库的代码?让他把自己本地的版本号发给你,你用他的版本号恢复。
- 找仓库管理员:大公司的 Git 仓库一般有备份,联系管理员查查推送前的版本,他们能帮你恢复。
别不好意思问,代码丢了是大事,大家都会帮你的 —— 小编上次就是隔壁组的老周给了版本号,才搞定的。
解决方案:不想再犯?这几招得记牢
- 少用 git push -f:非用不可的时候,先问自己三遍 “真的必须用吗?”,确认没人动过分支再用。
- 推前先备份:用
git branch 备份分支名
建个备份,比如git branch backup-before-force
,万一错了还有退路。 - 用更安全的命令:
git push --force-with-lease
比-f
好,它会先检查远程有没有新提交,有就不让你推,相当于加了个 “保险栓”。
小编自己现在养成了习惯,用任何带 “force” 的命令前,都先截图存下当前的版本号,虽然麻烦点,但踏实。
其实啊,Git 这东西看着复杂,只要摸透了它 “爱留备份” 的脾气,出了错也不用慌。关键是平时多小心,别乱⽤强制命令。要是你也有过类似的经历,欢迎在评论区说说你是咋解决的,让大家都学学招儿~