土法炼钢兴趣小组的算法知识备份

【Git 内部】reflog:logs/ 下的追加式历史

文章导航

分类入口
opensource
标签入口
#git#git-internals#reflog#logs

目录

git reset --hard 之后「找不回」提交,多半是没查 reflog。reflog 不是对象库的一部分,而是 .git/logs/ 下按引用路径镜像的追加日志:每次 ref 指针移动写一条记录。文件在磁盘上是类文本的二进制混排,与 git reflog 输出一一对应。

本文说明 reflog 文件路径、条目字段与 hexdump 对照方法。ref 本身格式见 第 04 篇


一、文件路径规则

文件 对应
.git/logs/HEAD 当前 HEAD 移动历史
.git/logs/refs/heads/master 分支 master
.git/logs/refs/remotes/origin/main 远程跟踪分支

目录结构镜像 refs/,扩展名不是独立概念——整个路径即日志文件。

默认 core.logAllRefUpdates 为 true 时,更新分支会同时写 logs/HEADlogs/refs/heads/<branch>。reflog 条目有过期策略(gc.reflogExpire 等),git gc 会修剪旧条目(第 10 篇)。


二、条目格式

每条记录一行(逻辑上),字段为空格分隔,结构为:

单条 reflog 记录的字段:old-sha、new-sha、提交者、时间戳、message
<old-sha> <new-sha> <committer-name> <committer-email> <timestamp> <tz> <message>

git reflog 显示时会缩短 SHA 并格式化时间。


三、hexdump 对照

对一次初始提交后的 .git/logs/HEAD 执行 hexdump -C(以下片段经删减):

00000020  30 30 30 30 30 30 30 30  20 32 62 32 34 62 32 36  |00000000 2b24b26|
00000030  61 31 31 37 65 66 35 63  66 64 62 66 38 38 30 34  |a117ef5cfdbf8804|
...
00000060  6c 69 61 6f 74 6f 6e 67  6c 61 6e 67 40 67 6d 61  |liaotonglang@gma|
00000070  69 6c 2e 63 6f 6d 3e 20  31 37 38 33 31 38 39 36  |il.com> 17831896|

可见 ASCII:0000000000000000000000000000000000000000(old)+ 空格 + 2b24b26a…(new)+ 提交者 + 时间戳 + 时区 + 消息。

复现:

git commit -m 'test'   # 至少一次提交
hexdump -C .git/logs/HEAD | head -8
git reflog

四、典型消息与恢复

message 前缀 典型触发
commit: git commit
checkout: git checkout / switch
reset: git reset
merge …: 快进或合并提交
pull …: pull 产生的 fetch + merge

git reflog show masterlogs/refs/heads/master。找回误删分支:git branch recovered <sha-from-reflog>


五、与对象可达性

reflog 引用的是对象 ID。即使某 commit 已不在任何分支上,只要 reflog 仍指向它且对象未被 gc prune,commit 仍可达。prune 策略与悬空对象见 第 10、11 篇


六、本文边界


参考资料

系列索引Git 内部结构 · 上篇refs · 下篇index 格式

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-05 · opensource

【Git 内部】Git 内部结构:对象库与磁盘文件格式

从 .git 目录布局、松散对象与 packfile 格式,到 refs、index、reflog、gc/fsck 与 fetch/push 落地——用官方 format 文档与本地实测 dump 系统讲清 Git 把版本历史存在哪、每个命令改写了哪些文件。全 16 篇。


By .