第 6 章 · 02 索引与 staging: 的真相 本节摘要:新手最困惑的 Git 问题之一:「为什么 add 之后还要 commit?add 到底干了什么?」本节要捅破这层窗户纸。 干的事是:把工作区文件内容存成 blob(进对象库),并在「索引」里记下「这个文件名现在对应这个 blob」。索引(index)是「下一次 commit 的草稿树」——add 是往草稿里添改,commit 是把草稿定稿。理解索引,你就理解了「工作区/暂存区/仓库」三区模型。 内容来源:基于 Git 内部模型整理的导读。 学习目标 阅读完本节,你应当能够: 说清 干的事:把文件内容存成 blob,在索引里记「文件名→blob 哈希」。 解释「索引」是「下一次 commit 的草稿树」。
git add 的真相本节摘要:新手最困惑的 Git 问题之一:「为什么 add 之后还要 commit?add 到底干了什么?」本节要捅破这层窗户纸。
git add干的事是:把工作区文件内容存成 blob(进对象库),并在「索引」里记下「这个文件名现在对应这个 blob」。索引(index)是「下一次 commit 的草稿树」——add 是往草稿里添改,commit 是把草稿定稿。理解索引,你就理解了「工作区/暂存区/仓库」三区模型。
内容来源:基于 Git 内部模型整理的导读。
阅读完本节,你应当能够:
git add 干的事:把文件内容存成 blob,在索引里记「文件名→blob 哈希」。「add 完还要 commit」是 Git 新手最大困惑。很多人记成「add 标记为待提交」,但这只是表象。真相是:add 把文件内容物化成 blob 并登记进索引,commit 把索引定稿成一棵 tree 加 commit 对象。
理解索引,你不仅解开困惑,更理解了 Git 的「灵活性」——你可以 add 文件 A 的改动、不 add 文件 B(把它们的改动分到不同 commit),这种「精细控制每次提交内容」的能力,是 Git 相对其他 VCS 的优势,而它建立在索引模型上。
工作区(Working) 暂存区(Index/Staging) 仓库(Repository) 你看到的文件 ─add─► 下次commit的草稿 ─commit─► 对象库(.git/objects) ◄─checkout─ ◄─┘
.git/index,记录「文件名 → blob 哈希 + 元信息」的列表,是「下一次 commit 的草稿」。.git/objects/,存所有 blob/tree/commit 对象,不可变。git add 干的事git add hello.txt: 1. 读 hello.txt 内容 2. 算哈希, 存成 blob 进对象库(若已存在则跳过, 去重) 3. 在索引里更新/添加一条: "hello.txt → 这个 blob 哈希"
注意:add 只动索引(草稿),没创建 commit。文件内容的 blob 虽进了对象库,但还没有 tree/commit 引用它——它是「待用」状态。
git commit 干的事(下一节详述)git commit: 1. 把当前索引的「文件名→blob」列表, 构建成一棵 tree 对象 2. 创建一个 commit 对象: 指向这棵 tree + parent(上次 commit) + 信息 3. 移动当前分支指针到新 commit
设想没有索引、commit 直接拍工作区快照——那你改了 5 个文件,只能全部一起提交,无法拆分。索引让你「挑哪些改动进这次 commit」:add A、add B,然后 commit(只含 A、B 的改动),C 的改动留到下次。这种「精细控制提交粒度」是 Git 的核心体验。
{文件名: blob哈希}。add 文件:读内容→hash_object 存 blob→更新索引里该文件名的条目。status:对比「工作区文件」与「索引」与「当前 commit 的 tree」,显示哪些 add 了、哪些改了没 add。git add = 把文件存成 blob + 在索引记「文件名→blob 哈希」,只动索引,不创建 commit。.git/index。下一节讲 commit——把索引定稿成快照。