一、误删分支/提交的常见场景与 reflog 的核心作用

做开发的人,或多或少都遇到过手滑的情况:比如本来想删个测试分支,结果把线上开发分支删了;或者改了半天代码提交后,又误操作把这个提交给重置没了,找半天找不到。这种时候要是没备份,简直要头大。

其实Git自带了一个专门用来救急的工具,叫reflog,它的全称是Reference Log,简单说就是Git给每个操作记的“操作日志”。只要你是在本地操作的Git,不管是提交、切换分支、合并、重置,甚至是删分支,这些操作都会被reflog记下来,哪怕你把提交记录从主分支里清掉了,只要没超过Git默认的保存时间,就能从这里找回来。

1.1 误删分支/提交的典型场景

我自己就遇到过两次:第一次是刚学Git的时候,想整理本地分支,执行了删分支的命令,结果把正在做功能开发的feature分支删了;第二次是改了线上的bug,提交后想把提交记录合并到主分支,结果执行git reset --hard的时候选错了参数,把刚提交的bug修复记录给清了。后来才知道,这两种情况都能用reflog救回来。

二、完整恢复操作的前置准备

在开始恢复之前,得先搞清楚几个基础的操作逻辑,不然容易越弄越乱。首先要明确,reflog只记录本地的操作,如果你是把远程分支删了,那得先把远程的分支或者提交拉到本地,才能用reflog恢复。

2.1 示例技术栈说明

本文所有示例统一使用Git(版本要求:2.20及以上,不同版本操作逻辑一致,只是部分命令的输出格式略有差异),所有命令均在本地终端执行,不需要额外的工具。

2.2 恢复前的注意事项

恢复操作之前,千万不要随便执行git gc(垃圾回收)命令,这个命令会清理掉reflog里过期的操作记录,一旦执行了,可能就找不回来了。另外,在恢复之前最好先把当前的工作区暂存一下,避免恢复过程中覆盖掉没提交的代码。暂存命令很简单:

# 暂存所有未提交的修改,方便后续恢复后再恢复这些修改
git stash

三、误删分支后的恢复全过程

误删分支是最常见的情况,比如你本地有个叫feature-user的分支,上面有你做了一周的功能,结果不小心删了,这个时候怎么找回来?

3.1 误删分支的操作示例

先模拟误删的场景,一步步来:

# 1. 初始化一个测试仓库(如果是自己的项目可以跳过这步)
mkdir git-recover-test
cd git-recover-test
git init

# 2. 新建一个测试文件,提交初始内容
echo "初始内容" > test.txt
git add test.txt
git commit -m "初始提交"

# 3. 新建feature-user分支,做一些修改并提交
git checkout -b feature-user
echo "用户功能开发内容" >> test.txt
git add test.txt
git commit -m "添加用户功能开发内容"

# 4. 切换回主分支,模拟误删feature-user分支
git checkout main
git branch -d feature-user # 这里故意删分支,模拟误操作

执行完最后一步,你会发现本地已经找不到feature-user分支了,这个时候就需要用reflog来恢复。

3.2 用reflog找回误删分支的步骤

第一步,先查reflog,找到删分支之前的操作记录:

# 查看所有操作的reflog记录
git reflog

执行后会输出类似下面的内容(不同环境格式略有差异):

c03a7b8 (HEAD -> main) HEAD@{0}: checkout: moving from feature-user to main
c03a7b8 (HEAD -> main) HEAD@{1}: commit: 添加用户功能开发内容
c03a7b8 (HEAD -> main) HEAD@{2}: checkout: moving from main to feature-user
a12f3c4 HEAD@{3}: commit (initial): 初始提交

每一行的格式是:提交哈希值 + HEAD@{序号} + 操作描述。你需要找到和feature-user分支相关的操作,比如上面的HEAD@{1},操作描述是“commit: 添加用户功能开发内容”,对应的哈希值是c03a7b8,这个就是feature-user分支最后一次提交的哈希值。

第二步,根据这个哈希值恢复分支:

# 恢复feature-user分支,指向找到的最后一次提交
git checkout -b feature-user c03a7b8

执行完这个命令,你就会发现feature-user分支回来了,而且上面的提交记录都还在,和删之前一模一样。

四、误删提交后的恢复全过程

除了误删分支,还有一种常见的情况是误删提交,比如你提交了几次代码,然后执行了git reset --hard,把中间的提交给清了,或者不小心把提交记录从分支里删了,这个时候也能用reflog找回来。

4.1 误删提交的操作示例

同样先模拟误删的场景:

# 还是用刚才的测试仓库,先回到主分支
git checkout main

# 1. 做几次提交,模拟正常开发
echo "第一次修改" >> test.txt
git add test.txt
git commit -m "第一次修改" # 提交1
echo "第二次修改" >> test.txt
git add test.txt
git commit -m "第二次修改" # 提交2
echo "第三次修改" >> test.txt
git add test.txt
git commit -m "第三次修改" # 提交3

# 2. 模拟误删提交:用reset把提交3和提交2清掉
git reset --hard HEAD~2 # 这里HEAD~2表示回退到当前HEAD的前2个提交,也就是提交1的位置

执行完最后一步,你会发现test.txt里只有初始内容和第一次修改的内容,第二次和第三次修改都没了,提交记录里也找不到这两次的提交了。

4.2 用reflog找回误删提交的步骤

第一步,查reflog,找到被删的提交的哈希值:

git reflog

输出类似:

a12f3c4 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~2
c03a7b8 HEAD@{1}: commit: 第三次修改
b24d5e6 HEAD@{2}: commit: 第二次修改
a12f3c4 (HEAD -> main) HEAD@{3}: commit: 第一次修改
a12f3c4 (HEAD -> main) HEAD@{4}: commit (initial): 初始提交

你需要找到被删的提交对应的哈希值,比如第二次修改的哈希是b24d5e6,第三次修改的哈希是c03a7b8。

第二步,根据需求恢复提交: 如果你想把两次误删的提交都找回来,可以直接把当前分支重置到第三次修改的哈希:

# 重置到第三次修改的提交,恢复所有被删的提交
git reset --hard c03a7b8

如果你只想恢复第二次修改的提交,可以先把第二次修改的内容拉出来,或者新建一个分支指向第二次修改的哈希:

# 新建一个分支指向第二次修改的提交
git checkout -b temp b24d5e6

执行完后,你就可以把temp分支里的内容合并到主分支,或者直接复制需要的代码。

五、reflog的技术细节与注意事项

很多人会问,reflog的记录能保存多久?会不会突然消失?其实Git默认的reflog保存时间是90天,超过90天的操作记录会被自动清理。不过这个时间是可以改的,如果你需要更长的保存时间,可以修改Git的配置:

# 设置reflog保存时间为180天(单位是天)
git config gc.reflogExpire 180.days

另外,reflog的记录是存在本地的,如果你把本地的仓库删了,或者重新克隆了远程仓库,那本地的reflog记录就没了,所以平时要注意不要随便删本地仓库。

5.1 恢复操作的常见坑

很多人在恢复的时候会遇到这样的问题:查reflog的时候找不到对应的记录,或者恢复后代码不对。这通常是因为两个原因:一是误操作后执行了git gc,把记录清了;二是找哈希值的时候找错了,比如把其他分支的哈希当成了自己要恢复的。所以在恢复的时候,一定要仔细看reflog里的操作描述,确认是自己要找的操作。

六、应用场景、优缺点与总结

6.1 应用场景

reflog的恢复功能主要适用于本地的误操作场景:比如误删本地分支、误删本地提交、误重置分支、误合并分支等,只要是本地的操作,并且操作记录还在reflog里,就能用这个方法恢复。如果是远程分支被删了,或者远程提交被清了,那需要先把远程的操作拉到本地,再用reflog恢复。

6.2 技术优缺点

优点很明显:一是操作简单,不需要额外的工具,只要用Git自带的命令就能完成;二是恢复速度快,只要找到对应的哈希值,几分钟就能恢复;三是覆盖场景广,大部分本地的误操作都能解决。

缺点也有:一是只适用于本地操作,远程的操作需要先同步到本地;二是有时间限制,超过90天的记录会被清理;三是需要用户能看懂reflog的记录,找到对应的哈希值,对新手来说有一点门槛。

6.3 文章总结

误删分支或提交是开发中很常见的问题,很多人遇到这种情况会慌,其实只要掌握了reflog的使用方法,就能轻松解决。reflog就像Git的“操作回收站”,只要操作记录还在,就能找回来。平时开发的时候,要注意养成良好的习惯:比如多提交代码、不要随便执行git gc、重要的分支及时推到远程,这样就算遇到误操作,也能轻松恢复。