开始前,会这些就够了
- 用过 git add 和 git status
- 知道文件内容与文件名不同
遇到不熟悉的词,先看这 3 个解释
- 哈希
- 哈希用规定的计算方法,把输入数据变成便于比较的结果;常见摘要算法会输出固定长度。同样的输入得到同样的结果,但不同输入仍可能得到相同结果。
- 磁盘
- 日常使用中的磁盘通常指保存系统、应用和文件的硬盘类设备,包括机械硬盘和固态硬盘。与普通运行内存不同,它们不需要持续供电来维持已经写入的数据。
- Git暂存区
- 暂存区记录你准备放进下一次提交的文件内容。把修改加入暂存区后,可以先检查这次准备提交的内容;继续编辑文件时,新修改不会自动替换已经暂存的版本。
一个文件有几千行,你只加了一个空格,Git 就把它列为已修改。可你又发现,改完再改回去,修改提示会消失。Git 不是在旁边记录每次键盘操作;它关心的是当前状态与某个已保存状态之间有什么差别。
内容有摘要,文件名另有记录
Git 把文件内容保存为数据对象,通常叫 blob,并根据对象内容和类型、长度等头部信息计算对象编号。相同字节内容在同一种对象格式下可复用同一个 blob。它不是只取文件名当编号,也不是把文件最后修改时间当成内容本身。
那文件名去了哪里?目录树对象记录名字、文件模式以及它指向的内容对象或子目录。提交对象再连接一次目录快照和历史信息。把内容与名字分开,就能解释为什么两条不同路径可以引用相同内容,也能解释文件内容未变时,改名仍属于项目状态变化。
“改了”必须先说是和谁比较
日常最重要的三处状态,是正在编辑的工作区、为下一次提交准备的暂存区,以及已经保存的提交。假设原文件写着 blue,你改成 green 后执行 git add,再改成 red。此时暂存区保留的是 green,工作区则是 red,不会因为继续编辑就自动同步暂存区。
所以这个文件可能同时出现在已暂存与未暂存改动里。普通 git diff 主要比较工作区和暂存区;git diff --cached 比较暂存区和已提交状态。两者都没有显示某段变化时,应先检查自己选的比较对象,而不是立刻认定 Git 漏记了编辑过程。
不必每次都从头检查所有字节
文件很多时,完整读取所有内容会花时间。Git 的索引除了记录内容对象,还会保存文件状态信息,并可利用文件系统提供的时间、大小等信息以及其他机制减少不必要的检查。这些是帮助筛选的线索,不能简单理解为“修改时间变了就一定有内容改动”。
当需要确认内容时,Git 会按相关规则比较它。你把一个已跟踪文件改了又完整改回原样,最终可能不再有内容差异,即使文件曾经被写过。屏幕上的红绿行则是把两份内容作差异展示的结果,不是仓库逐个保存了你打字、删除、撤销的动作录像。
看起来一样,也要检查换行和处理规则
空格、末尾换行和不同换行表示都可能影响字节内容。但 Git 又能按属性和配置把文本换行统一后保存,因此工作区的原始字节与仓库保存的字节未必完全相同。看到整篇都变红时,先检查是否换行格式或编码改变,比重新手工复制所有文字更有效。
理解机制后,可以养成一个简单习惯:提交前分别查看未暂存差异和已暂存差异,确认这次真正准备保存的内容。识别改动也不等于自动备份所有编辑;尚未保存到 Git 对象或提交中的内容不能靠“Git 应该看见过”来保证找回。
记住这三点
- Git 主要比较状态,内容对象与文件名、目录结构分别保存。
- 暂存之后再编辑,会形成新的未暂存差异;提交准备的是暂存区内容。
- 时间和大小可帮助加速检查,换行与过滤规则也会影响内容表示。
别把例子用过头
- 本文没有把对象编号说成任意内容绝对不碰撞的数学保证。
- git diff 没输出,不等于工作区、暂存区与历史在所有方面都一致。
- 这里讨论常见已跟踪普通文件;子模块、特殊索引标记等需要另看规则。
自己试一小步
怎样让同一个练习文件同时拥有已暂存和未暂存的修改?
- 在单独的练习仓库中,使用一个已经提交过的普通文本文件,不在工作项目上试验。
- 分两次修改不同文字,只在两次修改之间暂存该文件。
- 分别阅读 git status、git diff 和 git diff --cached,记录每条命令正在比较哪两处状态。
做到这些,就算完成
- 能够指出下一次普通提交会包含哪个版本。
- 解释时用工作区、暂存区、提交三处状态,而不是只说“旧文件”和“新文件”。
- 只修改练习文件,不需要强制重置、清理目录或推送远端。
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- Pro Git:Git 对象 (新标签页)↗
blob、tree、commit 的职责,内容与头部生成对象编号。
- Pro Git:记录每次更新到仓库 (新标签页)↗
已暂存与未暂存状态、两种 diff 的比较范围、提交快照。
- git-update-index (新标签页)↗
索引文件状态信息、stat 检查与 refresh 的含义。
- gitattributes (新标签页)↗
文本换行规范化、工作区编码与仓库内容之间的转换。
找一份资料继续练
先选一项,按下面的范围继续学;不必从头读完整门课程。
Pro Git 中文版:保存改动、看历史和合并分支 (新标签页)↗
只读 1.3 和第 2 章的文件状态与差异比较,在临时仓库改一个空格、暂存、再改回,观察每次比较的是哪两个状态。
查看学习准备与访问说明 →