首页 / Git 入门教程 / 引用日志(Reflog)

Git 入门教程

引用日志(Reflog)

本教程共 26 篇 · 第 19 篇 · 更新于 2026-07-29 · 约 5 分钟阅读

GitGit 入门教程reflog引用日志HEAD恢复提交数据恢复

19. 引用日志(Reflog)

本节目标:理解引用日志的本质是 Git 的”后悔药”,学会用 reflog 找回那些你以为已经丢失的提交。

什么是引用日志

Git 的引用日志(reflog)就像手机里的”最近删除”相册。

你删掉一张照片,它并没有立刻从手机里消失,而是进了”最近删除”。reflog 也一样。当你执行 git reset --hardgit rebasegit commit --amend,Git 并没有真正丢弃旧提交。它只是把它们记在 reflog 里。

一句话:reflog 记录了你本地仓库中 HEAD 每一次指针移动的轨迹

Note

reflog 只存在本地。推送到远程仓库的提交不会被远程帮你保留 reflog,clone 也不会复制别人的 reflog。这是你个人的操作历史。

reflog 长什么样

打开终端,进入任意一个 Git 仓库,输入:

git reflog

输出大概长这样:

a1b2c3d HEAD@{0}: commit: 修复登录按钮样式
e4f5g6h HEAD@{1}: checkout: moving from feature to main
i7j8k9l HEAD@{2}: commit (merge): 合并 feature 分支
m0n1o2p HEAD@{3}: rebase -i (finish): returning to refs/heads/main
q3r4s5t HEAD@{4}: commit: 添加用户头像上传

每一行是一条记录。HEAD@{0} 表示 HEAD 当前所在的位置,HEAD@{1} 是上一步,HEAD@{2} 是上上步,以此类推。

HEAD@{n} 语法

HEAD@{n} 是 reflog 专属的引用语法。它的意思是”HEAD 在第 n 步时所指向的提交”。

这跟 HEAD~n 不一样。HEAD~n 是沿着提交历史往上数第 n 个父提交,而 HEAD@{n} 是沿着操作历史回溯。

举个例子:你先在 main 分支提交了 A,然后切到 feature 分支提交了 B,再切回 main

  • HEAD~1 是提交 A(父提交)
  • HEAD@{1} 是提交 B(切回 main 之前的位置)

与 git log 的区别

对比项git loggit reflog
内容提交历史(祖先链)操作历史(HEAD 移动轨迹)
是否包含”丢失”提交不包含包含
作用域永久默认 90 天后过期
能否跨分支追踪按分支走按时间顺序全记录

一句话:git log 看”谁是谁的祖先”,git reflog 看”你踩过哪些坑”。

找回”丢失”的提交

这是 reflog 最常用的场景。假设你不小心执行了:

git reset --hard HEAD~3

三个提交”消失”了。git log 里看不到了。别慌。

  1. 先看 reflog 找到那三个提交:
git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
e4f5g6h HEAD@{1}: commit: 第三次提交
i7j8k9l HEAD@{2}: commit: 第二次提交
m0n1o2p HEAD@{3}: commit: 第一次提交
  1. 找到你想恢复的位置,比如 HEAD@{1}
git reset --hard HEAD@{1}

三个提交就回来了。

Warning

reflog 记录有过期时间。默认情况下,可达对象保留 90 天,不可达对象保留 30 天。过期后 Git 垃圾回收会真正删除它们。所以发现误操作要尽快恢复。

指定分支的 reflog

git reflog 默认显示 HEAD 的记录。你也可以查看某个分支的 reflog:

git reflog show main

这在排查”某个分支的顶端怎么跑到这里来了”时特别好用。

reflog 过期时间

想调整过期时间,可以改配置:

# 控制可达对象的保留天数
git config gc.reflogExpire 180.days

# 控制不可达对象的保留天数
git config gc.reflogExpireUnreachable 60.days

实际操作演示

我们来模拟一次”事故”和”救援”。

  1. 先制造三次提交:
echo "第一次" > a.txt && git add . && git commit -m "第一次提交"
echo "第二次" >> a.txt && git add . && git commit -m "第二次提交"
echo "第三次" >> a.txt && git add . && git commit -m "第三次提交"
  1. 查看 log,确认三次提交都在:
git log --oneline
c3f01dc 第三次提交
b2e90ab 第二次提交
a1b2c3d 第一次提交
  1. 执行”危险操作”:
git reset --hard HEAD~2
  1. 再看 log,第三次和第二次提交不见了:
git log --oneline
a1b2c3d 第一次提交
  1. 查看 reflog 找到它们:
git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD~2
c3f01dc HEAD@{1}: commit: 第三次提交
b2e90ab HEAD@{2}: commit: 第二次提交
  1. 恢复到 HEAD@{1}
git reset --hard HEAD@{1}
  1. 验证:
git log --oneline
c3f01dc 第三次提交
b2e90ab 第二次提交
a1b2c3d 第一次提交

三次提交全部恢复。

Note

如果你找不到想要的提交,试试 git fsck --lost-found。它能找到所有”悬挂”的提交对象,不过操作更底层,适合极端情况。

常见使用场景

  • git reset --hard 撤消后反悔
  • git rebase 后发现丢了提交
  • git commit --amend 覆盖了原始提交
  • 切换分支后发现之前的提交”不见了”
  • 误删分支后想找回那个分支指向的提交

核心记忆:reflog 是你的后悔药。只要没过期,几乎没有救不回来的提交。

这章学到了什么

  • reflog 是 Git 的”后悔药”,记录 HEAD 每一次指针移动的轨迹
  • HEAD@{n} 语法沿操作历史回溯,与 HEAD~n 沿祖先链回溯不同
  • git log 看祖先链,git reflog 看操作历史,后者包含”丢失”的提交
  • 找回误删提交的方法:先用 reflog 定位,再用 git reset --hard HEAD@{n} 恢复
  • reflog 有过期时间,默认可达对象保留 90 天,发现误操作要尽快恢复

下一章,我们学习如何安全地重写提交历史。