git bad revision 引用找不到速查:unknown revision 的六个根因
更新时间:2026-10-24。FAQ 速查页,面向
git checkout/git log/git diff时被fatal: ambiguous argument 'xxx': unknown revision or path not in the working tree或fatal: bad revision 'xxx'挡住的同学。bad revision 的含义一句话:你给的「引用名」(分支、tag、SHA、HEAD~3 这类相对引用)在当前仓库的引用表里查无此项——Git 不是找不到提交内容,是不认识这个指向提交的名字。收敛在六根轴上:分支或 tag 名打错字、远端引用根本没 fetch 到本地、detached HEAD 上的提交没有名字可引用、SHA 缩写太短撞车、引用在远端已被删除本地还在用旧名、以及引用名与路径名歧义缺--分隔。本篇主线工具是git show-ref——它打印本地全部引用的真实名单,是这类报错的照妖镜。
本文要回答的问题
unknown revision和bad revision是提交丢了还是名字错了?- 远端明明有
feature-x分支,本地 checkout 为什么说找不到? - detached HEAD 状态下提交的代码,为什么重启后「消失」了?
HEAD~99报 bad revision,是历史不够长还是语法错了?git show-ref怎么用,它和git branch -a的分工是什么?
一、报错原文与典型现象
bad revision 家族的几种真实措辞如下(路径以 /proj/demo 占位,远端以 git.example.com 占位):
$ git -C /proj/demo checkout featur-x
error: pathspec 'featur-x' did not match any file(s) known to git$ git -C /proj/demo log origin/feature-x
fatal: ambiguous argument 'origin/feature-x': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'$ git -C /proj/demo diff HEAD~99
fatal: bad revision 'HEAD~99'$ git -C /proj/demo show a1b2c
fatal: Not a valid object name a1b2c读报错抓两个信号:报 unknown revision 且带 -- 提示的,是 Git 在「引用」和「路径」两个名单里都没查到这个串,先当引用查、查不到才退到路径;报 bad revision 的是语法解析通过了但求值失败(比如 HEAD~99 的祖宗不存在);报 Not a valid object name 的是 SHA 本身对不上任何对象。三种措辞对应三种排查入口,别混着治。
二、病因处置速查表
| 报错现象 / 场景 | 可能原因 | 快速验证 | 处置 |
|---|---|---|---|
| checkout 分支名报 pathspec | 分支名打错,如 featur-x | git branch --list '*featur*' | 按 branch 列出的真实名字重打 |
| log origin/xxx 报 unknown revision | 远端引用没 fetch 到本地 | git show-ref | grep feature-x 无输出 | git fetch origin 后再操作 |
| detached HEAD 提交重启找不到 | 提交没挂任何分支/tag | git reflog 里能查到 SHA | 立刻 git branch rescue <SHA> 命名 |
| diff HEAD~99 报 bad revision | 历史深度不够 99 层 | git rev-list --count HEAD | 按实际深度调整相对引用 |
| show 短 SHA 报 Not a valid object | SHA 缩写太短撞车或打错 | git log --oneline | grep 前几位 | 用完整 SHA 或更长缩写 |
| 昨天还能用的分支今天找不到 | 远端分支被删,本地引用过期 | git fetch --prune 后引用消失 | 确认删除动作,用 reflog 找遗留提交 |
| 名字既像分支又像文件 | 引用与路径歧义 | git show-ref | grep <名字> | 路径前加 -- 分隔 |
| tag 名 checkout 后显示 detached | tag 是指向提交的固定快照 | git tag --list '<名字>' | 基于 tag git switch -c 建分支 |
三、排查决策图
下面这张图是标准排查路线,颜色按角色区分:红是报错入口与命中的根因,蓝是排查动作,绿是通过分支,橙是修复动作,紫是防复发沉淀。
读这张图抓主线顺序:先问「本地引用名单里有没有这个名字」(show-ref 一条见底),没有再问「是不是远端有、本地没拉」(fetch 后复查),最后才轮到「相对引用深度、SHA 撞车」这类求值层问题。九成 case 在前两步收敛——引用找不到的病,根子几乎都在「名单」而不在「提交」。
四、逐条排查展开
第一条:名字打错——先核名单再动手。 featur-x 之于 feature-x、v1.2 之于 v1.20,都是真实高频翻车。Git 报错会把名字原样回显,先肉眼对一遍;更稳的做法是直接查名单:
git show-ref | grep feature # 全引用名单里找片段
git branch -a --list '*feat*' # 只看分支,含远端跟踪
git tag --list 'v1.*' # 只看 taggit show-ref 输出形如 a1b2c3d refs/heads/feature-x,左边是 SHA 右边是引用全名——refs/heads/ 是本地分支、refs/tags/ 是 tag、refs/remotes/origin/ 是远端跟踪引用。你敲的名字必须和这份名单逐字符一致,Git 不做模糊匹配。引用名一律靠 shell 补全或复制粘贴,不手打。
第二条:远端有、本地没拉——unknown revision 的最大头。 同事在平台上建了 feature-x,你本地 git log origin/feature-x 直接报 unknown revision——因为远端跟踪引用只在 fetch 时更新,你本地的 origin/feature-x 还停留在上次同步时的名单里,根本没有这个条目。标准动作:
git fetch origin # 同步远端引用
git show-ref | grep feature-x # 复查:refs/remotes/origin/feature-x 出现了
git checkout feature-x # 现在能建了(自动跟踪 origin/feature-x)这条病在 CI 与新人机器上高发:clone 只拉默认分支的远端引用配置被改过(--single-branch),或长时间没 fetch。养成「引用找不到先 fetch」的肌肉记忆,比反复核对拼写快得多。fetch 与远端跟踪的机制见 remote、pull、push 用法。
第三条:detached HEAD——提交没丢,是没名字。 典型剧情:git checkout abc1234 进 detached 状态改代码、提交,一切正常;切回 master 再想找那几个提交,SHA 记不住、名字没起过,git log 里自然没有——报 bad revision 或直接「找不到」。提交其实还在对象库里,找回通道是 reflog:
git reflog # 找到 HEAD 曾经停在 abc1234 提交的记录
git branch rescue-work abc1234 # 给它起名字,从此进 log 视野教训:detached HEAD 上做的任何提交,当场建分支或打 tag 命名,不要指望事后记 SHA。reflog 默认只保留约九十天且只记本机 HEAD 的移动轨迹,换台机器、或拖得太久,这条找回通道也会关闭——命名是唯一不依赖运气的做法。detached 状态的完整行为与找回手段见 tag、bisect、reflog。
第四条:相对引用求值失败——HEAD~99 的病在历史深度。 HEAD~99 报 bad revision,不是语法错,是当前分支从 HEAD 往祖宗数不够 99 层——浅克隆(--depth 1)的仓库尤其高发,历史只有一层,任何 HEAD~n 都越界。核对:
git rev-list --count HEAD # 实际可数的提交数
git log --oneline | wc -l # 同上,换个口径处置:按实际深度调整引用;浅克隆要完整历史就 git fetch --unshallow 补全。同理,HEAD^2(第二父提交)在非合并提交上求值也会 bad revision——相对引用是先解析名字再求值,求值失败的措辞都是 bad revision。
第五条:SHA 缩写撞车或打错。 git show a1b2 报 Not a valid object name,两种可能:缩写打错(肉眼对 git log --oneline 的前几位),或缩写太短在对象库里不唯一(Git 会报 ambiguous 提示,但脚本里截断得太狠的 SHA 也可能直接无效)。纪律:给人看的用 7 位以上,给脚本用的传完整 40 位 SHA,不做截断。
第六条:引用被删与歧义分隔。 两种收尾场景。其一:远端分支被删后,本地 origin/feature-x 还残留(直到 git fetch --prune 才被清),基于它新建的本地分支改名引用会报找不到——先 prune 同步真实名单,再用 reflog 确认遗留提交去向。其二:名字既像引用又像路径(比如分支叫 docs 同时有 docs/ 目录),git log docs 的歧义解析与处置和 pathspec 篇同一条路——路径永远跟在 -- 后面,详见 pathspec did not match 速查。
五、规范做法与预防
- 引用名不手打:分支/tag 一律 shell 补全或从
show-ref、branch -a输出里复制,拼写类报错直接绝迹。 - 找不到先 fetch:任何
origin/xxxunknown revision 的第一反应是git fetch origin再复查,不是反复敲同一条命令。 - detached 提交当场命名:
git checkout <SHA>后要改代码,先git switch -c <新分支>;已经裸提交的,当天git branch补名。 - 脚本用完整 SHA:自动化里引用一律 40 位全量,相对引用(HEAD~n)前先
rev-list --count校验深度。 - 定期 prune:
git fetch --prune纳入日常,本地引用名单与远端保持一致,「幽灵引用」不积累。
这一篇在知识体系里的位置
本篇是 Git 排错速查簇的引用解析篇,定位「Git 不认识这个指向提交的名字」:路径名找不到(与引用报错同族但病根在文件侧)看 pathspec did not match 速查;连远端都够不着看 git clone 卡死超时速查;仓库与特性版本不认看 git 仓库版本不兼容速查;中文文件名显示异常看 git 中文乱码速查;误操作找回的完整手段看 tag、bisect、reflog 与 reset、revert、restore;分支归属看 branch 与 merge。
一句话总结
bad revision 的本质是「本地引用名单里没有这个名字」:先 git show-ref 查名单核对拼写,没有就 git fetch origin 同步远端引用再复查,detached HEAD 上的「消失提交」用 git reflog 找到 SHA 后立刻 git branch 命名,HEAD~n 类相对引用先 git rev-list --count HEAD 核对历史深度,SHA 缩写给足位数、脚本传全量。引用名靠补全、找不到先 fetch、detached 提交当场建分支,这类报错基本绝迹。