Hegwin.Me

长风破浪会有时,直挂云帆济沧海。

Git 找回reset --hard的代码及删除的分支

How to undo a git reset hard and branch delete

人总是会犯错的。

还记得第一次使用 git reset --hard + git push -f 是在2013年初。那时候我图省事,在staging服务器上修改了点代码,就直接push到github上去了,本以为只是一个小提交,结果push了一堆无用的代码上去。怎么办呢,这时候有前辈出来告诉我,即使是push到服务器的代码依然是可以修改的,同时告诉其他同事暂时不要push代码,最终用 reset --hard 和 force 解决了这次问题。

终于,这么多年过去之后,我似乎也成了“前辈”(然而水平也并没有太多提高)。

今天一个同事忽然说把代码弄没了—— reset hard之后, force push到github上了,很慌张的样子……哈哈,在之前的事故中,我也是忐忑不安,记忆犹新。

回到开头那句,人总是会犯错的,在改错的过程中也会犯错,虽然两次犯错叠加之后的概率很小,但还是有可能发生的。那么reset --hard之后还能找回代码吗,当然是可以的。 Git never deletes a commit. 这时候需要reflog出场了。

官方对reflog的描述是这样的:

Reference logs, or "reflogs", record when the tips of branches and other references were updated in the local repository.

我们可以从其中得到2个信息:

  1. 它是针对ref的change log,所以 git reset 或者 git cherry-pick这样的操作都会被记录下来;

  2. 它只存在本地(local),所以可以认为是本地的undo历史记录。

Reflog的基本操作

列出reflogs:

git reflog

或者:

git log --walk-reflogs

你能看到你之前的改动都还在,这时候你该心安了——即使reset --hard也不会丢失,这之后的套路应该熟悉了吧,找到你需要的commit,然后reset过去。

恢复一个分支

同理,用 -D 删除的分支也是可以找回来的。用reflog查看记录,找回分支删除前的commit的hash,比如4c84318,然后这样:

git branch <branch-name> 4c84318
< Back