Skip to content

文件状态与跟踪

文件的四种状态

Git 中的文件处于四种状态之一:

┌─────────────────────────────────────────────────────────┐
│                                                           │
│  未跟踪(Untracked)  ──git add──→  已暂存(Staged)         │
│                                        │                  │
│  未修改(Unmodified) ←──git commit──   │                  │
│       │                                                   │
│       │──编辑文件──→  已修改(Modified) ──git add──→      │
│                                                           │
└─────────────────────────────────────────────────────────┘
状态说明
未跟踪(Untracked)新建文件,Git 不知道它的存在
未修改(Unmodified)已提交,且自上次提交后未发生改动
已修改(Modified)已跟踪文件被修改,但未暂存
已暂存(Staged)修改已添加到暂存区,等待提交

git status 查看状态

git status 是使用最频繁的命令之一,显示工作区和暂存区的状态。

bash
git status

# 输出示例:
# On branch main
# Your branch is up to date with 'origin/main'.
#
# Changes to be committed:
#   (use "git restore --staged <file>..." to unstage)
#         modified:   src/auth.js      ← 已暂存(将进入下次提交)
#         new file:   docs/api.md
#
# 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        ← 已修改但未暂存
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#         temp.log                     ← 未跟踪文件

简短格式

bash
git status -s
# 或
git status --short

# 输出:
# M  src/auth.js    ← 暂存区有修改(左列 M)
#  M README.md      ← 工作区有修改(右列 M)
# A  docs/api.md    ← 新文件已暂存(A = Added)
# ?? temp.log       ← 未跟踪(?? = Untracked)
# D  old-file.txt   ← 已删除

左列表示暂存区状态,右列表示工作区状态:

标志含义
?? 未跟踪(Untracked)
A 新文件已暂存
M 修改已暂存(左)或已修改未暂存(右)
D 删除已暂存(左)或已删除未暂存(右)
R 重命名
C 复制
U 冲突未解决

git add 暂存文件

git add 将文件添加到暂存区(Index),准备下次提交。

bash
# 暂存单个文件
git add README.md

# 暂存多个文件
git add file1.js file2.js

# 暂存整个目录
git add src/

# 暂存所有修改(包括新文件、修改、删除)
git add .
git add --all
git add -A

# 暂存所有已跟踪文件的修改(不包括新文件)
git add -u

区别:git add . vs git add -A vs git add -u

命令新文件修改删除范围
git add .当前目录及子目录
git add -A整个仓库
git add -u整个仓库(已跟踪文件)

注意:在 Git 2.x 中,git add .git add -A 行为已统一,都处理整个仓库。

git add -p 交互式暂存

-p(patch)模式让你可以只暂存文件的部分内容,是精细化提交的强大工具。

bash
git add -p
# 或
git add --patch

交互提示说明

Stage this hunk [y,n,q,a,d,/,s,e,?]?

y - 暂存此块
n - 不暂存此块
q - 退出,不暂存任何剩余内容
a - 暂存此文件的所有块
d - 不暂存此文件的任何块
/ - 搜索匹配正则的块
s - 将当前块分割成更小的块
e - 手动编辑当前块
? - 显示帮助

实际使用示例

假设你修改了一个文件,但想分成两次提交(一次是 bug fix,一次是新功能):

bash
git add -p src/app.js

# 对于 bug fix 相关的块,输入 y(暂存)
# 对于新功能相关的块,输入 n(跳过)

git commit -m "fix: 修复空指针异常"

git add src/app.js
git commit -m "feat: 添加用户头像上传功能"

git rm 删除文件

从 Git 跟踪和工作区中删除文件。

bash
# 删除文件(同时从工作区和暂存区删除)
git rm README.md

# 只从暂存区删除,保留工作区文件(取消跟踪但不删除文件)
git rm --cached README.md

# 强制删除(已修改或已暂存的文件需要 -f)
git rm -f modified-file.txt

# 删除目录
git rm -r old-directory/

# 使用通配符
git rm '*.log'

取消跟踪但保留文件

这在把文件加入 .gitignore 之前已经提交时很有用:

bash
# 取消跟踪 .env 文件(但保留本地文件)
git rm --cached .env

# 添加到 .gitignore
echo ".env" >> .gitignore

git add .gitignore
git commit -m "chore: 停止跟踪 .env 文件"

git mv 移动/重命名文件

git mv 相当于 mv + git rm + git add 的组合。

bash
# 重命名文件
git mv old-name.js new-name.js

# 移动文件到子目录
git mv app.js src/app.js

# 移动并重命名
git mv old/path/file.js new/path/new-name.js
bash
# 等价的手动操作:
mv old-name.js new-name.js
git rm old-name.js
git add new-name.js

Git 能自动检测重命名(即使通过手动 mv 操作),因为它基于内容相似度来判断。

查看文件详细状态

bash
# 查看工作区中已追踪但未暂存的文件列表
git ls-files -m

# 查看暂存区中的文件列表
git ls-files -s

# 查看未跟踪文件
git ls-files -o --exclude-standard

# 查看被忽略的文件
git ls-files --others --ignored --exclude-standard

文件状态流转示例

bash
# 1. 初始状态:创建新文件
echo "Hello" > hello.txt
git status
# Untracked files: hello.txt

# 2. 暂存文件
git add hello.txt
git status
# Changes to be committed: new file: hello.txt

# 3. 提交文件
git commit -m "add hello.txt"
git status
# nothing to commit, working tree clean

# 4. 修改文件
echo "World" >> hello.txt
git status
# Changes not staged for commit: modified: hello.txt

# 5. 暂存修改
git add hello.txt
git status
# Changes to be committed: modified: hello.txt

# 6. 再次提交
git commit -m "update hello.txt"

总结

操作命令文件状态变化
创建新文件Untracked
暂存新文件git add <file>Untracked → Staged
提交git commitStaged → Unmodified
修改文件编辑Unmodified → Modified
暂存修改git add <file>Modified → Staged
取消暂存git restore --staged <file>Staged → Modified
丢弃修改git restore <file>Modified → Unmodified
删除跟踪git rm --cached <file>Unmodified → Untracked