前言
如果说 git commit 是Git的"快门",那 git status 就是Git的"仪表盘"。每次操作前后看一眼 git status,能让你清楚知道:现在工作区有什么改动?哪些已经暂存?哪些还没被Git跟踪?当前在哪个分支?
git status 是Git中使用频率最高的命令之一,几乎所有Git工作流都以它开始、以它结束。本篇将带你彻底读懂它的每一种输出。
一、git status 的作用
git status 用于查看工作区和暂存区的当前状态,主要告诉你:
- 当前在哪个分支
- 工作区有哪些文件被修改了(还未add)
- 暂存区有哪些文件(已经add,还未commit)
- 有哪些新文件还没被Git跟踪
- 有哪些文件被删除了
- 是否有合并冲突
它是你与Git"对话"的第一步------不知道当前状态,就无法决定下一步做什么。
二、基本用法和输出解读
2.1 无变更时的输出
git status
输出:
位于分支 main
无文件要提交,干净的工作区(clean working tree)
英文版:
On branch main
nothing to commit, working tree clean
这说明:工作区和暂存区都没有任何变化,所有修改都已提交。
2.2 有未跟踪文件
新建了一个文件但还没 git add:
echo "console.log('hello')" > new.js
git status
输出:
位于分支 main
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
new.js
提示:您有未跟踪的文件,但尚未包含在提交中。
提示:将使用 'git add' 建立对此文件版本的跟踪。
提示:提交为空但是存在尚未跟踪的文件(使用 'git add' 建立跟踪)
解读:
未跟踪的文件:Git知道这个文件存在,但还没纳入版本管理- 提示信息告诉你:用
git add可以开始跟踪它
2.3 有已暂存文件
git add new.js
git status
输出:
位于分支 main
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
新文件: new.js
解读:
要提交的变更:这些文件已在暂存区,等待git commit新文件:表示这是新加入跟踪的文件- 提示告诉你:用
git restore --staged可以把它从暂存区撤回
2.4 有已修改未暂存文件
修改一个已跟踪文件:
echo "console.log('updated')" >> app.js
git status
输出:
位于分支 main
修改尚未加入提交:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: app.js
修改尚未加入提交:
app.js
解读:
修改尚未加入提交:文件被修改了,但还没git add修改:表示这是一个已跟踪文件被修改- 两个提示:
git add暂存它,或git restore丢弃修改
2.5 综合状态
最常见的情况------多种状态同时存在:
git status
输出:
位于分支 main
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
新文件: config.js
修改: router.js
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: app.js
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
temp.js
这个输出清晰地分三栏:
| 区域 | 含义 | 文件 |
|---|---|---|
| 要提交的变更 | 已暂存,待commit | config.js, router.js |
| 尚未暂存 | 已修改,未add | app.js |
| 未跟踪的文件 | 新文件,Git不管理 | temp.js |
三、git status -s 简洁模式
-s 或 --short 选项输出极简格式,适合快速浏览:
git status -s
输出:
A config.js
M router.js
M app.js
?? temp.js
3.1 输出格式解读
格式为 XY filename:
- X:暂存区状态(第一列)
- Y:工作区状态(第二列)
- 两个状态之间可能有空格
3.2 状态标记含义表
| 标记 | 含义 |
|---|---|
| 未修改 | |
M |
修改(Modified) |
A |
新增(Added,已暂存) |
D |
删除(Deleted) |
R |
重命名(Renamed) |
C |
复制(Copied) |
U |
冲突(Unmerged,合并冲突) |
?? |
未跟踪(Untracked) |
!! |
被忽略(Ignored) |
3.3 两列状态的含义
M file.js # 暂存区有修改(已add),工作区无额外修改
M file.js # 工作区有修改(未add),暂存区无修改
MM file.js # 暂存区有修改,且工作区又有新的修改
A file.js # 新增并已暂存
AM file.js # 新增已暂存,且工作区又修改了
?? file.js # 未跟踪
举例演示 MM 状态:
echo "v1" > file.js
git add file.js # 暂存区:v1
echo "v2" >> file.js # 工作区:v1+v2
git status -s
# 输出:AM file.js(如果是新文件)
四、git status --long 详细模式(默认)
--long 是默认行为,就是上面看到的那种详细输出。显式使用:
git status --long
通常不需要显式写,因为默认就是long。但如果你配置了 status.short 为true,可以用 --long 临时切换回详细模式。
# 配置默认使用短格式
git config --global status.short true
# 临时用长格式
git status --long
五、git status -b 显示分支信息
-b 或 --branch 选项在输出顶部显示分支信息,常和 -s 组合使用:
git status -sb
输出:
## main...origin/main [领先 2]
A config.js
M app.js
?? temp.js
分支行解读:
## main...origin/main:当前分支main,跟踪远程origin/main[领先 2]:本地比远程多2个提交(ahead 2)[落后 1]:本地比远程少1个提交(behind 1)[领先 2, 落后 1]:既领先又落后,需要先pull再push
长格式中分支信息默认就显示:
git status -b
输出:
位于分支 main
您的分支领先 'origin/main' 共 2 个提交。
(使用 "git push" 来发布您的本地提交)
要提交的变更:
新文件: config.js
...
六、git status --ignored 显示被忽略的文件
.gitignore 排除的文件默认不显示。用 --ignored 可以查看:
# .gitignore 内容
# node_modules/
# *.log
git status --ignored
输出:
位于分支 main
要提交的变更:
新文件: config.js
忽略的文件:
(使用 "git add -f <文件>..." 以包含要提交的内容)
.gitignore
node_modules/
error.log
配合 -s 简洁模式:
git status -s --ignored
输出:
A config.js
!! node_modules/
!! error.log
!! 表示被忽略的文件。
七、git status --porcelain 机器可读格式
--porcelain 输出固定格式,适合脚本解析(不会随Git版本变化而改变):
git status --porcelain
输出:
A config.js
M app.js
?? temp.js
看起来和 -s 一样,但 --porcelain 保证格式稳定,而 -s 可能随版本更新变化。
7.1 porcelain v2
更详细的机器可读格式:
git status --porcelain=v2
输出:
# branch.head main
# branch.upstream origin/main
# branch.ab +2 0
1 A. N... 100644 100644 100644 a1b2c3d e5f6a7b config.js
1 .M N... 100644 100644 100644 b2c3d4e f6a7b8c app.js
? temp.js
每行含义:
#开头:分支信息1开头:已跟踪文件的状态?开头:未跟踪文件2开头:重命名/复制的文件u开头:冲突文件
7.2 在脚本中使用
#!/bin/bash
# 检查是否有未提交的修改
if [ -n "$(git status --porcelain)" ]; then
echo "有未提交的修改,请先提交"
exit 1
fi
echo "工作区干净,可以继续"
八、各种场景下的 git status
8.1 新建文件后
echo "content" > new.txt
git status
输出:
位于分支 main
未跟踪的文件:
new.txt
8.2 git add 后
git add new.txt
git status
输出:
位于分支 main
要提交的变更:
新文件: new.txt
8.3 git commit 后
git commit -m "添加new.txt"
git status
输出:
位于分支 main
无文件要提交,干净的工作区
8.4 修改已跟踪文件后
echo "more" >> app.js
git status
输出:
位于分支 main
修改尚未加入提交:
修改: app.js
8.5 删除文件后
方式一:直接用rm删除(工作区删除)
rm old.js
git status
输出:
位于分支 main
修改尚未加入提交:
删除: old.js
方式二:用git rm删除(同时从工作区和暂存区删除)
git rm old.js
git status
输出:
位于分支 main
要提交的变更:
删除: old.js
8.6 重命名文件后
git mv old_name.js new_name.js
git status
输出:
位于分支 main
要提交的变更:
重命名: old_name.js -> new_name.js
如果是普通 mv 而非 git mv:
mv old_name.js new_name.js
git status
输出:
位于分支 main
修改尚未加入提交:
删除: old_name.js
未跟踪的文件:
new_name.js
Git会识别为"删除+新增",git add 后会自动识别为重命名:
git add -A
git status
输出:
位于分支 main
要提交的变更:
重命名: old_name.js -> new_name.js
8.7 合并冲突时
git merge feature-branch
# 冲突!
git status
输出:
位于分支 main
您有尚未合并的路径。
(解决冲突并运行 "git commit")
(使用 "git merge --abort" 终止合并)
要提交的变更:
修改: no-conflict.js
双方修改:
修改: conflict.js
解读:
您有尚未合并的路径:正在合并中,有冲突双方修改:两边都改了同一个文件,需要手动解决- 解决后
git add conflict.js再git commit
冲突文件的状态标记详解:
git status -s
输出:
UU conflict.js # 双方都修改了(Both Modified)
AA both-added.js # 双方都新增了(Both Added)
DD both-deleted.js # 双方都删除了(Both Deleted)
AU added-by-us.js # 我们新增,对方修改
UA added-by-them.js # 对方新增,我们修改
DU deleted-by-us.js # 我们删除,对方修改
UD deleted-by-them.js # 对方删除,我们修改
8.8 rebase冲突时
git rebase feature-branch
# 冲突!
git status
输出:
交互式 rebase 正在进行中;至 8f3a2d1
(使用 "git rebase --continue" 继续变基)
(使用 "git rebase --skip" 跳过此补丁)
(使用 "git rebase --abort" 终止变基)
您有尚未合并的路径。
(解决冲突并运行 "git rebase --continue")
双方修改:
修改: conflict.js
8.9 cherry-pick冲突时
git cherry-pick 8f3a2d1
# 冲突!
git status
输出:
位于分支 main
您目前正 cherry-pick 提交 8f3a2d1。
(解决冲突并运行 "git cherry-pick --continue")
(使用 "git cherry-pick --skip" 跳过此操作)
(使用 "git cherry-pick --abort" 终止此操作)
双方修改:
修改: conflict.js
九、自定义 status 格式和颜色
9.1 自定义颜色
# 开启颜色
git config --global color.status auto
# 自定义各种状态的颜色
git config --global color.status.added "green bold"
git config --global color.status.changed "yellow bold"
git config --global color.status.untracked "red bold"
git config --global color.status.header "blue"
9.2 自定义分支信息格式
# 显示更多信息
git config --global status.branch true
git config --global status.displayCommentPrefix true
9.3 显示前置注释提示
默认的中文提示中那些括号里的帮助文字,可以关闭:
git config --global status.displayCommentPrefix false
十、git status 的性能
在大型仓库中,git status 可能很慢,主要瓶颈在未跟踪文件的检测。
10.1 --untracked-files 选项
# 默认:显示所有未跟踪文件(normal)
git status --untracked-files=normal
# 不显示未跟踪文件(最快)
git status --untracked-files=no
# 简写
git status -uno
# 显示未跟踪文件,包括被忽略目录里的(all)
git status --untracked-files=all
# 简写
git status -uall
normal 和 all 的区别:
normal:如果一个目录里全是未跟踪文件,只显示目录名all:逐个显示每个文件
10.2 大仓库优化建议
-
善用 .gitignore :把
node_modules/、dist/等排除 -
用 -uno 快速检查:只看已跟踪文件的状态
-
配置默认行为:
默认不显示未跟踪文件(加快速度)
git config --global status.showUntrackedFiles no
-
使用Git的文件系统监控(Git 2.37+):
git config --global core.fsmonitor true
git config --global core.untrackedcache true
这能让Git缓存文件系统状态,大幅提升 git status 速度。
十一、常见问题 FAQ
Q1:git status 显示 "HEAD detached at ..."
说明当前处于"分离头指针"状态,通常发生在checkout到某个commit而非分支时:
头指针分离于 8f3a2d1
无文件要提交,干净的工作区
此时提交不会属于任何分支。解决:
git checkout main # 回到分支
# 或创建新分支保存当前状态
git checkout -b new-branch
Q2:git status 显示中文文件名是乱码
git config --global core.quotepath false
默认Git会把非ASCII字符转义显示,这个配置关闭转义。
Q3:git status 很慢怎么办?
参考第十节优化建议,主要:
- 完善
.gitignore - 使用
core.fsmonitor - 临时用
git status -uno
Q4:如何只看是否有变化(不看具体内容)?
# 用porcelain格式判断
if [ -z "$(git status --porcelain)" ]; then
echo "无变化"
fi
Q5:git status 显示 "您的分支落后于..."
位于分支 main
您的分支落后 'origin/main' 共 3 个提交,并且可以快进。
(使用 "git pull" 来更新您的本地分支)
说明远程有新提交,本地需要 git pull。
Q6:ahead 和 behind 同时存在?
您的分支和 'origin/main' 产生了分叉,
并且分别有 2 和 1 处不同的提交。
说明本地和远程都各自有提交,需要先 git pull 合并再 git push。
Q7:git status 显示 "interactive rebase in progress"
说明你正在执行 git rebase -i 交互式变基,处于暂停状态。可以:
git rebase --continue # 解决冲突后继续
git rebase --skip # 跳过当前提交
git rebase --abort # 放弃rebase回到之前
Q8:如何让git status不显示某些文件?
把这些文件加入 .gitignore:
echo "*.log" >> .gitignore
echo "node_modules/" >> .gitignore
如果文件已经被跟踪,需要先取消跟踪:
git rm --cached debug.log
echo "debug.log" >> .gitignore
Q9:git status -s 中第一列和第二列的区别?
XY filename
- X(第一列):暂存区相对HEAD的状态(已add的改动)
- Y(第二列):工作区相对暂存区的状态(未add的改动)
例如 MM file.js:
- 第一个M:暂存区有修改(已add)
- 第二个M:工作区又有新修改(未add)
Q10:如何查看暂存区里有什么?
# 查看暂存区文件列表
git ls-files --stage
# 查看暂存区状态
git diff --staged --stat
十二、小结
本篇详细讲解了 git status 命令:
| 知识点 | 要点 |
|---|---|
| 作用 | 查看工作区和暂存区状态 |
| 基本输出 | 分三栏:要提交、未暂存、未跟踪 |
| -s 简洁模式 | XY filename 格式,X暂存区Y工作区 |
| -b 分支信息 | 显示ahead/behind情况 |
| --ignored | 显示被.gitignore排除的文件 |
| --porcelain | 机器可读格式,用于脚本 |
| 常见场景 | 新建/修改/删除/重命名/合并冲突 |
| 性能优化 | .gitignore、fsmonitor、-uno |
12.1 git status 输出的三个区域
再次强调,git status 的输出分为三个区域,理解这三个区域是掌握Git的关键:
区域一:要提交的变更(Changes to be committed)
这些文件已经在暂存区,执行 git commit 就会进入版本库。对应 git add 过的文件。
要提交的变更:
新文件: new.js # 新增并暂存
修改: app.js # 修改并暂存
删除: old.js # 删除并暂存
区域二:尚未暂存以备提交的变更(Changes not staged for commit)
这些文件已被Git跟踪,且工作区有修改,但还没 git add。执行 git commit 不会包含它们。
尚未暂存以备提交的变更:
修改: router.js # 修改了但没add
区域三:未跟踪的文件(Untracked files)
这些文件在工作区存在,但Git还没纳入管理。需要 git add 才能开始跟踪。
未跟踪的文件:
temp.js # 新文件,还没被Git管理
12.2 状态转换图
文件在这三个区域之间的转换:
未跟踪 ──git add──▶ 已暂存 ──git commit──▶ 已提交
▲ │ │
│ │git restore --staged │
│ ▼ │
└───────── 已修改未暂存 ◀────────────────┘
│
│git restore
▼
已恢复原样
核心记忆:
git status # 查看详细状态
git status -s # 简洁模式
git status -sb # 简洁+分支信息(最常用)
git status --ignored # 显示被忽略文件
git status --porcelain # 脚本用格式
养成习惯 :每次 git add 前看一眼 git status,每次 git commit 前看一眼,每次 git pull/push 前看一眼。这是避免Git操作失误的最简单方法。
下一篇我们将学习 git log------如何查看提交历史,追溯每一次修改的来龙去脉。
作者:全栈陈序员 出处:CSDN 声明:本文为原创文章,转载请注明出处