Git: Git添加文件到暂存区详解

暂存区(Staging Area)是Git的独特概念,它位于工作区和版本库之间,让你精确控制每次提交的内容。git add命令将修改添加到暂存区。

1. git add概述

(1) 什么是暂存区?

暂存区是Git三区模型中的关键部分:

100%
graph TB
    subgraph Git三区模型
        W[工作区<br/>Working Directory<br/>实际编辑的文件]
        S[暂存区<br/>Staging Area<br/>准备提交的修改]
        R[版本库<br/>Repository<br/>所有提交历史]
    end
    
    W -->|git add| S
    S -->|git commit| R
    R -->|git checkout| W
    
    style W fill:#fff3cd
    style S fill:#d4edda
    style R fill:#c3e6cb

(2) 为什么需要暂存区?

暂存区提供了精细的提交控制:

优势 说明 示例
选择性提交 不是所有修改都要提交 只提交修复bug的文件,不提交实验代码
分批提交 不同修改分开提交 功能A和功能B分别提交
修改检查 提交前检查内容 确认暂存的修改无误
撤销修改 撤销暂存不影响工作区 暂存了错误文件可以撤销

(3) git add的作用

git add命令将工作区的修改复制到暂存区:


2. 添加流程

(1) 基本语法

BASH
# 添加单个文件
git add <文件名>

# 添加多个文件
git add <文件1> <文件2> <文件3>

# 添加目录下所有文件
git add <目录名>

# 添加当前目录所有文件
git add .

(2) 添加流程详解

100%
sequenceDiagram
    participant W as 工作区
    participant S as 暂存区
    participant R as 版本库
    
    Note over W: 文件状态: Modified/Untracked
    
    W->>S: git add <file>
    Note over S: 复制文件到暂存区<br/>计算SHA-1哈希<br/>更新索引
    
    Note over S: 文件状态: Staged
    
    S->>R: git commit
    Note over R: 文件状态: Committed

(3) 添加后的变化

添加文件到暂存区后:

▶ 示例:添加单个文件

BASH
# 创建新文件
echo "# My Project" > README.md

# 查看状态(未跟踪)
git status
# Untracked files:
#   README.md

# 添加到暂存区
git add README.md

# 查看状态(已暂存)
git status
# Changes to be committed:
#   new file:   README.md

# 查看暂存区内容
git diff --staged
# diff --git a/README.md b/README.md
# new file mode 100644
# index 0000000..e69de29
# --- /dev/null
# +++ b/README.md
# @@ -0,0 +1 @@
# +# My Project

▶ 示例:添加多个文件

BASH
# 创建多个文件
echo "console.log('app');" > app.js
echo "console.log('test');" > test.js
echo "node_modules/" > .gitignore

# 添加多个文件
git add app.js test.js .gitignore

# 查看状态
git status -s
# A  .gitignore
# A  app.js
# A  test.js

# 或者分步添加
git add app.js
git add test.js
git add .gitignore

# 结果相同

3. 添加选项

(1) 批量添加方式

Git提供多种批量添加方式:

BASH
# 添加当前目录所有文件(不包括删除)
git add .

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

# 添加所有文件(包括新文件、修改、删除)
git add -A
# 或
git add --all

# 交互式添加(逐个确认)
git add -p

(2) 选项对比

命令 新文件 已修改 已删除 作用范围
git add <文件> 指定文件
git add . 当前目录
git add -u 整个仓库
git add -A 整个仓库

(3) 交互式添加

git add -p(patch模式)让你逐个确认每个修改块:

BASH
git add -p
# 显示修改块,询问是否暂存
# Stage this hunk [y,n,q,a,d,e,?]?
# y - yes,暂存这个块
# n - no,不暂存
# q - quit,退出
# a - all,暂存这个文件的所有块
# d - discard,不暂存这个文件的所有块
# e - edit,手动编辑这个块
# ? - help,显示帮助

▶ 示例:批量添加对比

BASH
# 创建场景
echo "new file" > new.txt          # 新文件
echo "content" > tracked.txt
git add tracked.txt
git commit -m "Add tracked"
echo "modified" >> tracked.txt     # 已修改
git rm tracked.txt                 # 删除(模拟)

# 使用 git add .
git add .
git status -s
# A  new.txt
# (不处理删除)

# 重置
git reset

# 使用 git add -u
git add -u
git status -s
# D  tracked.txt
# (只处理已跟踪文件的修改和删除)

# 重置
git reset

# 使用 git add -A
git add -A
git status -s
# A  new.txt
# D  tracked.txt
# (处理所有)

4. 暂存区管理

(1) 查看暂存区内容

BASH
# 查看暂存的修改
git diff --staged
# 或
git diff --cached

# 查看暂存区和版本库的差异
git diff --staged HEAD

# 查看暂存区文件列表
git status

(2) 暂存区的特点

暂存区的重要特性:

100%
graph TB
    A[工作区文件] -->|git add| B[暂存区快照]
    B -->|git commit| C[版本库提交]
    
    A -->|继续编辑| D[工作区新版本]
    D -->|git add| E[更新暂存区]
    
    B -.->|不同版本| D
    
    style B fill:#d4edda
    style D fill:#fff3cd

关键理解

(3) 暂存区覆盖

重复git add会覆盖暂存区内容:

BASH
# 第一次添加
echo "version 1" > file.txt
git add file.txt
# 暂存区:version 1

# 修改文件
echo "version 2" > file.txt
# 工作区:version 2
# 暂存区:version 1(未变)

# 再次添加
git add file.txt
# 暂存区:version 2(已更新)

▶ 示例:暂存区与工作区分离

BASH
# 创建并添加文件
echo "Line 1" > file.txt
git add file.txt

# 查看暂存区内容
git diff --staged
# +Line 1

# 继续编辑文件
echo "Line 2" >> file.txt

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

# 查看状态
git status -s
# AM file.txt
# A:暂存区有内容(Line 1)
# M:工作区有新修改(Line 2)

# 更新暂存区
git add file.txt

# 现在暂存区包含所有修改
git diff --staged
# +Line 1
# +Line 2

5. 撤销添加

(1) 撤销暂存

如果暂存了错误的文件,可以撤销暂存:

BASH
# 撤销单个文件的暂存(新语法)
git restore --staged <文件名>

# 撤销单个文件的暂存(旧语法)
git reset HEAD <文件名>

# 撤销所有暂存
git restore --staged .
# 或
git reset

(2) 撤销后的状态

撤销暂存后:

(3) 撤销vs丢弃

注意区分两个操作:

100%
graph TB
    A[已暂存的文件] -->|git restore --staged| B[撤销暂存<br/>工作区保留]
    A -->|git restore| C[丢弃修改<br/>恢复到暂存区版本]
    
    B --> D[状态: Untracked/Modified]
    C --> E[状态: Staged]
    
    style B fill:#d4edda
    style C fill:#f8d7da

▶ 示例:撤销暂存操作

BASH
# 创建并添加文件
echo "test content" > test.txt
git add test.txt
git status -s
# A  test.txt

# 撤销暂存
git restore --staged test.txt
git status -s
# ?? test.txt
# 文件变回未跟踪状态

# 已跟踪文件的撤销
echo "# Project" > README.md
git add README.md
git commit -m "Add README"

echo "new content" >> README.md
git add README.md
git status -s
# M  README.md

# 撤销暂存
git restore --staged README.md
git status -s
#  M README.md
# 文件变回已修改状态,修改内容保留

▶ 示例:交互式添加场景

BASH
# 创建包含多个修改的文件
cat > app.js << 'EOF'
function oldFunction() {
  console.log('old');
}

function newFeature() {
  console.log('new feature');
}

function debugCode() {
  console.log('debug');  // 临时调试代码
}
EOF

git add app.js
git commit -m "Add app"

# 修改文件:包含功能改进和调试代码
cat > app.js << 'EOF'
function oldFunction() {
  console.log('old');
  console.log('improved');  // 功能改进
}

function newFeature() {
  console.log('new feature');
  console.log('enhanced');  // 功能增强
}

function debugCode() {
  console.log('debug');  // 临时调试代码
}
EOF

# 使用交互式添加,只暂存功能改进
git add -p
# 逐个确认每个修改块
# y - 暂存功能改进
# n - 不暂存调试代码

# 提交功能改进
git commit -m "Improve features"

# 调试代码还在工作区,未提交

❓ 常见问题

Q git add . 和 git add -A 有什么区别?
A git add .只处理当前目录及子目录的文件,不包括其他目录的删除。git add -A处理整个仓库的所有文件,包括所有目录的新增、修改和删除。在仓库根目录下两者效果相同,但在子目录中会有差异。
Q 暂存后继续编辑文件会怎样?
A 文件会同时出现在暂存区和工作区,但内容不同。暂存区保存的是添加时的版本,工作区是编辑后的新版本。状态显示为AM或MM。需要再次git add更新暂存区,或者提交暂存区内容后再添加新修改。
Q 如何查看暂存区的内容?
A 使用git diff --stagedgit diff --cached查看暂存的修改内容。这会显示暂存区与上次提交的差异。如果想看具体文件内容,可以用git show :filename查看暂存区的文件。
Q git add会覆盖已暂存的内容吗?
A 是的。对同一文件再次执行git add会更新暂存区的内容为最新版本。这是更新暂存区的正常方式,不是问题而是特性。
Q 如何只添加文件的部分修改?
A 使用git add -p进入交互模式,Git会逐个显示修改块(hunk),你可以选择y暂存、n跳过、e手动编辑。这样可以精确控制哪些修改进入暂存区,实现一个文件的不同修改分开提交。

📖 小节


📝 作业

  1. 基础题:创建一个Git仓库,添加多个文件到暂存区,使用git diff --staged查看暂存内容,然后提交。观察每一步的状态变化。

  2. 进阶题:创建一个文件,添加到暂存区后继续编辑,观察工作区和暂存区的差异。尝试使用git add -p交互式添加,只暂存部分修改。

  3. 挑战题:模拟一个真实场景:修复了两个bug,添加了新功能,还有临时调试代码。使用交互式添加和多次提交,将不同修改分开提交,保持提交历史的清晰性。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏