Git fetch 后仍看不到其他远程分支
单分支克隆后,git fetch --all 仍可能只更新原分支。确认远端目标分支存在,检查 remote.origin.fetch,并按需追加一个分支或恢复全部普通分支的抓取范围。
仓库最初用 git clone --single-branch 克隆,只需要一个分支。后来要切换到其他分支,执行了 git fetch origin,甚至 git fetch --all,git branch -r 仍只显示原来的分支。
远端分支仍然存在时,可以调整本地配置继续使用当前仓库。单分支克隆会保留受限的抓取规则,后续普通 fetch 仍按这条规则更新。需要先确认远端确实提供目标分支,再查看本地的抓取范围。
下面以远程名 origin、原分支 main、目标分支 release 为例。它们都是示例名称,执行时换成实际值。示例适用于普通工作仓库,不直接用于镜像仓库或带自定义引用映射的仓库;最后的切换步骤需要 Git 支持 git switch。
分清远端分支和本地记录
git branch 默认只列本地分支,不能用它判断远程分支是否已经抓取。先看远程跟踪分支,再直接查询服务器:
git branch -r
git remote get-url origin
git ls-remote --exit-code origin refs/heads/release
git branch -r 查看本地保存的远程跟踪引用,例如 origin/main。git ls-remote 则向服务器查询当前账户能看到的引用,不依赖本地是否已经有 origin/release。
如果最后一条命令返回提交 ID 和 refs/heads/release,就能确定该远程对当前账户提供了这个分支。如果没有匹配项,--exit-code 会使命令返回状态 2;认证失败、网络错误等需按实际错误处理,不能归为同一种“分支不存在”。还要核对远程地址、分支拼写和大小写。远程地址中如有令牌,不要把输出直接贴进公开日志。
远端查得到,而本地列表没有,才继续检查抓取规则。
单分支克隆留下了什么配置
在仓库中读取所有相关配置,并查看它们来自哪个文件:
git config --show-origin --get-all remote.origin.fetch
如果输出中的规则类似下面这样,普通 fetch 就只会维护 origin/main:
+refs/heads/main:refs/remotes/origin/main
冒号左边选择远端引用,右边指定写入本地的位置。这条规则只匹配 main,没有包含 release。开头的 + 允许相应引用的非快进更新;这里的目标是远程跟踪引用,不是本地工作分支。
git fetch --all 中的“all”指所有需要抓取的远程,并不会自动把每个远程的单分支规则扩展成全部分支。因此,反复执行它通常不会改变这个结果。
即使不记得用过 --single-branch,也可能遇到这种配置。克隆时的 --depth 默认隐含单分支,除非同时指定 --no-single-branch。不过,最终还是以当前配置为准,不能只根据克隆时是否使用浅历史推断原因。
修改前记录完整输出,并备份输出中对应的仓库配置文件。若看到多条自定义映射、排除规则,或规则来自全局配置及额外 include 文件,先确认它们的用途,不要直接用下面的整组替换方式覆盖。
只补充需要的一个分支
如果只想再跟踪 release,可以向已有列表追加它,再抓取:
git remote set-branches --add origin release
git fetch origin
git branch -r --list origin/release
--add 保留原来跟踪的分支,增加目标分支的规则。第二条命令根据更新后的配置获取对象和远程跟踪引用。第三条命令应能列出 origin/release。
这一步只是在本地增加远程跟踪记录,不会自动切换当前工作分支,也不会把 release 合并进当前分支。已经看到目标规则时不必重复追加;如果 fetch 本身报错,应先处理错误,再检查分支列表。
有时执行 git fetch origin release 后,输出显示抓取成功,却仍没有 origin/release。指定分支名可以决定要取哪些内容,但未显式指定本地目标时,远程跟踪引用仍受配置中的映射影响。对象和 FETCH_HEAD 已更新,不等于持久的 origin/release 引用已经创建。补齐规则后,后续普通抓取就能持续更新这个远程跟踪引用。
需要恢复抓取全部普通分支
如果仓库原本只有前面那种单分支映射,且希望以后都抓取 origin 的普通分支,可以改为:
git remote set-branches origin '*'
git fetch origin
git config --get-all remote.origin.fetch
git branch -r
这里没有 --add,会替换该远程当前跟踪的分支列表。'*' 必须加引号,让 Git 收到通配符本身,避免 shell 先将它展开为当前目录的文件名。
正常的对应规则应为:
+refs/heads/*:refs/remotes/origin/*
它将远端普通分支映射到本地 origin/ 下的远程跟踪引用。它不会为每个分支自动建立同名本地分支,也不等于补齐所有历史或所有标签。大型仓库扩展抓取范围可能增加传输量和磁盘占用,只需一个分支时用上一节的追加方式即可。
无需为此删除再添加 origin。那会同时移除这个远程的配置和远程跟踪分支,影响范围比调整抓取规则更大。
创建本地分支并确认上游
确认 origin/release 已存在后,先保存未提交的工作。若本地还没有 release 分支,再创建并切换:
git switch -c release --track origin/release
git branch -vv
--track 为新分支设置上游,git branch -vv 可查看相应关系。预期是本地 release 跟踪 origin/release,而不只是当前工作目录看起来切换成功。
如果本地 release 已存在,不要改用强制创建来覆盖它。先检查该分支的提交和上游,再决定是否切换或调整关系。切换被未提交修改阻止时,也应先保存修改,不要用强制选项解决一个原本属于抓取范围的问题。
需要恢复原来的单分支策略时,若修改前确实只有 main 这一条普通映射,可以执行:
git remote set-branches origin main
git config --get-all remote.origin.fetch
如果修改前有多条规则,则按备份逐条恢复原值。这只恢复今后的抓取范围,先前已下载的对象、建立的本地分支及远程跟踪引用不一定因此消失;不需要为了回退配置而急着清理它们。浅克隆是否需要更多历史,应按后续查看历史或合并时的实际需求另行处理。


