文章目录
- Git Reflog 完全指南:找回“消失”的提交神器
- 一、什么是 Git Reflog
- 二、reflog 和 log 的区别
- 1. git log
- 2. git reflog
- 三、为什么 reflog 能恢复代码
- 四、查看 reflog
- 1. 查看 HEAD 的 reflog
- 2. 查看某个分支 reflog
- 3. 更简洁输出
- 五、HEAD@{n} 是什么
- (补充)注意:`git checkout HEAD@{2}` 不是切换到分支,而是切换到 HEAD 在 2 步之前的位置。这个命令使用的是 Git 的 引用日志(reflog) 功能。
- 具体解释:
- 1. `HEAD@{2}` 是什么?
- 2. 这个命令的作用:
- 3. 什么时候会用到这个命令?
- 4. 重要注意事项:
- 总结:
- 六、最经典场景:reset 后恢复代码
- 七、误删分支恢复
- 八、rebase 后救援
- 九、找回 detached HEAD 中的提交
- 十、reflog 的保存位置
- 十一、reflog 会永久保存吗?
- 十二、修改 reflog 保存时间
- 十三、reflog 与 garbage collection(GC)
- 十四、reflog 的核心价值
- 1. 防止误操作
- 2. 学习 Git 的最佳工具
- 3. 调试复杂历史问题
- 十五、常用 reflog 命令总结
- 查看 reflog
- 查看指定分支 reflog
- 回到某次 HEAD 状态
- 从 reflog 恢复分支
- 查看所有引用日志
- 十六、reflog vs stash
- 十七、一个非常重要的认知
- 十八、最佳实践
- 1. 出事故先 reflog
- 2. 不要立刻 gc
- 3. rebase 前创建备份分支
- 4. 熟练使用 HEAD@{n}
- 十九、总结
Git Reflog 完全指南:找回“消失”的提交神器
在学习 Git 的过程中,很多人都会遇到这样的场景:
- 不小心执行了
git reset --hard - 误删了分支
- commit 丢了
- rebase 搞乱了历史
- checkout 后找不到之前的提交
这时候,很多人会以为:
“完了,代码没了。”
实际上,大多数情况下:
Git 只是“找不到引用了”,但对象还在。
而能够帮助你找回这些“丢失提交”的核心工具,就是:
gitreflog很多人只会git log,却不知道git reflog才是真正的“后悔药”。
这篇文章会全面介绍:
- 什么是 reflog
- reflog 和 log 的区别
- reflog 的工作原理
- 如何恢复误删提交
- reset/rebase 后如何救回代码
- reflog 的保存机制
- 常见实战案例
一、什么是 Git Reflog
reflog的全称:
Reference Log(引用日志)
它记录的是:
Git 中“引用(ref)”的变化历史。
比如:
- HEAD 指向变化
- 分支移动
- reset
- merge
- rebase
- checkout
- commit
都会被记录。
查看 reflog:
gitreflog示例:
a1b2c3d HEAD@{0}: commit: fix login bug d4e5f6g HEAD@{1}: reset: moving to HEAD~1 h7i8j9k HEAD@{2}: commit:addauth middleware这里记录了:
- HEAD 当前在哪里
- HEAD 之前在哪里
- 每一步发生了什么操作
二、reflog 和 log 的区别
很多人容易混淆:
gitlog和:
gitreflog它们完全不同。
1. git log
git log查看的是:
commit 历史图
也就是:
提交之间的关系例如:
A -> B -> C它只显示:
- 当前可达的 commit
- 分支历史
2. git reflog
reflog查看的是:
HEAD/分支引用移动历史
它记录的是:
HEAD 曾经指向哪里即使:
- commit 已经脱离分支
- commit 不可达
- branch 删除了
reflog 仍可能找到它。
三、为什么 reflog 能恢复代码
理解 reflog 的关键:
Git 的 commit 本质上是对象。
即使:
gitreset--hard只是:
移动了分支指针commit 对象本身并不会立刻删除。
而 reflog 会记录:
分支原来指向哪里所以你还能找回。
四、查看 reflog
1. 查看 HEAD 的 reflog
gitreflog等价于:
gitreflog show HEAD2. 查看某个分支 reflog
gitreflog show main3. 更简洁输出
gitreflog--oneline五、HEAD@{n} 是什么
reflog 中最常见:
HEAD@{0} HEAD@{1} HEAD@{2}表示:
HEAD 在过去某个时间点的位置例如:
HEAD@{0} 当前 HEAD@{1} 上一步 HEAD@{2} 上两步你可以:
gitcheckout HEAD@{2}也可以:
gitreset--hardHEAD@{2}(补充)注意:git checkout HEAD@{2}不是切换到分支,而是切换到 HEAD 在 2 步之前的位置。这个命令使用的是 Git 的 引用日志(reflog) 功能。
具体解释:
1.HEAD@{2}是什么?
HEAD@{n}表示HEAD 指针在 n 步之前的位置- 这里的
{2}指的是操作历史的第 2 步(从 0 开始计数) - 它记录的是你本地仓库中所有 HEAD 移动的历史
2. 这个命令的作用:
gitcheckout HEAD@{2}- 会将你的工作目录切换到2 次操作之前 HEAD 所在的位置
- 会进入分离头指针状态(detached HEAD state)(危险!)
- 这个位置可能是一个提交(commit),不一定是分支
3. 什么时候会用到这个命令?
- 当你误操作了(比如不小心 reset 了代码)
- 想查看之前的工作状态
- 需要找回"丢失"的提交
- 想回到某个操作前的状态
4. 重要注意事项:
- 这不是切换分支,而是切换到历史的某个状态
- 会进入detached HEAD状态,这意味着:
- 你不在任何分支上
- 新的提交不会被任何分支引用
- 完成查看后,应该切回正常分支:
git checkout your-branch-name
总结:
git checkout HEAD@{2}是一个恢复/回退操作,让你回到 2 次操作之前的状态,而不是切换到某个分支。它是 Git 的"后悔药"功能之一,用于在误操作后找回丢失的工作。
六、最经典场景:reset 后恢复代码
假设:
gitlog--onelineC B A你误执行:
gitreset--hardHEAD~2现在:
只剩 A很多人会慌。
这时:
gitreflog可能看到:
abc123 HEAD@{0}: reset: moving to HEAD~2 def456 HEAD@{1}: commit: C ghi789 HEAD@{2}: commit: B恢复方法:
gitreset--harddef456或者:
gitreset--hardHEAD@{1}提交瞬间恢复。
七、误删分支恢复
假设:
gitbranch-Dfeature-login分支删除了。
但 reflog 还在。
查看:
gitreflog找到:
123abcd commit: finish login恢复:
gitcheckout-bfeature-login 123abcd分支回来了。
八、rebase 后救援
git rebase是事故高发区。
例如:
gitrebase main结果:
- commit 顺序乱了
- squash 错了
- 丢 commit
此时:
gitreflog会看到:
HEAD@{5}: rebase started HEAD@{4}: rebase finished恢复:
gitreset--hardHEAD@{5}直接回到 rebase 之前。
九、找回 detached HEAD 中的提交
很多人:
gitcheckout 某个commit进入:
detached HEAD然后提交了代码:
gitcommit后来切回 main:
gitcheckout main那个 commit “消失”了。
其实还在。
查看:
gitreflog找到:
789abcd commit: temp fix恢复:
gitcheckout-brecover-temp 789abcd十、reflog 的保存位置
reflog 实际保存在:
.git/logs/例如:
.git/logs/HEAD .git/logs/refs/heads/main十一、reflog 会永久保存吗?
不会。
Git 会自动清理。
默认:
90 天:可达对象 30 天:不可达对象| 类型 | 保留时间 | 说明 |
|---|---|---|
| 可达对象 | 90 天 | 当前还在使用的提交(安全期较长) |
| 不可达对象 | 30 天 | 已删除的提交(很快会被清理) |
查看配置:
gitconfig--getgc.reflogExpiregitconfig--getgc.reflogExpireUnreachable(啥也没有呀?windows)
十二、修改 reflog 保存时间
例如:
gitconfig--globalgc.reflogExpire180.days不可达对象:
gitconfig--globalgc.reflogExpireUnreachable60.days十三、reflog 与 garbage collection(GC)
Git 最终会执行:
gitgc清理:
- 无引用对象
- 过期 reflog
- dangling commits
所以:
reflog 不是永久备份系统。
只是:
“短期后悔药”。
十四、reflog 的核心价值
1. 防止误操作
这是 reflog 最大意义。
2. 学习 Git 的最佳工具
你能看到:
- HEAD 如何移动
- reset 如何工作
- rebase 做了什么
- merge 如何改变引用
非常适合理解 Git 内部机制。
3. 调试复杂历史问题
尤其:
- rebase
- cherry-pick
- force push
- reset
十五、常用 reflog 命令总结
查看 reflog
gitreflog查看指定分支 reflog
gitreflog show main回到某次 HEAD 状态
gitreset--hardHEAD@{3}从 reflog 恢复分支
gitcheckout-brecover abc123查看所有引用日志
gitlog-g十六、reflog vs stash
很多人误以为 reflog 能替代 stash。
其实:
| 功能 | reflog | stash |
|---|---|---|
| 自动记录 | ✅ | ❌ |
| 保存工作区 | ❌ | ✅ |
| 恢复 commit | ✅ | ❌ |
| 恢复未提交修改 | 有限 | ✅ |
| 防误删 | ✅ | 一般 |
十七、一个非常重要的认知
很多 Git 新手认为:
reset --hard = 删除代码实际上:
reset 只是移动引用真正删除对象:
通常发生在:
git gc之后。
而 reflog 正是:
“引用移动历史记录”。
十八、最佳实践
1. 出事故先 reflog
不要慌。
第一件事:
gitreflog2. 不要立刻 gc
否则可能真的丢失对象。
3. rebase 前创建备份分支
例如:
gitbranch backup-before-rebase4. 熟练使用 HEAD@{n}
这是 reflog 的核心能力。
十九、总结
git reflog是 Git 中最容易被忽视,但最强大的命令之一。
它本质上记录的是:
Git 引用(HEAD/branch)的变化历史。
它最大的价值:
- 恢复误删 commit
- 找回 reset 后代码
- 撤销错误 rebase
- 恢复删除分支
- 找回 detached HEAD 提交
可以说:
学会 reflog,才算真正掌握 Git 的“后悔机制”。
很多时候:
代码并没有丢, 只是你失去了引用。而 reflog:
正是找回这些引用的时光机。