暂存区详解
进阶
视频演示
暂存区详解:暂存区 vs 本地仓库
🤔 你的问题
- 暂存区和 Git 本地仓库有什么区别?
- 暂存区的数据怎么维护?
📊 Git 的三个区域
完整流程
工作区(Working Directory)
↓ git add
暂存区(Staging Area / Index)
↓ git commit
本地仓库(Local Repository)
↓ git push
远程仓库(Remote Repository)
详细说明
1. 工作区(Working Directory)
位置: 你的项目文件夹(除了 .git 文件夹)
内容: 你正在编辑的文件
特点:
- 你可以直接修改文件
- Git 可以追踪这些文件
- 但修改还没有被 Git 记录
例子:
project/
├── .git/ ← Git 仓库(不包括在工作区)
├── app.py ← 工作区(你正在编辑)
└── utils.py ← 工作区(你正在编辑)
2. 暂存区(Staging Area / Index)
位置: .git/index 文件(隐藏文件)
内容: 准备提交的文件快照
特点:
- 一个中间区域
- 你可以选择性地添加文件
- 只有添加到暂存区的文件才会被提交
- 数据存储在
.git/index文件中
作用:
- 让你选择要提交哪些文件
- 可以分批次提交
- 可以预览提交内容
3. 本地仓库(Local Repository)
位置: .git/objects/ 文件夹
内容: 已提交的代码历史
特点:
- 存储所有提交记录
- 包含完整的版本历史
- 数据存储在
.git/objects/中 - 一旦提交,就很难修改(需要特殊操作)
🔍 暂存区 vs 本地仓库的区别
核心区别
| 特性 | 暂存区(Staging Area) | 本地仓库(Local Repository) |
|---|---|---|
| 位置 | .git/index 文件 |
.git/objects/ 文件夹 |
| 作用 | 准备提交的文件 | 已提交的代码历史 |
| 可修改性 | ✅ 容易修改(可以添加/删除) | ❌ 不容易修改(已提交) |
| 持久性 | ⚠️ 临时(提交后清空) | ✅ 永久(除非删除仓库) |
| 选择性 | ✅ 可以选择文件 | ❌ 提交时包含所有暂存的文件 |
| 查看方式 | git status(绿色) |
git log |
详细对比
暂存区(Staging Area)
# 添加到暂存区
git add app.py
# 状态
git status
# 输出:
# Changes to be committed:
# modified: app.py (绿色,表示在暂存区)特点:
- ✅ 可以随时添加文件:
git add file1.py file2.py - ✅ 可以移除文件:
git reset file1.py - ✅ 可以清空:
git reset - ⚠️ 提交后自动清空
- ⚠️ 如果删除
.git文件夹,暂存区也会丢失
本地仓库(Local Repository)
# 提交到本地仓库
git commit -m "Update app"
# 查看提交历史
git log
# 输出:
# commit abc1234...
# Author: Your Name
# Date: ...
# Update app特点:
- ✅ 永久存储(除非删除仓库)
- ✅ 包含完整的提交历史
- ✅ 可以查看、回退、分支
- ❌ 不容易修改(需要
git commit --amend或git reset) - ❌ 提交后包含所有暂存的文件
🛠️ 暂存区的数据维护
暂存区的存储位置
位置: .git/index 文件
这是一个二进制文件,存储:
- 文件的路径
- 文件的内容哈希
- 文件的时间戳
- 文件的权限
暂存区的操作
1. 添加文件到暂存区
# 添加单个文件
git add app.py
# 添加多个文件
git add app.py utils.py
# 添加所有修改的文件
git add .
# 添加所有文件(包括新文件)
git add -A发生了什么:
- Git 读取文件内容
- 计算文件内容的哈希值
- 将文件信息写入
.git/index - 文件内容存储在
.git/objects/中(作为对象)
2. 从暂存区移除文件
# 移除单个文件(但保留工作区的修改)
git reset app.py
# 或
git restore --staged app.py
# 清空整个暂存区
git reset发生了什么:
- 从
.git/index中移除文件信息 - 文件仍然在工作区(你的修改还在)
- 文件对象仍然在
.git/objects/中(不会删除)
3. 查看暂存区内容
# 查看暂存区的状态
git status
# 查看暂存区和工作区的差异
git diff --staged
# 或
git diff --cached
# 查看暂存区的文件列表
git ls-files --stage4. 修改暂存区的内容
# 修改文件后,需要重新添加到暂存区
vim app.py # 修改文件
git add app.py # 重新添加到暂存区(覆盖之前的)
# 或者,直接修改暂存区中的文件
git add app.py # 添加到暂存区
vim app.py # 修改文件
git add app.py # 再次添加(更新暂存区)📝 实际例子
例子 1: 理解暂存区的作用
# 1. 修改了 3 个文件
vim app.py # 修改
vim utils.py # 修改
vim config.py # 修改
# 2. 查看状态
git status
# 输出:
# modified: app.py (红色,工作区)
# modified: utils.py (红色,工作区)
# modified: config.py (红色,工作区)
# 3. 只添加 app.py 到暂存区
git add app.py
# 4. 查看状态
git status
# 输出:
# Changes to be committed:
# modified: app.py (绿色,暂存区)
#
# Changes not staged for commit:
# modified: utils.py (红色,工作区)
# modified: config.py (红色,工作区)
# 5. 提交(只提交 app.py)
git commit -m "Update app.py"
# 只有 app.py 被提交,utils.py 和 config.py 还在工作区
# 6. 查看状态
git status
# 输出:
# Changes not staged for commit:
# modified: utils.py (红色,工作区)
# modified: config.py (红色,工作区)
# 暂存区已清空(因为已提交)例子 2: 暂存区的维护
# 1. 添加文件到暂存区
git add app.py
# .git/index 文件被更新,包含 app.py 的信息
# 2. 修改 app.py
vim app.py
# 工作区的 app.py 已修改
# 但暂存区还是旧版本
# 3. 查看差异
git diff # 工作区 vs 暂存区(显示修改)
git diff --staged # 暂存区 vs 本地仓库(显示已暂存的内容)
# 4. 更新暂存区
git add app.py # 重新添加,更新暂存区
# 5. 或者,移除暂存区的内容
git reset app.py # 从暂存区移除(但工作区的修改还在)例子 3: 暂存区的生命周期
# 初始状态
git status
# 输出:nothing to commit, working tree clean
# 暂存区:空
# 本地仓库:有之前的提交
# 修改文件
vim app.py
git status
# 输出:
# modified: app.py (红色,工作区)
# 暂存区:空
# 本地仓库:有之前的提交
# 添加到暂存区
git add app.py
git status
# 输出:
# Changes to be committed:
# modified: app.py (绿色,暂存区)
# 暂存区:有 app.py
# 本地仓库:有之前的提交
# 提交
git commit -m "Update app"
git status
# 输出:nothing to commit, working tree clean
# 暂存区:空(已清空)
# 本地仓库:有新的提交(包含 app.py)🔧 暂存区的数据维护机制
1. 自动维护
Git 自动维护:
- 当你执行
git add时,Git 自动更新.git/index - 当你执行
git commit时,Git 自动清空暂存区 - 当你执行
git reset时,Git 自动更新.git/index
2. 手动维护
你可以手动操作:
git add- 添加文件到暂存区git reset- 从暂存区移除文件git restore --staged- 从暂存区移除文件(新命令)
3. 暂存区的持久性
暂存区的数据:
- ✅ 存储在
.git/index文件中 - ✅ 即使关闭终端,暂存区的内容还在
- ⚠️ 如果删除
.git文件夹,暂存区也会丢失 - ⚠️ 提交后,暂存区自动清空
4. 暂存区的数据结构
.git/index 文件包含:
- 文件路径
- 文件内容的 SHA-1 哈希
- 文件的时间戳
- 文件的权限信息
- 指向
.git/objects/中实际文件内容的指针
💡 为什么需要暂存区?
1. 选择性提交
# 修改了多个文件,但只想提交部分
vim app.py
vim utils.py
vim test.py
# 只提交 app.py
git add app.py
git commit -m "Update app"
# utils.py 和 test.py 还在工作区,可以继续修改2. 预览提交内容
# 添加到暂存区后,可以预览
git add app.py
git diff --staged # 查看将要提交的内容
# 确认无误后再提交
git commit -m "Update app"3. 分批次提交
# 修改了多个文件
vim file1.py
vim file2.py
vim file3.py
# 分批次提交
git add file1.py
git commit -m "Add feature 1"
git add file2.py
git commit -m "Add feature 2"
git add file3.py
git commit -m "Add feature 3"4. 撤销操作
# 添加到暂存区后,发现有问题
git add app.py
# 可以轻松移除
git reset app.py
# 文件还在工作区,可以继续修改🎯 关键理解
暂存区 vs 本地仓库
| 操作 | 暂存区 | 本地仓库 |
|---|---|---|
| 添加 | git add |
git commit |
| 查看 | git status(绿色) |
git log |
| 修改 | 容易(重新 add) | 困难(需要特殊操作) |
| 清空 | 提交后自动清空 | 不会清空(永久存储) |
| 作用 | 准备提交 | 已提交的历史 |
数据维护
- 暂存区:存储在
.git/index,由 Git 自动维护 - 本地仓库:存储在
.git/objects/,由 Git 自动维护 - 你可以操作:添加、移除、查看暂存区的内容
- Git 自动处理:提交时清空暂存区,创建新的提交对象
📋 总结
暂存区的特点
- 临时性:提交后自动清空
- 选择性:可以选择要提交的文件
- 可修改性:可以随时添加/移除文件
- 预览性:可以预览将要提交的内容
本地仓库的特点
- 永久性:提交后永久存储
- 完整性:包含所有提交历史
- 不可变性:不容易修改(需要特殊操作)
- 历史性:可以查看、回退、分支
记住
- 暂存区 = 准备提交的文件(临时、可选择)
- 本地仓库 = 已提交的代码历史(永久、完整)
- 暂存区的数据 = 存储在
.git/index,由 Git 自动维护
暂存区就像购物车,你可以选择要买什么,确认后再结账(提交)!