Git sparse checkout仅控制工作区路径显示,不减少对象下载;真正省空间需结合partial clone(--filter=blob:none)与--cone模式初始化,并用reapply刷新工作区。

Git sparse checkout 听起来像“只拉几个文件进来”,但实际没那么简单——它管的是工作区里能看到哪些路径,对象库该下多大还是下多大。想省磁盘、省带宽,得把 partial clone 和 sparse-checkout 绑在一起用,否则只是“表面轻量”。
git sparse-checkout init --cone 是当前最稳的起点
别再用老办法往 .git/info/sparse-checkout 里一行行 echo 路径了。Git 2.25+ 推荐 git sparse-checkout init --cone,它启用“锥形模式”(cone mode),规则更简洁、性能更好、也少踩坑。
--cone模式下,指定目录名(比如torch/nn),Git 自动包含它的所有子目录,外加所有父级路径(像torch/和根目录下的setup.py)- 不加
--cone就是传统非锥形模式,得写!/docs/**这种 gitignore 风格规则,容易漏、难调试 - 执行后 Git 自动设置
core.sparseCheckout=true和core.sparseCheckoutCone=true,并生成带注释的.git/info/sparse-checkout
只检出、不下载:必须加 --filter=blob:none
光开 sparse-checkout 不管用。如果你先 git clone 再 git sparse-checkout set,Git 还是会把整个仓库的 blob(文件内容)全拉到 .git/objects 里——只是不解压到工作区而已。真正节省空间,得从克隆那一刻就过滤。
- 正确做法:
git clone --filter=blob:none --no-checkout,进目录后git sparse-checkout init --cone && git sparse-checkout set torch/nn torch/cuda setup.py --filter=blob:none表示跳过所有文件内容下载;后续首次访问某个文件时,Git 会按需 fetch(lazy fetch)- 注意:该参数要求远程服务器支持 protocol v2(GitHub、GitLab 2021 年后基本都支持,自建 Gitea/GitServer 需确认)
git sparse-checkout set 后工作区没更新?试试 reapply
常见场景:执行 git sparse-checkout set src/web components/ui 后,src/web 目录空空如也,git status 也显示 clean。这不是失败,而是 Git 没触发重检出。
- 运行
git sparse-checkout reapply强制重新应用规则,把匹配路径的文件从索引写入工作区 - 如果提示 “error: Your local changes would be overwritten”,说明那些路径下已有未跟踪文件(比如你手动创建过
src/web/index.html),Git 不敢覆盖——先git clean -fd或手动删掉冲突文件 - 也可以用
git read-tree -m -u HEAD替代reapply,但更底层、风险略高,日常推荐reapply
切换分支时 sparse-checkout 规则会失效?不是 bug,是设计
在 sparse 模式下切分支,Git 默认只更新你“关心”的路径。比如在 main 分支只检出了 src/web,切到 feat/api 后,src/web 会更新,但 src/backend 即使该分支有改动也不会出现在工作区——这是预期行为,不是卡住了。
- 如果某次切分支后发现关键文件“消失”,先运行
git sparse-checkout list确认当前规则是否还在 - 需要临时看全量?用
git sparse-checkout disable,它会清掉 SKIP_WORKTREE 标志并恢复全部文件(但不会重新下载 blob) - 注意:
git commit -a在 sparse 模式下**不会**把未检出路径里的修改当删除处理,这点和直觉相反,但能避免误删
真正麻烦的从来不是怎么配 sparse-checkout,而是团队协作时别人没开、CI 流水线没设 filter、或者某个脚本硬编码了 ls src/ 却忘了目录可能根本不存在——这些地方比命令本身更容易翻车。