09 --- .git 地图:打开那个隐藏文件夹
摘要: 本章深入探索 Git 仓库的核心------.git 隐藏文件夹。通过可视化地图和动手实验,你将了解 .git 目录结构及各文件/文件夹的作用,理解 Git 如何将版本历史、分支、暂存区等状态存储为普通文件。重点掌握 objects/(存储历史内容)、refs/(存储分支/标签引用)、HEAD(当前分支指针)、index(暂存区)和 logs/(操作日志)等核心组件的功能。通过观察 add、commit 等命令对 .git 文件的实际影响,你将不再视 Git 为黑盒,并为后续深入学习对象模型和引用机制打下坚实基础。
写在前面:这一章要解决什么
前面八章你用了无数 git 命令,但那个藏着历史的 .git 文件夹从来没打开过。这一章就带你 打开它看看------
.git里都有什么- 每个文件夹/文件是干嘛的
- 为什么说「Git 像 Linux,一切皆文件」
- 你每次
add、commit到底动了哪些文件
学完后,你应该能:
- 说清
.git下主要路径的职责 - 不再觉得 Git 是黑盒
- 为后面的「对象、引用」章节打基础
读者设定: 大一同学,会用基本 Git,但没看过 .git 内部。
1. 定位:为什么要看 .git
1.1 一句话先记住
Git 不神秘------它的状态大多就是 .git 里的普通文件。
像 Linux 把一切都当文件(连设备都是 /dev/xxx),Git 也把历史、分支、当前在哪 都存在文件里。
1.2 看了 .git 能得到什么
| 不看 | 看了 |
|---|---|
| Git 是黑盒 | 知道每次命令动了什么文件 |
| 出错靠瞎试 | 能从文件层面排查 |
| 觉得分支很玄 | 分支就是个文本文件,存一个哈希 |
| 怕改坏历史 | 知道 .git 备份好就行 |
1.3 和你已经会的对比
| 你已经会的 | .git 对应 |
|---|---|
| 浏览器书签是个文件 | 分支是 .git/refs/heads/名字 |
| 「当前打开的标签页」存在配置 | HEAD 文件说你在哪 |
| 数据库的数据文件 | objects/ 存历史内容 |
1.4 本章内容目标
| 目标 | 你能做到 |
|---|---|
| 看地图 | 说出主要路径职责 |
| 不慌 | 知道 Git 状态是文件 |
| 备份 | 知道备份什么能保住历史 |
| 预告 | 为对象(第 10 章)、引用(第 12 章)铺垫 |
2. 本质:.git 是 Git 的大脑
2.1 先看一张总图

图:命令作用于四个层------对象库、引用、暂存区、工作区。本章重点在 .git 内的前三层。
2.2 用白话拆开
.git 是 Git 仓库的「大脑」。删了它,仓库就退化成普通文件夹。它里面主要有:
| 路径 | 干什么 |
|---|---|
objects/ |
存历史内容(文件快照、目录树、提交) |
refs/ |
存「名字」(分支、标签、远程跟踪分支) |
HEAD |
说「你现在在哪条分支」 |
index |
暂存区(第 02 章那个「篮子」) |
logs/ |
引用移动的日志(reflog 的数据源) |
config |
本仓库的配置 |
hooks/ |
钩子脚本(默认是样例) |
info/exclude |
本地忽略规则(不提交) |
2.3 几条硬规矩
| 规矩 | 白话 |
|---|---|
删 .git = 丢历史 |
工作区文件可能还在,但历史没了 |
别手改 refs 和 objects |
不懂哈希前容易搞乱 |
index 是二进制 |
用 git ls-files --stage 看,别用编辑器打开 |
备份 .git 约等于备份历史 |
工作区文件是派生的 |
2.4 新手最常踩的坑
| 坑 | 表现 | 办法 |
|---|---|---|
| 以为历史在工作区文件里 | 删了 .git 才发现历史没了 |
备份要带 .git |
| 手改分支文件 | 引用和日志不同步 | 用 git branch 等命令 |
以为 .git 不能动 |
不敢看 | 看可以,改要小心 |
把 .git 提交进另一个仓库 |
嵌套混乱 | .git 不该被跟踪 |
3. 建议学习顺序
text
先看 `.git` 长啥样
→ 认主要路径
→ 做一次 add + commit,看哪些文件变了
→(预告)下一章拆 objects
4. 动手准备
bash
mkdir lab-dotgit
cd lab-dotgit
git init -b main
git config user.name "Ada Example"
git config user.email "ada@example.com"
git --version
text
git version 2.43.0
5. 跟着做:看 .git 里有什么
5.1 刚 init 完的地图
bash
find .git -maxdepth 2 | sort | head -30
text
.git
.git/HEAD
.git/branches
.git/config
.git/description
.git/hooks
.git/info
.git/info/exclude
.git/objects
.git/objects/info
.git/objects/pack
.git/refs
.git/refs/heads
.git/refs/tags
白话翻译: 刚 init 完,objects/ 基本是空的,refs/heads/ 也是空的(还没有任何提交)。
5.2 看 HEAD:你现在在哪
bash
cat .git/HEAD
text
ref: refs/heads/main
白话翻译: HEAD 是个文本文件,内容是「我指向 refs/heads/main 这条分支」。main 文件还没建(没提交),但 HEAD 已经准备好指它。
5.3 做一次 add,看什么变了
bash
printf 'hello\n' > f.txt
git add f.txt
find .git/objects -type f
text
.git/objects/58/7be6b4c3f93f93c489c0111bba5596147a26cb
白话翻译: add 把文件内容写成「对象」塞进 objects/。这个长串是内容的哈希(第 10 章细讲)。
5.4 做一次 commit,再看什么变了
bash
git commit -m "c1"
find .git/objects -type f
text
.git/objects/49/97ca7a42e3ad9b729fbad3acd44fbabd07b6bd
.git/objects/58/7be6b4c3f93f93c489c0111bba5596147a26cb
.git/objects/aa/204d311bcd992bb9ea23ca4a795cfa8cce4275
白话翻译: 多了两个对象:一个是「目录树」(说 f.txt 叫这个名字、内容是哪个哈希),一个是「提交」(指向那棵树 + 作者 + 说明)。
5.5 看分支文件
bash
cat .git/refs/heads/main
text
aa204d311bcd992bb9ea23ca4a795cfa8cce4275
白话翻译: 分支 main 就是个文本文件,存的是最新提交的哈希。所谓「分支」就是这一行字。
5.6 看 logs:reflog 的数据源
bash
cat .git/logs/HEAD
text
0000000000000000000000000000000000000000 aa204d311bcd992bb9ea23ca4a795cfa8cce4275 Ada Example <ada@example.com> 1784883528 +0800 commit (initial): c1
白话翻译: logs/HEAD 记录了 HEAD 的移动历史。这就是 git reflog 显示的东西(进阶章细讲)。

图:再看一遍------add/commit/switch 各动了哪些层。
6. .git 主要路径速查
| 路径 | 干什么 | 谁来改 |
|---|---|---|
objects/ |
存历史内容(对象) | add、commit、fetch |
refs/heads/ |
本地分支(每条一个文件) | commit、branch、reset |
refs/tags/ |
标签 | tag |
refs/remotes/ |
远程跟踪分支 | fetch |
HEAD |
当前在哪 | switch、checkout |
index |
暂存区 | add、reset |
logs/ |
引用移动日志 | 大部分命令 |
config |
本仓库配置 | git config --local |
hooks/ |
钩子脚本 | 手动启用 |
info/exclude |
本地忽略 | 手动编辑 |
7. 对照表:降低记忆负担
7.1 命令 → 大致动了哪些 .git 文件
| 命令 | objects | refs | index | 工作区 | logs |
|---|---|---|---|---|---|
add |
写 blob | --- | 改 | --- | --- |
commit |
写 tree + commit | 改分支 | 刷新 | --- | 写 |
branch 名字 |
--- | 新建分支文件 | --- | --- | 有时 |
switch |
--- | 改 HEAD | 改 | 改 | 写 |
reset --hard |
--- | 改分支 | 改 | 改 | 写 |
fetch |
下载 | 改远程跟踪 | --- | --- | 写 |
tag |
可能写 tag 对象 | 新建标签文件 | --- | --- | --- |
完整表见第 11 章。
7.2 「.git 里有啥」vs「工作区有啥」
.git 里有 |
工作区里有 | |
|---|---|---|
| 历史 | 有(objects + refs) | 没有 |
| 你正编辑的文件 | 没有 | 有 |
| 暂存区 | 有(index) | 没有 |
| 配置 | 有(config) | 没有 |
8. 安全习惯
8.1 建议这样做
| 习惯 | 原因 |
|---|---|
备份带上 .git |
没它就没历史 |
| 看可以,改要小心 | 用 Git 命令改,别手编辑 |
别把 .git 提交进别的仓库 |
嵌套混乱 |
学会用 git 命令查 |
git status、git log、git ls-files |
8.2 别这样做
| 别 | 原因 |
|---|---|
手改 refs/heads/ 文件 |
容易和 logs 不同步 |
用编辑器开 index |
二进制,会搞坏 |
删 objects/ 里的文件 |
历史就缺了 |
把 .git 当普通文件夹提交 |
嵌套仓库 |
9. 真实场景
9.1 仓库「坏了」怎么排查
git status报奇怪错误 → 先看.git/HEAD是否还在- 分支不见了 → 看
.git/refs/heads/还有没有 - 历史少了 →
git fsck检查对象完整性(进阶)
9.2 换电脑迁移项目
- 整个项目目录(含
.git)拷过去,历史就在 - 或者只拷工作区 → 没历史,等于重新开始
9.3 想看但不敢改
- 用
cat、find、ls只读查看 - 真要实验,先复制一份再玩
10. 稍微多懂一点点(可选)
logs/是 reflog 的来源 :git reflog读的就是这里的文件。ORIG_HEAD:危险操作前 Git 会备份一份旧 HEAD 位置。FETCH_HEAD:上次fetch拉来的远端 tip。MERGE_HEAD:合并进行中时存在,记录「对方」是谁。objects/pack/:很多对象压缩打包放这(gc维护)。
11. 小实验(请一定动手)
实验甲:看 init 后的地图
- 建仓,
find .git -maxdepth 2 | sort。 cat .git/HEAD,看指向哪。- 确认
objects/和refs/heads/基本空。
实验乙:看 add + commit 后的变化
- 建文件、
add、find .git/objects -type f。 commit后再find .git/objects -type f,数多了几个。cat .git/refs/heads/main看分支存的哈希。cat .git/logs/HEAD看移动记录。
实验丙:建个分支看文件
git branch dev。ls .git/refs/heads/,应该多了dev。cat .git/refs/heads/dev,和main一样吗?
通过标准: 能说清「分支是文件、HEAD 是文件、历史在 objects」。
12. 常见问题
问 1:.git 能删吗?
能删,但历史就没了。工作区文件可能还在。
问 2:.git 能拷给别人吗?
能,整目录拷过去就是完整历史。但更推荐用 clone。
问 3:objects 里那串是什么?
是内容的哈希。第 10 章细讲。
问 4:分支文件能手改吗?
能改但不推荐。用 git branch 等命令,避免和 logs 不同步。
问 5:index 能用编辑器打开吗?
别。它是二进制。用 git ls-files --stage 看。
问 6:HEAD 和分支啥关系?
HEAD 通常是个符号引用,指向当前分支;分支文件又指向提交。
问 7:logs/ 和 reflog 一样吗?
reflog 读的就是 logs/。进阶章细讲。
问 8:.git 多大算正常?
看历史大小。小项目几 KB 到几 MB;大型项目可能上百 MB(用 gc 维护)。
13. 总结、学习路线与思维升华
13.1 这一章请记住的
| 点 | 记住什么 |
|---|---|
.git 是大脑 |
删了就丢历史 |
| objects | 存历史内容 |
| refs | 存名字(分支、标签) |
| HEAD | 说你在哪 |
| index | 暂存区 |
| logs | reflog 数据源 |
| 下一章 | 拆 objects 看对象类型 |
13.2 在整个系列中的位置
text
01--08 新手篇
09 .git 地图 ← 当前
10 对象模型
11 操作→文件
12 引用与 HEAD
13 暂存区深入
14 历史是图
15--24 进阶
13.3 思维升华
Git 不神秘------它的状态大多是
.git里的普通文件。看懂地图,命令就不再是黑盒。
备份带上
.git,历史就跟着你走。
13.4 参考资料
- Pro Git 中文版 --- 底层命令与上层命令
- Pro Git 中文版 --- Git 对象
- Pro Git 中文版 --- Git 引用
- git init 说明
- git ls-files 说明
- 本仓库图示署名:
assets/diagrams/ATTRIBUTION.md
命令输出样例验证环境:Git 2.43.0 ;演示作者信息为虚构:Ada Example <ada@example.com>。
13.5 本章检查清单
- 看过
.git目录结构 - 说清 objects/refs/HEAD/index 各干什么
- 看过
add后多了对象 - 看过
commit后多了对象 + 分支文件 - 看过
.git/refs/heads/main存哈希 - 知道备份要带
.git - 不手改 refs/objects
打开 .git,Git 就不再是黑盒了。下一章我们拆 objects/,看里面那四类对象到底长啥样。