前置知识: Git

三棵树

2 minIntermediate2026/6/14

Git三棵树模型:工作区、暂存区、本地仓库的状态管理与转换。

1. 三棵树模型

1.1 概念

工作区 (Working Directory)
    │  git add

暂存区 (Staging Area / Index)
    │  git commit

本地仓库 (Repository)
    │  git push

远程仓库 (Remote)

1.2 三棵树的定义

位置内容操作
工作区文件系统实际文件编辑、创建、删除
暂存区.git/index下次提交的快照git addgit rm
本地仓库.git/objects所有提交历史git commit

2. 工作区

2.1 文件状态

工作区中的文件有四种状态:

未跟踪 (Untracked)
    │  git add

已暂存 (Staged)
    │  git commit

已提交 (Committed)
    │  修改文件

已修改 (Modified)
    │  git add

已暂存 (Staged)

2.2 查看状态

git status
# On branch main
# Changes to be committed:        ← 已暂存
#   modified:   index.js
#
# Changes not staged for commit:  ← 已修改未暂存
#   modified:   README.md
#
# Untracked files:                ← 未跟踪
#   new-feature.js

2.3 简洁输出

git status -s
# M  index.js       ← 已暂存的修改
#  M README.md      ← 未暂存的修改
# ?? new-feature.js ← 未跟踪
# A  added.js       ← 新添加到暂存区
# D  deleted.js     ← 已删除(暂存区)
#  D removed.js     ← 已删除(工作区)
# MM both.js        ← 暂存区和工作区都有修改

3. 暂存区

3.1 Index 文件

暂存区存储在 .git/index 文件中,是一个二进制文件,记录了下次提交的文件快照:

# 查看暂存区内容
git ls-files -s
# 100644 abc1234 0    README.md
# 100644 def5678 0    src/index.js
# 100644 ghi9012 0    package.json

3.2 暂存操作

# 添加文件到暂存区
git add file.txt           # 添加单个文件
git add .                  # 添加所有变更
git add -p file.txt        # 交互式添加部分变更
git add -u                 # 添加已跟踪文件的修改

# 从暂存区移除
git rm --cached file.txt   # 移除跟踪但保留文件
git reset file.txt         # 取消暂存

# 查看暂存区与仓库的差异
git diff --staged
git diff --cached          # 同上

3.3 部分暂存

# 交互式添加
git add -p
# Stage this hunk [y,n,q,a,d,/,s,e,?]?
# y - 暂存此块
# n - 不暂存
# s - 分割成更小的块
# e - 手动编辑

4. 本地仓库

4.1 提交到仓库

# 提交暂存区的内容
git commit -m "feat: add user authentication"

# 提交所有已跟踪文件的修改(跳过 git add)
git commit -a -m "fix: resolve login bug"

# 修改上一次提交
git commit --amend -m "feat: add user auth with tests"

4.2 查看仓库状态

# 查看提交历史
git log --oneline -5

# 查看当前提交的 tree
git ls-tree -r HEAD

# 查看引用
git show-ref

5. 三棵树之间的差异

5.1 diff 命令矩阵

命令比较对象说明
git diff工作区 vs 暂存区未暂存的修改
git diff --staged暂存区 vs 仓库已暂存待提交的修改
git diff HEAD工作区 vs 仓库所有未提交的修改
git diff --name-only仅文件名快速查看变更文件

5.2 状态转换

                    git add                    git commit
工作区 ──────────────────────→ 暂存区 ──────────────────────→ 仓库
  │                               │                               │
  │  git diff                     │  git diff --staged            │
  │  (工作区 vs 暂存区)            │  (暂存区 vs 仓库)              │
  │                               │                               │
  │  git checkout -- file         │  git reset HEAD file          │
  │  ←────────────────            │  ←────────────────            │
  │  (丢弃工作区修改)              │  (取消暂存)                    │
  │                               │                               │
  │                                                               │
  │  git diff HEAD (工作区 vs 仓库)                                │
  │  git checkout HEAD -- file (恢复到仓库版本)                     │
  │  ←────────────────────────────────────────                    │

6. 常见操作流程

6.1 标准工作流

# 1. 修改文件
vim src/index.js

# 2. 查看状态
git status

# 3. 查看差异
git diff

# 4. 暂存修改
git add src/index.js

# 5. 确认暂存
git diff --staged

# 6. 提交
git commit -m "feat: add new feature"

# 7. 推送
git push origin main

6.2 修正错误

# 暂存了错误的文件
git reset HEAD wrong-file.js    # 取消暂存

# 工作区修改错误(未暂存)
git checkout -- file.js         # 恢复到暂存区版本
git restore file.js             # Git 2.23+ 推荐方式

# 提交后发现遗漏
git add forgotten-file.js
git commit --amend --no-edit    # 追加到上次提交

# 完全重置到上次提交
git reset --hard HEAD           # 丢弃所有未提交的修改