7、Git工作区与暂存区:工作区、暂存区、版本库关系、git add原理、git commit原理
说实话,我刚用Git那会儿,最困惑的就是这三个区域到底怎么玩的。工作区、暂存区、版本库,听起来像三个黑盒子。后来我踩了不少坑,才真正搞明白它们之间的关系。今天我就用最直白的方式,把这块讲透。
7.1 三个区域,一张图说清楚
先看这张图,我亲手画的。你盯着看30秒,基本就懂了。
嗯,这张图我建议你保存下来。每次搞混了就拿出来看一眼。
7.2 工作区:你眼睛看到的文件
工作区,说白了就是你电脑上那个项目文件夹。你打开VS Code、Sublime或者记事本,看到的那些.py、.js、.md文件,全都在工作区里。
我举个例子。你新建一个项目,里面有个index.html。你改了它,保存了。这时候变化只发生在工作区。Git知道吗?知道。但Git不会自动帮你记录。
关键认知:工作区是「未受Git管理」的区域。你在这里改得翻天覆地,Git也只是默默看着,不会做任何记录。
7.3 暂存区:一个神奇的中间地带
暂存区,英文叫Staging Area,也有人叫Index。它其实就是一个文件,藏在.git/index里。但你别小看它,它是Git设计里最精妙的地方之一。
我个人习惯把暂存区理解成「购物车」。你去超市买东西,看到好的先放购物车里,最后到收银台统一结账。暂存区就是这个购物车——你先git add把文件放进去,最后git commit一次性结账。
我的经验:我刚开始用Git时,总是一次性git add .把所有文件都扔进去。后来发现这样不好。比如你改了A文件(功能代码)和B文件(调试日志),应该分开add、分开commit。这样以后查历史记录时,每个commit的意图才清晰。
7.4 版本库:Git的心脏
版本库就是.git目录里的那一堆东西。你所有提交的历史、所有的分支、所有的标签,全存在这里。它才是Git真正「记住」你的地方。
我记得有一次,同事不小心删了工作区里的文件,急得满头大汗。我说别慌,只要commit过,版本库里就有备份。果然,一个git checkout就全回来了。这就是版本库的价值——它是你的后悔药。
| 区域 | 位置 | 数据安全性 | 是否被Git跟踪 |
|---|---|---|---|
| 工作区 | 项目根目录 | 低(可被删除) | 否(未add前) |
| 暂存区 | .git/index | 中(可被覆盖) | 是(已add后) |
| 版本库 | .git/objects | 高(不可变) | 是(已commit后) |
7.5 git add 原理:到底发生了什么?
很多人以为git add就是把文件「复制」到暂存区。其实不是。Git没那么笨,它不会复制整个文件。
git add真正做的事情是:
- 计算文件的SHA-1哈希值(一个40位的十六进制字符串)
- 把文件内容压缩后存入
.git/objects目录 - 在
.git/index中记录这个文件的路径、哈希值、修改时间等信息
说白了,git add就是给文件拍了一张「快照」,然后把快照的索引记在暂存区里。文件本身还在工作区,没动。
避坑指南:我曾经犯过一个错——改了文件后忘了git add,直接git commit。结果commit了个寂寞,改的内容根本没进去。记住:git commit只提交暂存区里的内容,工作区里的改动它不管。
7.6 git commit 原理:永久存档
git commit做的事情更简单,但也更关键:
- 把暂存区里的所有「快照」打包成一个commit对象
- 这个commit对象包含:作者信息、时间戳、提交信息、父commit的哈希值
- 把这个commit对象存入
.git/objects - 更新当前分支指针,指向这个新commit
你想想看,每次commit,Git都记录了三样东西:谁在什么时候做了什么改动。这就是版本管理的核心。
我的建议:commit信息一定要写清楚。别写什么「fix bug」「update」这种废话。我见过最离谱的commit信息是「111」和「asdf」。三个月后回头看,鬼知道当时改了啥。好的commit信息应该是:「修复用户登录时密码验证失败的bug」——一看就懂。
7.7 三个区域的实战操作
光说不练假把式。我们走一遍实际流程:
# 1. 查看工作区状态
git status
# 2. 把文件加入暂存区
git add index.html
git add src/ # 也可以加整个目录
# 3. 查看暂存区内容
git diff --cached # 只看暂存区和工作区的差异
# 4. 提交暂存区
git commit -m "添加首页HTML结构"
# 5. 跳过暂存区直接提交(慎用)
git commit -a -m "直接提交所有改动"
警告:git commit -a会跳过暂存区,直接把工作区里所有已跟踪文件的改动提交。新手慎用。我建议你老老实实走add → commit两步,养成好习惯。
7.8 为什么Git要设计暂存区?
你可能会问:为什么不能直接从工作区到版本库?多此一举嘛。
其实不是。暂存区给了你一个「后悔和整理」的空间。比如你改了10个文件,但只想提交其中3个。没有暂存区,你只能要么全提交,要么一个一个提交。有了暂存区,你可以先git add那3个,然后git commit,剩下的7个下次再说。
我个人觉得,这是Git比SVN高明的地方之一。SVN没有暂存区,每次提交都是全量。Git给了你更细粒度的控制权。
一句话总结:工作区是你写代码的地方,暂存区是你挑拣代码的地方,版本库是你保存代码的地方。三个区域各司其职,缺一不可。
好了,这一章就到这里。记住这三个区域的关系,后面的分支、合并、回退操作,你才能玩得转。
公众号:蓝海资料掘金营,微信deep3321