Skip to content

Git 工作区、暂存区和版本库

本章将深入探讨 Git 的三个核心概念:工作区、暂存区和版本库。理解这三个区域的作用和相互关系是掌握 Git 的关键。

三个区域概览

┌─────────────────────────────────────────────────────────────────┐
│                        Git 项目结构                              │
├─────────────────────────────────────────────────────────────────┤
│  工作区 (Working Directory)                                     │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  • 实际的项目文件                                        │    │
│  │  • 可以编辑、创建、删除文件                               │    │
│  │  • Git 监控但不直接管理                                  │    │
│  └─────────────────────────────────────────────────────────┘    │
│                              │                                   │
│                         git add                                  │
│                              ↓                                   │
│  暂存区 (Staging Area / Index)                                  │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  • 临时存储即将提交的文件快照                             │    │
│  │  • 精确控制提交内容                                      │    │
│  │  • 位于 .git/index 文件中                               │    │
│  └─────────────────────────────────────────────────────────┘    │
│                              │                                   │
│                        git commit                                │
│                              ↓                                   │
│  版本库 (Repository)                                            │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  • 存储完整的项目历史                                    │    │
│  │  • 包含所有提交、分支、标签                              │    │
│  │  • 位于 .git 目录中                                     │    │
│  └─────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

工作区 (Working Directory)

定义和特点

工作区是你实际工作的地方,包含项目的所有文件和文件夹(除了 .git 目录)。

特点:

  • 📁 包含项目的实际文件
  • ✏️ 可以自由编辑、创建、删除文件
  • 👀 Git 会监控文件变化但不自动保存
  • 🔄 可以随时恢复到任何历史版本

工作区操作示例

bash
# 创建演示项目
mkdir git-areas-demo
cd git-areas-demo
git init

# 在工作区创建文件
echo "# 项目说明" > README.md
echo "print('Hello, World!')" > main.py
mkdir src
echo "# 工具函数" > src/utils.py

# 查看工作区状态
git status

输出:

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        README.md
        main.py
        src/

nothing added to commit but untracked files present (use "git add" to track)

工作区文件状态

工作区中的文件可能处于以下状态:

  1. 未跟踪 (Untracked):新创建的文件
  2. 已修改 (Modified):已跟踪但被修改的文件
  3. 已删除 (Deleted):被删除的已跟踪文件
bash
# 演示不同状态
git add README.md main.py src/utils.py
git commit -m "初始提交"

# 修改已跟踪文件
echo "更新内容" >> README.md

# 创建新文件
echo "新功能" > feature.py

# 删除文件
rm main.py

# 查看状态
git status

输出:

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md
        deleted:    main.py

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        feature.py

no changes added to commit (use "git add" or "git commit -a")

暂存区 (Staging Area)

定义和特点

暂存区(也称为索引 Index)是工作区和版本库之间的缓冲区,用于准备下次提交的内容。

特点:

  • 🎯 精确控制提交内容
  • 📦 可以部分暂存文件修改
  • 🔄 可以多次修改暂存内容
  • 💾 存储在 .git/index 文件中

暂存区操作

1. 添加文件到暂存区

bash
# 添加单个文件
git add README.md

# 添加多个文件
git add main.py feature.py

# 添加目录
git add src/

# 添加所有修改
git add .

# 添加所有已跟踪文件的修改
git add -u

# 交互式添加
git add -i

2. 查看暂存区内容

bash
# 查看暂存区状态
git status

# 查看暂存区与工作区的差异
git diff

# 查看暂存区与上次提交的差异
git diff --staged
# 或
git diff --cached

3. 从暂存区移除文件

bash
# 从暂存区移除文件(保留工作区修改)
git restore --staged README.md

# 或使用旧语法
git reset HEAD README.md

# 移除所有暂存的修改
git restore --staged .

部分暂存功能

Git 允许你只暂存文件的部分修改:

bash
# 创建一个文件进行演示
cat > example.py << EOF
def function1():
    print("第一个函数")

def function2():
    print("第二个函数")

def function3():
    print("第三个函数")
EOF

git add example.py
git commit -m "添加示例函数"

# 修改多个函数
cat > example.py << EOF
def function1():
    print("第一个函数 - 已更新")
    return "updated"

def function2():
    print("第二个函数")

def function3():
    print("第三个函数 - 已更新")
    return "updated"
EOF

# 交互式部分暂存
git add -p example.py

Git 会逐个显示修改块,你可以选择:

  • y - 暂存这个修改块
  • n - 不暂存这个修改块
  • s - 分割修改块
  • q - 退出

版本库 (Repository)

定义和特点

版本库是 Git 存储项目完整历史的地方,包含所有提交、分支、标签等信息。

特点:

  • 📚 存储完整的项目历史
  • 🌳 管理分支和标签
  • 🔒 数据完整性保证
  • 📁 位于 .git 目录中

版本库结构

bash
# 查看 .git 目录结构
ls -la .git/

主要文件和目录:

.git/
├── HEAD              # 指向当前分支
├── config            # 仓库配置
├── description       # 仓库描述
├── index             # 暂存区文件
├── hooks/            # Git 钩子脚本
├── info/             # 排除文件等信息
├── objects/          # Git 对象存储
├── refs/             # 引用存储(分支、标签)
└── logs/             # 引用日志

版本库操作

1. 提交到版本库

bash
# 提交暂存区内容
git commit -m "提交信息"

# 提交并添加所有已跟踪文件的修改
git commit -am "提交信息"

# 修改最后一次提交
git commit --amend -m "新的提交信息"

2. 查看版本库历史

bash
# 查看提交历史
git log

# 简洁格式
git log --oneline

# 图形化显示
git log --graph --oneline

# 查看特定文件的历史
git log -- filename

# 查看提交统计
git log --stat

3. 查看版本库对象

bash
# 查看对象类型
git cat-file -t HEAD

# 查看对象内容
git cat-file -p HEAD

# 查看树对象
git ls-tree HEAD

三个区域的交互

数据流向图

工作区 ←──────────────────────────────────────────────────────→ 版本库
  │                                                           ↑
  │ git add                                                   │
  ↓                                                           │ git checkout
暂存区 ──────────────────→ 版本库                              │
         git commit                                           │

工作区 ←──────────────────────────────────────────────────────┘

常用操作命令

1. 工作区 → 暂存区

bash
git add <file>          # 添加文件
git add .               # 添加所有文件
git add -A              # 添加所有修改(包括删除)
git add -u              # 添加已跟踪文件的修改
git add -p              # 交互式添加

2. 暂存区 → 版本库

bash
git commit -m "message"     # 提交暂存区内容
git commit --amend          # 修改最后一次提交

3. 版本库 → 工作区

bash
git checkout <commit> -- <file>    # 恢复文件到特定版本
git restore <file>                 # 恢复文件到最新提交版本
git reset --hard <commit>          # 重置到特定提交(危险操作)

4. 暂存区 → 工作区

bash
git restore --staged <file>    # 取消暂存
git reset HEAD <file>          # 取消暂存(旧语法)

实际应用场景

场景1:精确控制提交内容

bash
# 同时修改了多个文件,但只想提交部分修改
echo "功能A的修改" >> fileA.txt
echo "功能B的修改" >> fileB.txt
echo "临时调试代码" >> debug.txt

# 只提交功能相关的修改
git add fileA.txt fileB.txt
git commit -m "实现功能A和功能B"

# debug.txt 保留在工作区,不提交

场景2:分阶段开发

bash
# 第一阶段:实现基本功能
echo "基本功能实现" > feature.py
git add feature.py
git commit -m "实现基本功能"

# 第二阶段:添加错误处理
echo "添加错误处理" >> feature.py
git add feature.py
git commit -m "添加错误处理"

# 第三阶段:优化性能
echo "性能优化" >> feature.py
git add feature.py
git commit -m "优化性能"

场景3:实验性修改

bash
# 在工作区进行实验性修改
echo "实验性功能" > experiment.py

# 如果实验成功,添加到暂存区
git add experiment.py

# 如果实验失败,直接丢弃
rm experiment.py
# 或者
git clean -f

高级技巧

1. 暂存区的高级用法

bash
# 查看暂存区的具体内容
git ls-files --stage

# 比较工作区、暂存区、版本库
git diff                    # 工作区 vs 暂存区
git diff --staged          # 暂存区 vs 版本库
git diff HEAD              # 工作区 vs 版本库

2. 工作区的清理

bash
# 查看未跟踪的文件
git clean -n

# 删除未跟踪的文件
git clean -f

# 删除未跟踪的文件和目录
git clean -fd

# 交互式清理
git clean -i

3. 版本库的维护

bash
# 垃圾回收
git gc

# 检查仓库完整性
git fsck

# 查看仓库大小
du -sh .git/

常见问题和解决方案

问题1:暂存区和工作区不一致

bash
# 问题:修改了文件但忘记添加到暂存区
echo "新修改" >> file.txt
git commit -m "提交修改"  # 这不会包含新修改

# 解决:添加修改并修正提交
git add file.txt
git commit --amend --no-edit

问题2:误删了工作区文件

bash
# 恢复已跟踪的文件
git restore deleted_file.txt

# 恢复到特定版本
git restore --source=HEAD~1 file.txt

问题3:暂存区内容错误

bash
# 清空暂存区
git restore --staged .

# 重新选择要暂存的内容
git add correct_file.txt

最佳实践

1. 工作区管理

  • ✅ 保持工作区整洁,及时清理临时文件
  • ✅ 使用 .gitignore 忽略不需要跟踪的文件
  • ✅ 定期检查 git status

2. 暂存区使用

  • ✅ 使用暂存区精确控制提交内容
  • ✅ 利用 git add -p 进行部分暂存
  • ✅ 提交前检查 git diff --staged

3. 版本库维护

  • ✅ 写清晰的提交信息
  • ✅ 保持提交的原子性(一个提交只做一件事)
  • ✅ 定期进行垃圾回收

总结

理解工作区、暂存区和版本库的关系是掌握 Git 的关键:

  • 工作区:你的工作空间,自由编辑文件
  • 暂存区:提交的准备区,精确控制提交内容
  • 版本库:永久存储,保存完整的项目历史

掌握这三个概念后,你就能:

  • ✅ 精确控制每次提交的内容
  • ✅ 安全地进行实验性修改
  • ✅ 有效管理项目的版本历史
  • ✅ 理解 Git 命令的真正含义

在下一章中,我们将学习如何创建和管理 Git 仓库。

本站内容仅供学习和研究使用。