Appearance
文件状态与暂存
概述
Git 通过文件状态来追踪项目中的文件变化。理解文件状态生命周期是掌握 Git 的关键,它能帮助你准确控制哪些修改应该被提交,哪些应该被忽略。
Git 的文件状态分为:未跟踪(Untracked)、未修改(Unmodified)、已修改(Modified)、已暂存(Staged)。文件在这些状态之间流转,最终形成提交历史。
文件状态生命周期
状态流转图
┌─────────────────────────────────────────────────────────────┐
│ Git 文件状态生命周期 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ 未跟踪 │ │
│ │ (Untracked) │ │
│ └──────┬───────┘ │
│ │ │
│ git add │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 未修改 │◄───│ 已暂存 │ │
│ │ (Unmodified) │ │ (Staged) │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ 编辑文件 │ git commit │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 已修改 │ │ 已提交 │ │
│ │ (Modified) │ │ (Committed) │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ git add │ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ 已暂存 │ │
│ │ (Staged) │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘四种状态详解
未跟踪(Untracked)
bash
# 新创建的文件处于未跟踪状态
echo "new file" > new.txt
# 查看状态
git status
# On branch main
# Untracked files:
# new.txt
# 特点:
# - Git 不知道这个文件的存在
# - 不会被纳入版本控制
# - 需要手动添加到暂存区未修改(Unmodified)
bash
# 已提交且未修改的文件处于未修改状态
git status
# On branch main
# nothing to commit, working tree clean
# 特点:
# - 文件内容与仓库中一致
# - 工作目录干净
# - 不需要任何操作已修改(Modified)
bash
# 修改已跟踪的文件
echo "modified content" >> tracked.txt
# 查看状态
git status
# On branch main
# Changes not staged for commit:
# modified: tracked.txt
# 特点:
# - 文件内容与仓库中不同
# - 修改在工作目录中
# - 需要添加到暂存区已暂存(Staged)
bash
# 将修改添加到暂存区
git add tracked.txt
# 查看状态
git status
# On branch main
# Changes to be committed:
# modified: tracked.txt
# 特点:
# - 文件修改已暂存
# - 准备好提交
# - 下次提交会包含这些修改git add 添加文件
基本用法
bash
# 添加单个文件
git add filename.txt
# 添加多个文件
git add file1.txt file2.txt file3.txt
# 添加当前目录下所有文件
git add .
# 添加所有文件(包括删除的文件)
git add --all
# 或
git add -A
# 添加所有修改和删除的文件(不包括新文件)
git add -u
# 添加所有文件(包括未跟踪的文件)
git add *添加指定类型文件
bash
# 添加所有 .php 文件
git add *.php
# 添加所有 .js 文件
git add *.js
# 添加 src 目录下所有文件
git add src/
# 添加多个目录
git add src/ tests/ docs/
# 添加特定模式的文件
git add src/**/*.php交互式添加
bash
# 交互式添加
git add -i
# 输出示例
# staged unstaged path
# 1: unchanged +0/-1 TODO
# 2: unchanged +1/-1 index.html
# 3: unchanged +5/-1 lib/simplegit.rb
#
# *** Commands ***
# 1: status 2: update 3: revert 4: add untracked
# 5: patch 6: diff 7: quit 8: help
# What now>部分暂存(Patch 模式)
bash
# 交互式部分暂存
git add -p filename.txt
# 输出示例
diff --git a/filename.txt b/filename.txt
index abc1234..def5678 100644
--- a/filename.txt
+++ b/filename.txt
@@ -1,5 +1,8 @@
line 1
line 2
+new line 1
+new line 2
line 3
line 4
+new line 3
(1/1) Stage this hunk [y,n,q,a,d,e,?]?
# 选项说明:
# y - 暂存此块
# n - 不暂存此块
# q - 退出
# a - 暂存此文件所有剩余块
# d - 不暂存此文件所有剩余块
# s - 分割成更小的块
# e - 手动编辑
# ? - 帮助添加时设置权限
bash
# 添加文件并设置可执行权限
git add --chmod=+x script.sh
# 添加文件并取消可执行权限
git add --chmod=-x script.sh
# 查看权限变化
git diff --cached添加的注意事项
bash
# 注意:git add 是幂等的
# 多次添加同一个文件不会产生问题
# 添加后继续修改
git add file.txt
echo "more content" >> file.txt
# 此时文件同时处于已暂存和已修改状态
git status
# Changes to be committed:
# modified: file.txt
#
# Changes not staged for commit:
# modified: file.txt
# 需要再次添加
git add file.txtgit 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/App.php
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: src/Controller.php
Untracked files:
(use "git add <file>..." to include in what will be committed)
src/NewClass.php
no changes added to commit but untracked files present简洁模式
bash
# 简洁输出
git status -s
# 或
git status --short
# 输出示例
M src/Controller.php # 已修改(未暂存)
M src/App.php # 已修改(已暂存)
MM src/Model.php # 已修改(部分暂存)
A src/NewClass.php # 新文件(已暂存)
?? src/Unknown.php # 未跟踪
D src/OldClass.php # 已删除(已暂存)
D src/Deleted.php # 已删除(未暂存)
R old.txt -> new.txt # 重命名
C copy.txt # 复制
# 状态码说明:
# ?? - 未跟踪
# A - 新添加到暂存区
# M - 已修改
# D - 已删除
# R - 重命名
# C - 复制
# 第一列表示暂存区状态
# 第二列表示工作目录状态分支状态
bash
# 查看分支状态
git status -sb
# 或
git status --short --branch
# 输出示例
## main...origin/main
M src/Controller.php
# 显示分支差异
git status -v
# 显示暂存区与仓库的差异
git status -vv
# 显示暂存区和工作目录的差异忽略子模块
bash
# 忽略子模块变化
git status --ignore-submodules
# 忽略脏子模块
git status --ignore-submodules=dirty
# 忽略所有子模块
git status --ignore-submodules=all显示被忽略的文件
bash
# 显示被忽略的文件
git status --ignored
# 输出示例
On branch main
Ignored files:
.env
vendor/
node_modules/查看特定文件状态
bash
# 查看特定文件状态
git status src/App.php
# 查看目录状态
git status src/
# 使用通配符
git status "*.php".gitignore 忽略文件
基本语法
bash
# .gitignore 文件语法
# 1. 注释
# 这是注释
# 2. 忽略特定文件
.env
config.local.php
# 3. 忽略特定扩展名的文件
*.log
*.tmp
*.swp
# 4. 忽略整个目录
vendor/
node_modules/
build/
# 5. 忽略目录下的所有文件
logs/*
temp/*
# 6. 不忽略特定文件(例外规则)
!important.log
!important/
# 7. 忽略根目录下的文件(不影响子目录)
/README.md
/.env
# 8. 忽略所有目录下的特定文件
**/temp.txt
# 9. 忽略特定目录下的所有文件
src/**/temp/
# 10. 使用方括号匹配
*.[oa] # 忽略 .o 和 .a 文件
*.[xX][mM][lL] # 忽略 .xml(不区分大小写)通配符详解
bash
# * 匹配任意字符(不包括 /)
*.log # 匹配所有 .log 文件
src/*.log # 匹配 src 目录下的 .log 文件
# ** 匹配任意字符(包括 /)
**/test # 匹配任意目录下的 test
src/**/*.php # 匹配 src 下所有目录的 .php 文件
# ? 匹配单个字符
file?.txt # 匹配 file1.txt, file2.txt 等
# [] 匹配字符集
file[123].txt # 匹配 file1.txt, file2.txt, file3.txt
file[a-z].txt # 匹配 filea.txt 到 filez.txt
# ! 取反
*.log
!important.log # 不忽略 important.log
# / 目录分隔符
/build/ # 忽略根目录下的 build 目录
build/ # 忽略所有 build 目录常用 .gitignore 模板
PHP 项目
bash
# .gitignore for PHP project
# 依赖
/vendor/
node_modules/
# 编译输出
/build/
/dist/
# 日志
*.log
/logs/
# 缓存
*.cache
/cache/
# 环境配置
.env
.env.local
.env.*.local
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# 操作系统
.DS_Store
Thumbs.db
# 测试
.phpunit.result.cache
/coverage/
# 临时文件
*.tmp
*.bak
*.backup前端项目
bash
# .gitignore for Frontend project
# 依赖
node_modules/
bower_components/
# 构建输出
dist/
build/
.next/
out/
# 日志
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# 环境配置
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# 缓存
.cache/
.parcel-cache/
# IDE
.idea/
.vscode/
*.swp
*.swo
# 操作系统
.DS_Store
Thumbs.db
# 测试
coverage/
# 临时文件
*.log
*.tmpLaravel 项目
bash
# .gitignore for Laravel project
# 依赖
/vendor/
node_modules/
# 构建输出
/public/build
/public/hot
# 存储
/storage/*.key
/storage/logs/*
/storage/framework/cache/*
/storage/framework/sessions/*
/storage/framework/views/*
# 环境配置
.env
.env.backup
.env.production
.phpunit.result.cache
# IDE
.idea/
.vscode/
*.swp
# 操作系统
.DS_Store
Thumbs.db
# 其他
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log创建 .gitignore 文件
bash
# 创建 .gitignore 文件
touch .gitignore
# 使用模板创建
curl -o .gitignore https://www.toptal.com/developers/gitignore/api/php,macos,windows
# 或使用在线生成器
# https://www.toptal.com/developers/gitignore
# 添加到仓库
git add .gitignore
git commit -m "chore: 添加 .gitignore 配置"检查忽略规则
bash
# 检查文件是否被忽略
git check-ignore -v .env
# 输出示例
.gitignore:18:.env .env
# 检查多个文件
git check-ignore -v file1.txt file2.txt
# 查看所有被忽略的文件
git status --ignored清理已跟踪的忽略文件
bash
# 从仓库中删除但保留本地文件
git rm --cached .env
# 从仓库中删除整个目录
git rm --cached -r vendor/
# 从仓库中删除所有被忽略的文件
git rm --cached -r .
git add .
# 提交更改
git commit -m "chore: 从版本控制中移除被忽略的文件"全局 .gitignore
bash
# 创建全局 .gitignore
touch ~/.gitignore_global
# 配置全局忽略
git config --global core.excludesfile ~/.gitignore_global
# 添加常见忽略规则
cat > ~/.gitignore_global << 'EOF'
# 操作系统
.DS_Store
Thumbs.db
# IDE
.idea/
.vscode/
*.swp
*.swo
# 临时文件
*~
*.log
EOF文件状态操作
查看文件差异
bash
# 查看工作目录与暂存区的差异
git diff
# 查看暂存区与仓库的差异
git diff --staged
# 或
git diff --cached
# 查看工作目录与仓库的差异
git diff HEAD
# 查看特定文件差异
git diff filename.txt
# 查看两个提交之间的差异
git diff commit1 commit2
# 查看统计信息
git diff --stat
# 查看简要信息
git diff --name-only撤销修改
bash
# 撤销工作目录的修改(未暂存)
git restore filename.txt
# 或
git checkout -- filename.txt
# 撤销暂存区的修改(取消暂存)
git restore --staged filename.txt
# 或
git reset HEAD filename.txt
# 完全撤销(工作目录和暂存区)
git restore --source=HEAD filename.txt
# 撤销所有修改
git restore .
# 撤销特定目录的修改
git restore src/删除文件
bash
# 删除文件并暂存删除
git rm filename.txt
# 删除文件但保留本地副本
git rm --cached filename.txt
# 删除整个目录
git rm -r directory/
# 强制删除(包括未提交的修改)
git rm -f filename.txt
# 删除所有被跟踪的文件
git rm -r --cached .重命名文件
bash
# 重命名文件
git mv oldname.txt newname.txt
# 等价于
mv oldname.txt newname.txt
git rm oldname.txt
git add newname.txt
# 移动文件
git mv file.txt src/
# 移动并重命名
git mv old/path/file.txt new/path/newfile.txt实用技巧
快速查看修改概览
bash
# 查看修改的文件列表
git status -s
# 查看修改统计
git diff --stat
# 查看修改摘要
git diff --shortstat
# 查看修改的文件数量
git diff --numstat | wc -l批量操作
bash
# 添加所有修改的文件
git add -u
# 添加所有文件(包括删除)
git add -A
# 撤销所有暂存
git reset HEAD
# 撤销所有修改
git restore .
# 删除所有未跟踪的文件
git clean -f
# 删除所有未跟踪的文件和目录
git clean -fd
# 预览将要删除的文件
git clean -n使用 Git 别名
bash
# 配置状态别名
git config --global alias.st status
git config --global alias.ss "status -s"
git config --global alias.d diff
git config --global alias.ds "diff --staged"
# 使用别名
git st
git ss
git d
git ds总结
文件状态速查表
| 状态 | 说明 | 操作 |
|---|---|---|
| Untracked | 未跟踪 | git add 添加 |
| Unmodified | 未修改 | 编辑文件 |
| Modified | 已修改 | git add 暂存 |
| Staged | 已暂存 | git commit 提交 |
常用命令速查
bash
# 添加文件
git add . # 添加所有文件
git add -p # 交互式添加
# 查看状态
git status # 完整状态
git status -s # 简洁状态
# 撤销操作
git restore <file> # 撤销工作目录修改
git restore --staged <file> # 取消暂存
# 删除文件
git rm <file> # 删除并暂存
git rm --cached <file> # 只删除仓库中的文件
# 重命名
git mv <old> <new> # 重命名文件下一步
掌握文件状态管理后,建议继续学习:
