git branch 不显示未暂存文件数,需用 git status --porcelain 解析 M 和 ?? 行统计,并通过 shell 提示符函数(如 Bash 的 PS1 或 Zsh 的 vcs_info)实时展示分支名与未暂存数。

git branch 命令本身不显示未暂存文件数
git branch 只列出本地分支,当前分支前加 *,它不感知工作区或暂存区状态。想在终端提示符(如 Bash/Zsh)里实时看到「当前分支名 + 未暂存文件数」,必须靠 shell 提示符定制,不是 Git 命令能直接解决的。
用 git status --porcelain 获取未暂存文件数
真正判断“未暂存文件数”的可靠方式是解析 git status --porcelain 输出。它每行代表一个变更文件,格式为 XY filename,其中:
-
??表示未跟踪文件(untracked) -
M表示已修改但未暂存(modified, unstaged) -
MM表示已修改且已暂存(staged),但工作区还有改动
所以统计以 M 或 ?? 开头的行数,就能得到“未暂存的变更文件总数”。实际脚本中常用:
git status --porcelain | grep -E '^\?\?|^M ' | wc -l
注意:^M 后面有个空格,避免误匹配 MM;^\?\? 是正则转义写法,匹配开头两个问号。
Bash 提示符里嵌入分支名和未暂存计数
在 ~/.bashrc 中定义函数并插入 PS1:
parse_git_branch() {
local branch=$(git branch --show-current 2>/dev/null)
if [ -n "$branch" ]; then
local dirty=$(git status --porcelain | grep -E '^\?\?|^M ' | wc -l | tr -d ' ')
echo "($branch${dirty:+:$dirty})"
fi
}然后设置提示符:
PS1='\u@\h:\w$(parse_git_branch) \$ '
效果示例:user@host:~/project(main:2) $ 表示当前在 main 分支,有 2 个未暂存变更(含未跟踪文件)。
容易踩的坑:
- 没加
2>/dev/null:非 Git 目录下执行会报错,破坏整个提示符显示 - 没用
--show-current:老版本 Git(git rev-parse --abbrev-ref HEAD 2>/dev/null - 直接用
git status而非--porcelain:输出不稳定,含颜色/空行/中文,难以安全解析
Zsh 用户优先用 vcs_info 模块
Zsh 自带 vcs_info,比手写函数更健壮,且原生支持 Git 状态缓存:
autoload -Uz vcs_info
zstyle ':vcs_info:git:*' formats '(%b%u%c)'
zstyle ':vcs_info:git:*' actionformats '(%b%u%c|!%a)'
zstyle ':vcs_info:git:*' check-for-changes true
zstyle ':vcs_info:git:*' unstagedstr ':'
zstyle ':vcs_info:git:*' stagedstr='+'
precmd() { vcs_info }
PS1='%n@%m:%~%v %# '其中 %u 默认显示未暂存标记(如 :),%c 显示已暂存标记(如 +)。要显示具体数字,需自定义 nvcs 函数配合 git status --porcelain —— 但多数人只需符号提示,已足够快速感知状态。
复杂点在于:不同 shell 对命令替换的执行时机、子 shell 环境、性能敏感度差异很大;Zsh 的 vcs_info 默认不统计数字,Bash 方案依赖每次渲染都跑一次 git status --porcelain,大仓库可能卡顿——这时候就得加缓存逻辑或改用 git update-index --refresh 预热索引。


















