1. 为什么“git clone 所有分支”是个伪命题先把一个容易踩坑的认知掰正:git clone默认行为其实已经把所有分支的提交对象都拉到了本地。你打开.git目录,里面objects文件夹装的就是完整的提交历史,远端每一个分支指向的 commit 都在里面躺着。那为什么git branch -a只看到main或者master,其他分支像是“消失”了?原因在于 Git 的引用(ref)映射机制。克隆时,远端的分支引用被映射成了本地的“远程跟踪分支”,也就是origin/xxx这种形式。本地只自动创建一个分支,通常是远端 HEAD 指向的那个默认分支。其他分支不是没拉下来,而是没有在本地创建对应的“本地分支”去跟踪它们。这就像你搬进一栋楼,所有房间的钥匙都挂在物业(.git/refs/remotes),但你手里只拿了一把房门钥匙(本地分支),其他房间你随时能进,只是没配钥匙而已。所以这个标题真正要解决的问题,不是“怎么把数据拉下来”,而是怎么把远程跟踪分支批量转成本地可切换的分支,以及怎么在克隆那一刻就让所有分支都就位。理解了这一点,后面所有操作你都不会迷糊。我见过太多人一上来就搜“git clone 所有分支”,然后照着某些老帖子敲git clone --mirror,结果得到一个裸仓库,连工作区都没有,一脸懵。这就是没搞清楚“数据”和“引用”的区别。下面我把几种真实可用的方案拆开讲,每种适合什么场景、有什么坑,都给你说明白。2. 克隆后批量创建本地分支的三种实战方案2.1 方案一:一条 for 循环搞定所有远程分支这是最通用、最不挑环境的方法。克隆完成后,进入仓库目录,执行下面这段命令:git branch -r | grep -v '\->' | sed 's/origin\///' | while read branch; do git branch --track "$branch" "origin/$branch" 2>/dev/null done拆开看每一步在干什么。git branch -r列出所有远程跟踪分支,输出里通常有一行origin/HEAD -> origin/main,这个箭头行不是真正的分支,所以用grep -v '\->'过滤掉。sed 's/origin\///'把前缀origin/去掉,得到纯分支名。然后while read逐个读取,用git branch --track建立本地分支并设置跟踪关系。末尾的2>/dev/null是为了吞掉“分支已存在”的报错,让脚本可以重复执行。这个方案的好处是幂等,你跑第二遍不会报错中断。实测在一个有 40 多个分支的仓库里,这条命令两秒内跑完。注意--track参数很关键,它让本地分支自动关联对应的远程分支,之后你git pull不用再指定远端,直接就能拉。提示:如果你的默认分支叫main,脚本会尝试为origin/main创建本地main,但本地main已经存在,会报错被吞掉,不影响其他分支。这是正常现象。2.2 方案二:克隆时用 --no-single-branch 配合脚本有些团队的分支特别多,克隆时如果只想要默认分支的历史,可以用--single-branch加速。反过来,如果你明确要所有分支,可以显式加上--no-single-branch:git clone --no-single-branch <仓库地址> myproject cd myproject git branch -r | grep -v '\->' | sed 's/origin\///' | xargs -I {} git branch --track {} origin/{}--no-single-branch是默认行为的显式写法,加上它主要是为了防止某些全局配置或环境变量把默认行为改掉。比如有人配了clone.defaultRemoteName或者用了浅克隆的别名,显式声明能避免意外。xargs -I {}的写法比 while 循环更紧凑,但要注意分支名里如果有特殊字符可能出问题,一般分支名都是字母数字加连字符,不用担心。这个方案适合写进团队的初始化脚本里。我一般会在脚本开头加一句set -e,让任何一步失败就停下,避免半拉子状态。2.3 方案三:用 git remote update 刷新后再批量建分支如果你的仓库已经克隆了一段时间,远端新增了分支,本地git branch -r看不到新的,这时候需要先同步引用:git remote update origin --prune git fetch --all git branch -r | grep -v '\->' | sed 's/origin\///' | while read branch; do git branch --track "$branch" "origin/$branch" 2>/dev/null donegit remote update origin --prune会拉取远端最新的引用列表,同时清理掉远端已经删除但本地还留着的远程跟踪分支。--prune这个参数很多人不知道,它解决的是“远端分支删了,本地origin/xxx还在”的脏数据问题。我踩过一次坑:同事删了一个功能分支,我本地还显示origin/feature-old,结果基于它建了本地分支,推上去又创建了一个同名远程分支,闹了笑话。加上--prune就不会有这个问题。git fetch --all是双保险,确保所有 remote 的引用都是最新的。这两条命令跑完,再执行批量建分支的循环,就能把新增分支也纳入本地。3. 镜像克隆与裸仓库:什么时候该用,什么时候是坑3.1 git clone --mirror 的真实用途git clone --mirror会创建一个裸仓库,它把所有引用(包括远程跟踪分支、标签、甚至 refs/notes)原样复制,并且配置成可以git push --mirror完整回推。听起来很美好,但它没有工作区,你不能直接在里面写代码、提交、切换分支。它适合的场景是做仓库的完整备份或者搭建一个中转镜像。如果你只是想本地开发时能切换到所有分支,用--mirror就是杀鸡用牛刀,而且牛刀还不好使。我见过有人用--mirror克隆后,发现git checkout报错说“此操作必须在工作区中运行”,然后到处问怎么解决。解决办法是从裸仓库再克隆一次,或者用git clone --bare加git config core.bare false手动转成非裸仓库,但这一通操作下来,还不如一开始就用普通克隆加批量建分支。3.2 裸仓库转普通仓库的正确姿势如果你已经用--mirror克隆了,又想要工作区,可以这样救回来:cd mirror-repo.git git config core.bare false git config core.logallrefupdates true git checkout maincore.bare false告诉 Git 这个仓库有工作区,core.logallrefupdates true开启引用日志,方便回滚。然后git checkout main会把默认分支的文件释放到当前目录。但注意,裸仓库的目录结构里没有.git子目录,所有 Git 数据直接在根目录,转成非裸后,工作区文件会和.git数据混在一起,看起来有点怪,但能用。我建议还是重新克隆一次,干净利落。3.3 浅克隆与所有分支的冲突git clone --depth 1是浅克隆,只拉最近一次提交,速度极快,适合 CI 环境。但它默认只拉默认分支,而且历史被截断,其他分支的提交对象根本不在本地。你就算批量建了本地分支,切过去也会发现历史不完整,git log只能看到一条提交。如果确实需要所有分支的完整历史,就别用--depth。如果只是想在浅克隆里看看其他分支的最新代码,可以用git fetch --depth 1 origin <分支名>单独拉某个分支的浅历史,但这不是“所有分支”的常规做法。4. 批量操作中的常见报错与排查手册4.1 报错“fatal: A branch named 'xxx' already exists”这个报错在批量脚本里非常常见,原因就是本地已经存在同名分支。比如你跑了两遍脚本,或者默认分支已经被自动创建了。解决办法就是在git branch --track后面加2>/dev/null吞掉错误,或者用git branch --track ... || true让脚本继续。更优雅的写法是先判断分支是否存在:git show-ref --verify --quiet "refs/heads/$branch" || git branch --track "$branch" "origin/$branch"git show-ref --verify --quiet检查本地分支是否存在,存在就跳过,不存在才创建。这样脚本更健壮,也不会产生一堆错误输出干扰视线。4.2 报错“error: the requested upstream branch 'origin/xxx' does not exist”这说明你试图跟踪的远程分支在本地引用里找不到。可能原因有三个:一是远端确实没有这个分支,你的git branch -r列表是过期的;二是远程跟踪分支的名字不是origin/xxx,比如你用了自定义的 remote 名字;三是--prune刚清理掉了已删除的远程分支,但你的循环还在用旧列表。解决办法是先跑git remote update origin --prune刷新,再重新生成分支列表。如果是自定义 remote 名,把脚本里的origin替换成你的 remote 名即可。4.3 分支名包含斜杠时的处理功能分支经常长这样:feature/user-login、bugfix/issue-123。这种带斜杠的分支名在sed和while read里一般没问题,因为斜杠不是特殊字符。但如果你用xargs且没有正确处理,可能会被拆成多个参数。我建议统一用while read循环,它对含斜杠、含连字符的分支名兼容性最好。另外,git branch --track feature/user-login origin/feature/user-login这种写法完全合法,Git 会自动创建refs/heads/feature/user-login的目录结构。4.4 中文分支名的乱码问题有些团队会用中文命名分支,比如功能/登录模块。在终端里执行批量脚本时,如果 locale 设置不对,git branch -r的输出可能是转义后的八进制字符,导致建出来的本地分支名乱码。解决办法是设置export LANG=en_US.UTF-8或者export LC_ALL=en_US.UTF-8,让 Git 以 UTF-8 输出。更好的做法是别用中文分支名,这不是 Git 的限制,而是各种工具链(CI、IDE、命令行)对中文支持参差不齐,迟早出问题。5. 高效管理多分支的进阶技巧5.1 用 git branch --set-upstream-to 修正跟踪关系批量建分支时如果忘了加--track,本地分支和远程分支就没有关联,git pull会报“no tracking information”。补救方法是对每个分支执行:git branch --set-upstream-to=origin/<分支名> <本地分支名>批量修正可以这样:for b in $(git branch --format='%(refname:short)'); do git branch --set-upstream-to="origin/$b" "$b" 2>/dev/null donegit branch --format='%(refname:short)'只输出分支短名,比解析git branch的星号和空格更可靠。这个脚本会把所有本地分支的跟踪关系重新指向同名的远程分支,适合在批量建分支后统一修正。5.2 用 git config 设置默认推送行为多分支环境下,git push的默认行为很容易让人困惑。Git 2.0 之后,push.default的默认值是simple,它只推送当前分支到同名的远程分支,如果远程没有同名分支就会报错。你可以改成current,这样推送当前分支到同名远程分支,不存在就创建:git config --global push.default current这个设置在多分支开发时特别顺手,不用每次git push -u origin <分支名>。但要注意,current不会自动建立跟踪关系,第一次推送后还是建议用--set-upstream-to补上。5.3 用 git fetch 的 refspec 一次性拉取所有分支除了克隆后建分支,还有一种思路是在git fetch时用 refspec 把所有远程分支映射到本地分支:git fetch origin '+refs/heads/*:refs/heads/*'这个 refspec 的意思是:把远端refs/heads/下的所有引用,强制映射到本地refs/heads/下。+表示允许非快进更新。执行后,本地会直接出现所有远程分支对应的本地分支,不需要再跑循环。但这个方法有个副作用:它会覆盖本地同名分支,如果你本地有未推送的提交,可能会丢。所以用之前一定要确认本地没有需要保留的独有提交,或者先git stash或建临时分支备份。注意:这个 refspec 写法比较激进,适合在干净的克隆仓库里用,不适合日常开发仓库。5.4 用别名简化批量操作如果你经常需要批量建分支,可以把它做成 Git 别名:git config --global alias.pullall '!git branch -r | grep -v "\->" | sed "s/origin\///" | while read b; do git branch --track "$b" "origin/$b" 2>/dev/null; done'之后直接git pullall就能一键建好所有本地分支。别名以!开头表示执行 shell 命令,注意里面的引号转义。这个别名我用了好几年,换电脑第一件事就是配上。6. 不同场景下的方案选型对照场景推荐方案关键命令注意事项全新克隆,需要所有分支普通克隆 + 批量建分支脚本git clone后跑 while 循环脚本要幂等,吞掉已存在报错已有仓库,远端新增分支remote update + 批量建分支git remote update --prune先刷新引用再建分支做仓库完整备份git clone --mirrorgit clone --mirror裸仓库无工作区,不能直接开发CI 环境快速拉取浅克隆 + 按需 fetchgit clone --depth 1历史不完整,不适合本地开发一次性映射所有分支fetch refspecgit fetch origin '+refs/heads/*:refs/heads/*'会覆盖本地同名分支,慎用日常多分支开发别名 + push.default currentgit config --global push.default current首次推送后补跟踪关系这张表是我自己踩坑总结出来的,你可以根据手头的情况直接对号入座。新手最容易犯的错就是不管什么场景都上--mirror,结果被裸仓库卡住。记住一个原则:要开发就用普通克隆,要备份才用镜像。7. 我踩过的坑和给你的实操建议第一个坑是在错误目录执行脚本。有次我在父目录跑批量建分支,结果 Git 找不到仓库,报了一堆错。后来我在脚本开头加了git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "不在 Git 仓库中"; exit 1; },先检查当前目录是不是 Git 仓库,不是就退出。这个检查能省掉很多莫名其妙的报错。第二个坑是分支名大小写问题。Windows 和 macOS 的文件系统默认大小写不敏感,Feature/Login和feature/login在本地可能被当成同一个分支,但在 Linux 服务器上是两个不同分支。批量建分支时如果遇到大小写不同的分支名,本地可能只创建一个。解决办法是在大小写不敏感的系统上,避免创建仅大小写不同的分支名,这是团队规范问题,不是脚本能解决的。第三个坑是远程分支太多导致终端卡顿。有个仓库有 200 多个分支,git branch -r输出一大串,脚本跑起来倒是不慢,但每次git branch看本地分支列表要翻好几屏。我的做法是定期清理不用的本地分支:git branch --merged main | grep -v main | xargs git branch -d,把已经合并到主分支的本地分支删掉。注意-d是安全删除,只删已合并的,未合并的会报错,避免误删。第四个坑是跟踪关系指向了错误的远程。有次我克隆了一个 fork 的仓库,remote 名字是upstream而不是origin,脚本里写死了origin,结果建出来的分支跟踪关系全是错的。后来我把脚本改成动态获取 remote 名:remote=$(git remote | head -1),然后用$remote替换origin。这样不管 remote 叫什么,脚本都能正确工作。最后一个建议:批量建分支后,用git branch -vv检查一遍。这个命令会列出每个本地分支及其跟踪的远程分支和最新提交,一眼就能看出哪些分支没建好、哪些跟踪关系不对。花十秒钟检查,比后面切错分支改错代码强得多。如果你只是偶尔需要所有分支,手动git checkout <分支名>其实就够了,Git 会自动创建本地分支并建立跟踪。但如果你面对的是几十个分支的仓库,或者需要写自动化脚本,上面这些方法就能帮你省下大量重复劳动。工具是死的,场景是活的,选对方案比记住命令更重要。
1. 为什么“git clone 所有分支”是个伪命题先把一个容易踩坑的认知掰正:git clone默认行为其实已经把所有分支的提交对象都拉到了本地。你打开.git目录,里面objects文件夹装的就是完整的提交历史,远端每一个分支指向的 commit 都在里面躺着。那为什么git branch -a只看到main或者master,其他分支像是“消失”了?原因在于 Git 的引用(ref)映射机制。克隆时,远端的分支引用被映射成了本地的“远程跟踪分支”,也就是origin/xxx这种形式。本地只自动创建一个分支,通常是远端 HEAD 指向的那个默认分支。其他分支不是没拉下来,而是没有在本地创建对应的“本地分支”去跟踪它们。这就像你搬进一栋楼,所有房间的钥匙都挂在物业(.git/refs/remotes),但你手里只拿了一把房门钥匙(本地分支),其他房间你随时能进,只是没配钥匙而已。所以这个标题真正要解决的问题,不是“怎么把数据拉下来”,而是怎么把远程跟踪分支批量转成本地可切换的分支,以及怎么在克隆那一刻就让所有分支都就位。理解了这一点,后面所有操作你都不会迷糊。我见过太多人一上来就搜“git clone 所有分支”,然后照着某些老帖子敲git clone --mirror,结果得到一个裸仓库,连工作区都没有,一脸懵。这就是没搞清楚“数据”和“引用”的区别。下面我把几种真实可用的方案拆开讲,每种适合什么场景、有什么坑,都给你说明白。2. 克隆后批量创建本地分支的三种实战方案2.1 方案一:一条 for 循环搞定所有远程分支这是最通用、最不挑环境的方法。克隆完成后,进入仓库目录,执行下面这段命令:git branch -r | grep -v '\->' | sed 's/origin\///' | while read branch; do git branch --track "$branch" "origin/$branch" 2>/dev/null done拆开看每一步在干什么。git branch -r列出所有远程跟踪分支,输出里通常有一行origin/HEAD -> origin/main,这个箭头行不是真正的分支,所以用grep -v '\->'过滤掉。sed 's/origin\///'把前缀origin/去掉,得到纯分支名。然后while read逐个读取,用git branch --track建立本地分支并设置跟踪关系。末尾的2>/dev/null是为了吞掉“分支已存在”的报错,让脚本可以重复执行。这个方案的好处是幂等,你跑第二遍不会报错中断。实测在一个有 40 多个分支的仓库里,这条命令两秒内跑完。注意--track参数很关键,它让本地分支自动关联对应的远程分支,之后你git pull不用再指定远端,直接就能拉。提示:如果你的默认分支叫main,脚本会尝试为origin/main创建本地main,但本地main已经存在,会报错被吞掉,不影响其他分支。这是正常现象。2.2 方案二:克隆时用 --no-single-branch 配合脚本有些团队的分支特别多,克隆时如果只想要默认分支的历史,可以用--single-branch加速。反过来,如果你明确要所有分支,可以显式加上--no-single-branch:git clone --no-single-branch <仓库地址> myproject cd myproject git branch -r | grep -v '\->' | sed 's/origin\///' | xargs -I {} git branch --track {} origin/{}--no-single-branch是默认行为的显式写法,加上它主要是为了防止某些全局配置或环境变量把默认行为改掉。比如有人配了clone.defaultRemoteName或者用了浅克隆的别名,显式声明能避免意外。xargs -I {}的写法比 while 循环更紧凑,但要注意分支名里如果有特殊字符可能出问题,一般分支名都是字母数字加连字符,不用担心。这个方案适合写进团队的初始化脚本里。我一般会在脚本开头加一句set -e,让任何一步失败就停下,避免半拉子状态。2.3 方案三:用 git remote update 刷新后再批量建分支如果你的仓库已经克隆了一段时间,远端新增了分支,本地git branch -r看不到新的,这时候需要先同步引用:git remote update origin --prune git fetch --all git branch -r | grep -v '\->' | sed 's/origin\///' | while read branch; do git branch --track "$branch" "origin/$branch" 2>/dev/null donegit remote update origin --prune会拉取远端最新的引用列表,同时清理掉远端已经删除但本地还留着的远程跟踪分支。--prune这个参数很多人不知道,它解决的是“远端分支删了,本地origin/xxx还在”的脏数据问题。我踩过一次坑:同事删了一个功能分支,我本地还显示origin/feature-old,结果基于它建了本地分支,推上去又创建了一个同名远程分支,闹了笑话。加上--prune就不会有这个问题。git fetch --all是双保险,确保所有 remote 的引用都是最新的。这两条命令跑完,再执行批量建分支的循环,就能把新增分支也纳入本地。3. 镜像克隆与裸仓库:什么时候该用,什么时候是坑3.1 git clone --mirror 的真实用途git clone --mirror会创建一个裸仓库,它把所有引用(包括远程跟踪分支、标签、甚至 refs/notes)原样复制,并且配置成可以git push --mirror完整回推。听起来很美好,但它没有工作区,你不能直接在里面写代码、提交、切换分支。它适合的场景是做仓库的完整备份或者搭建一个中转镜像。如果你只是想本地开发时能切换到所有分支,用--mirror就是杀鸡用牛刀,而且牛刀还不好使。我见过有人用--mirror克隆后,发现git checkout报错说“此操作必须在工作区中运行”,然后到处问怎么解决。解决办法是从裸仓库再克隆一次,或者用git clone --bare加git config core.bare false手动转成非裸仓库,但这一通操作下来,还不如一开始就用普通克隆加批量建分支。3.2 裸仓库转普通仓库的正确姿势如果你已经用--mirror克隆了,又想要工作区,可以这样救回来:cd mirror-repo.git git config core.bare false git config core.logallrefupdates true git checkout maincore.bare false告诉 Git 这个仓库有工作区,core.logallrefupdates true开启引用日志,方便回滚。然后git checkout main会把默认分支的文件释放到当前目录。但注意,裸仓库的目录结构里没有.git子目录,所有 Git 数据直接在根目录,转成非裸后,工作区文件会和.git数据混在一起,看起来有点怪,但能用。我建议还是重新克隆一次,干净利落。3.3 浅克隆与所有分支的冲突git clone --depth 1是浅克隆,只拉最近一次提交,速度极快,适合 CI 环境。但它默认只拉默认分支,而且历史被截断,其他分支的提交对象根本不在本地。你就算批量建了本地分支,切过去也会发现历史不完整,git log只能看到一条提交。如果确实需要所有分支的完整历史,就别用--depth。如果只是想在浅克隆里看看其他分支的最新代码,可以用git fetch --depth 1 origin <分支名>单独拉某个分支的浅历史,但这不是“所有分支”的常规做法。4. 批量操作中的常见报错与排查手册4.1 报错“fatal: A branch named 'xxx' already exists”这个报错在批量脚本里非常常见,原因就是本地已经存在同名分支。比如你跑了两遍脚本,或者默认分支已经被自动创建了。解决办法就是在git branch --track后面加2>/dev/null吞掉错误,或者用git branch --track ... || true让脚本继续。更优雅的写法是先判断分支是否存在:git show-ref --verify --quiet "refs/heads/$branch" || git branch --track "$branch" "origin/$branch"git show-ref --verify --quiet检查本地分支是否存在,存在就跳过,不存在才创建。这样脚本更健壮,也不会产生一堆错误输出干扰视线。4.2 报错“error: the requested upstream branch 'origin/xxx' does not exist”这说明你试图跟踪的远程分支在本地引用里找不到。可能原因有三个:一是远端确实没有这个分支,你的git branch -r列表是过期的;二是远程跟踪分支的名字不是origin/xxx,比如你用了自定义的 remote 名字;三是--prune刚清理掉了已删除的远程分支,但你的循环还在用旧列表。解决办法是先跑git remote update origin --prune刷新,再重新生成分支列表。如果是自定义 remote 名,把脚本里的origin替换成你的 remote 名即可。4.3 分支名包含斜杠时的处理功能分支经常长这样:feature/user-login、bugfix/issue-123。这种带斜杠的分支名在sed和while read里一般没问题,因为斜杠不是特殊字符。但如果你用xargs且没有正确处理,可能会被拆成多个参数。我建议统一用while read循环,它对含斜杠、含连字符的分支名兼容性最好。另外,git branch --track feature/user-login origin/feature/user-login这种写法完全合法,Git 会自动创建refs/heads/feature/user-login的目录结构。4.4 中文分支名的乱码问题有些团队会用中文命名分支,比如功能/登录模块。在终端里执行批量脚本时,如果 locale 设置不对,git branch -r的输出可能是转义后的八进制字符,导致建出来的本地分支名乱码。解决办法是设置export LANG=en_US.UTF-8或者export LC_ALL=en_US.UTF-8,让 Git 以 UTF-8 输出。更好的做法是别用中文分支名,这不是 Git 的限制,而是各种工具链(CI、IDE、命令行)对中文支持参差不齐,迟早出问题。5. 高效管理多分支的进阶技巧5.1 用 git branch --set-upstream-to 修正跟踪关系批量建分支时如果忘了加--track,本地分支和远程分支就没有关联,git pull会报“no tracking information”。补救方法是对每个分支执行:git branch --set-upstream-to=origin/<分支名> <本地分支名>批量修正可以这样:for b in $(git branch --format='%(refname:short)'); do git branch --set-upstream-to="origin/$b" "$b" 2>/dev/null donegit branch --format='%(refname:short)'只输出分支短名,比解析git branch的星号和空格更可靠。这个脚本会把所有本地分支的跟踪关系重新指向同名的远程分支,适合在批量建分支后统一修正。5.2 用 git config 设置默认推送行为多分支环境下,git push的默认行为很容易让人困惑。Git 2.0 之后,push.default的默认值是simple,它只推送当前分支到同名的远程分支,如果远程没有同名分支就会报错。你可以改成current,这样推送当前分支到同名远程分支,不存在就创建:git config --global push.default current这个设置在多分支开发时特别顺手,不用每次git push -u origin <分支名>。但要注意,current不会自动建立跟踪关系,第一次推送后还是建议用--set-upstream-to补上。5.3 用 git fetch 的 refspec 一次性拉取所有分支除了克隆后建分支,还有一种思路是在git fetch时用 refspec 把所有远程分支映射到本地分支:git fetch origin '+refs/heads/*:refs/heads/*'这个 refspec 的意思是:把远端refs/heads/下的所有引用,强制映射到本地refs/heads/下。+表示允许非快进更新。执行后,本地会直接出现所有远程分支对应的本地分支,不需要再跑循环。但这个方法有个副作用:它会覆盖本地同名分支,如果你本地有未推送的提交,可能会丢。所以用之前一定要确认本地没有需要保留的独有提交,或者先git stash或建临时分支备份。注意:这个 refspec 写法比较激进,适合在干净的克隆仓库里用,不适合日常开发仓库。5.4 用别名简化批量操作如果你经常需要批量建分支,可以把它做成 Git 别名:git config --global alias.pullall '!git branch -r | grep -v "\->" | sed "s/origin\///" | while read b; do git branch --track "$b" "origin/$b" 2>/dev/null; done'之后直接git pullall就能一键建好所有本地分支。别名以!开头表示执行 shell 命令,注意里面的引号转义。这个别名我用了好几年,换电脑第一件事就是配上。6. 不同场景下的方案选型对照场景推荐方案关键命令注意事项全新克隆,需要所有分支普通克隆 + 批量建分支脚本git clone后跑 while 循环脚本要幂等,吞掉已存在报错已有仓库,远端新增分支remote update + 批量建分支git remote update --prune先刷新引用再建分支做仓库完整备份git clone --mirrorgit clone --mirror裸仓库无工作区,不能直接开发CI 环境快速拉取浅克隆 + 按需 fetchgit clone --depth 1历史不完整,不适合本地开发一次性映射所有分支fetch refspecgit fetch origin '+refs/heads/*:refs/heads/*'会覆盖本地同名分支,慎用日常多分支开发别名 + push.default currentgit config --global push.default current首次推送后补跟踪关系这张表是我自己踩坑总结出来的,你可以根据手头的情况直接对号入座。新手最容易犯的错就是不管什么场景都上--mirror,结果被裸仓库卡住。记住一个原则:要开发就用普通克隆,要备份才用镜像。7. 我踩过的坑和给你的实操建议第一个坑是在错误目录执行脚本。有次我在父目录跑批量建分支,结果 Git 找不到仓库,报了一堆错。后来我在脚本开头加了git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "不在 Git 仓库中"; exit 1; },先检查当前目录是不是 Git 仓库,不是就退出。这个检查能省掉很多莫名其妙的报错。第二个坑是分支名大小写问题。Windows 和 macOS 的文件系统默认大小写不敏感,Feature/Login和feature/login在本地可能被当成同一个分支,但在 Linux 服务器上是两个不同分支。批量建分支时如果遇到大小写不同的分支名,本地可能只创建一个。解决办法是在大小写不敏感的系统上,避免创建仅大小写不同的分支名,这是团队规范问题,不是脚本能解决的。第三个坑是远程分支太多导致终端卡顿。有个仓库有 200 多个分支,git branch -r输出一大串,脚本跑起来倒是不慢,但每次git branch看本地分支列表要翻好几屏。我的做法是定期清理不用的本地分支:git branch --merged main | grep -v main | xargs git branch -d,把已经合并到主分支的本地分支删掉。注意-d是安全删除,只删已合并的,未合并的会报错,避免误删。第四个坑是跟踪关系指向了错误的远程。有次我克隆了一个 fork 的仓库,remote 名字是upstream而不是origin,脚本里写死了origin,结果建出来的分支跟踪关系全是错的。后来我把脚本改成动态获取 remote 名:remote=$(git remote | head -1),然后用$remote替换origin。这样不管 remote 叫什么,脚本都能正确工作。最后一个建议:批量建分支后,用git branch -vv检查一遍。这个命令会列出每个本地分支及其跟踪的远程分支和最新提交,一眼就能看出哪些分支没建好、哪些跟踪关系不对。花十秒钟检查,比后面切错分支改错代码强得多。如果你只是偶尔需要所有分支,手动git checkout <分支名>其实就够了,Git 会自动创建本地分支并建立跟踪。但如果你面对的是几十个分支的仓库,或者需要写自动化脚本,上面这些方法就能帮你省下大量重复劳动。工具是死的,场景是活的,选对方案比记住命令更重要。