如何正确拉取超大体积的git项目——开发小技巧
最近遇到一个体积相当大的仓库(40GB+),结果在安利给群内小伙伴时,很多人遇到了直接使用 git clone
克隆仓库到本地时,对本地网络的稳定性有巨大挑战,一旦网络波动导致传输中断,就只能从头下载。
很多人拉项目时习惯git clone
一把梭哈,这并不是一个很好的习惯,众所周知国内访问github属于玄学,而且有些项目非常大,搞不好需要好几个小时才能拉取完,长时间+不稳定的网络,很容易出意外。本文就是介绍两种应对超大体积项目的拉取的办法「Git LFS」和「Git fetch」。
文章目录
Git 的 git clone
命令本身是不直接支持断点续传的,git clone
本质上是创建一个新仓库,并一次性拉取远程所有数据(包括提交历史、分支、标签等)。如果中途中断本地目录会处于不完整状态,直接重试 git clone 会失败,如果你退出终端本地目录也会被清空。
使用 Git Large File Storage(Git LFS)
简单介绍一下 Git LFS
Git Large File Storage(Git LFS)是一个用于管理大型文件的Git扩展工具,旨在解决Git原生对大文件支持不足的问题。
Git LFS 优点
- Git LFS用轻量级文本指针(如oid sha256:…)替换实际大文件,避免仓库臃肿。
- 大文件内容存储在专用服务器(如GitHub LFS、块储存、自建储存、CDN),仅按需下载。
- 支持单个文件GB级别存储,突破Git对文件大小的限制。(比如 github 是单文件小于100MB,单文件大于50MB会出现警告)
- 因为大文件实际是分离储存的,可以优化拉取速度。
- 安装Git LFS 并配置好后,日常 git 操作时,几乎是无感的,Git LFS 会自动处理大文件。
Git LFS 缺点
- 需要项目创建者配合从一开始就使用 Git LFS,如果项目没有采用,对于想要克隆拉取项目的人是没有办法去使用 Git LFS 的。
- 额外的大文件储存和下载都是需要开发者额外掏钱的,像是GitHub就只有10 GiB的免费空间和流量可用,超过的部分需要额外收费。(如果你是pth之类的AI模型文件,huggingface之类的平台给了免费的 LFS 空间)
不要 git clone 一把梭哈,改用 git fetch 分步拉取
简单介绍一下 git fetch 分步拉取
Git LFS 更多面对的是项目中部分文件体积很大的情况,比如Unity项目中的.asset文件、PSD源文件、CSV数据集。但还有一种情况,项目中每个文件体积都不大,可能只有几兆到十几兆,但是项目中文件数量极多,几百上千个,加到一起后整个项目体积也到了 GB 规模。这个时候更适合分步拉取的方式。
和 git clone 相比 git fetch 的优势
- git fetch 基于 Git 对象模型,天然支持断点续传。
- 即使多次中断,只要本地 .git 目录未损坏,均可通过反复执行 git fetch 逐步补全数据。
- 如果中断期间远程仓库新增了提交,git fetch 会同时下载新增内容和未完成的旧内容,最终保持本地与远程一致。
和 git clone 相比 git fetch 的缺点
除了操作稍微多了几个步骤,没任何额外的缺点。
git fetch 分布拉取的方法
- 先手动创建空仓库并构建
.git
文件
mkdir your-repo && cd your-repo
git init
git remote add origin https://github.com/user/repo.git
- 分步拉取数据
git fetch origin --progress # 如果中间传输中断,就在目录下再执行一次这个命令即可。
- 等待拉取完毕(以下仅为举例,请根据实现终端显示为准),这时候项目所有内容都会被打包在
.git/objects/pack
目录下的.pack
文件内。
Resolving deltas: 100% (9999/9999), done.
From https://github.com/user/repo.git
* [new branch] master -> origin/master
* [new tag] v1.0 -> v1.0
* [new tag] v1.1 -> v1.1
* [new tag] v1.2 -> v1.2
* [new tag] v2.0 -> v2.0
* [new tag] v2.1 -> v2.1
* [new tag] v2.2 -> v2.2
* [new tag] v2.3 -> v2.3
* [new tag] v2.4 -> v2.4
* [new tag] v3.0 -> v3.0
- 将需要的分支检出,比如我们检出 master 主分支。
git checkout master
- 其他优化建议
使用浅克隆减少首次下载量,比如只拉取最新分支
git clone --depth 1 https://github.com/user/repo.git
之后再补全历史(或者就干脆不补全,节约点空间)
git fetch --unshallow
总结
总的来说 Git LFS 主要是应对项目中出现几个巨大体积文件的情况,git fetch 主要是应对一次开机无法完成下载的超大型仓库或不稳定网络环境,比直接 git clone 一把梭哈更加灵活。
PS:顺带提一嘴,如果多次中断和重新拉取,可能会在.git/objects/pack
目录下出现很多个.pack文件。如果需要清理的的话,在项目目录下执行git gc --auto
。
再PS:不用在意.pack文件的巨大体积,因为工作目录下你看到的具体文件,是通过硬链接、符号链接构建的,工作目录内的文件和 .pack 中的对象共享同一份数据,并不会真实占用双倍物理空间。实际占用大概是1.2~1.3倍空间,因为.pack文件还是有一定的压缩的。
石樱灯笼
2025-05-15 15:06
有些曾经很烂的仓库必须得 –depth 这个参数才能解决。像我之前的公司,每次提交都会把node_modules目录全都提交上去,假如中途换人开发的话还会把node_modules删掉重建一个,每次git都可以把Windows的文件浏览器搞崩溃。
大文件项目现在基本没有在GitHub上的了,全跑去huggingface了,尤其是AI生成项目,一个模型就上G。
去年夏天
2025-05-15 15:10
嗯,用github的也是把项目文件放上去,但是模型都放huggingface上,用Git LFS链接模型。
github那个大文件流量费用,个人开发者一个不小心就破产了。
石樱灯笼
2025-05-15 16:43
我倒是挺喜欢传统的大文件放特定位置让用户自己下载的方式。
现在线上这些方式,把新手开发者都养坏了,上来自动化部署就从线上往下抠个几十G的库文件,也不管用不用得上,部署个几十M就够用的Docker里塞一个几十G的库文件的傻屌行为太多了,然后过一阵子服务端各种原因一崩,整个业务全断,在互联网上也找不到备份,项目就死了。
ACEVS
2025-05-15 10:03
分段拉取不错。
去年夏天
2025-05-15 10:39
分段是个好习惯,之前不知道,时不时遇到魔法不稳定导致的断开
obaby
2025-05-14 16:49
git fetch 看起来这个不错
去年夏天
2025-05-15 10:38
主要支持断点续传……下班前没搞定还可以第二天继续