如何正确拉取超大体积的git项目——开发小技巧

浏览: 56 次浏览 作者: 去年夏天 分类: 技术文章,Ubuntu,Windows 发布时间: 2025-05-14 15:48

最近遇到一个体积相当大的仓库(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 分布拉取的方法

  1. 先手动创建空仓库并构建.git文件
mkdir your-repo && cd your-repo
git init
git remote add origin https://github.com/user/repo.git
  1. 分步拉取数据
git fetch origin --progress  # 如果中间传输中断,就在目录下再执行一次这个命令即可。
  1. 等待拉取完毕(以下仅为举例,请根据实现终端显示为准),这时候项目所有内容都会被打包在.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
  1. 将需要的分支检出,比如我们检出 master 主分支。
git checkout master
  1. 其他优化建议

使用浅克隆减少首次下载量,比如只拉取最新分支

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文件还是有一定的压缩的。

分享这篇文章
7 条评论
  • 石樱灯笼

    2025-05-15 15:06

    有些曾经很烂的仓库必须得 –depth 这个参数才能解决。像我之前的公司,每次提交都会把node_modules目录全都提交上去,假如中途换人开发的话还会把node_modules删掉重建一个,每次git都可以把Windows的文件浏览器搞崩溃。

    大文件项目现在基本没有在GitHub上的了,全跑去huggingface了,尤其是AI生成项目,一个模型就上G。

    1. 去年夏天

      2025-05-15 15:10

      嗯,用github的也是把项目文件放上去,但是模型都放huggingface上,用Git LFS链接模型。
      github那个大文件流量费用,个人开发者一个不小心就破产了。

      1. 石樱灯笼

        2025-05-15 16:43

        我倒是挺喜欢传统的大文件放特定位置让用户自己下载的方式。
        现在线上这些方式,把新手开发者都养坏了,上来自动化部署就从线上往下抠个几十G的库文件,也不管用不用得上,部署个几十M就够用的Docker里塞一个几十G的库文件的傻屌行为太多了,然后过一阵子服务端各种原因一崩,整个业务全断,在互联网上也找不到备份,项目就死了。

  • ACEVS

    2025-05-15 10:03

    分段拉取不错。

    1. 去年夏天

      2025-05-15 10:39

      分段是个好习惯,之前不知道,时不时遇到魔法不稳定导致的断开

  • obaby

    2025-05-14 16:49

    git fetch 看起来这个不错

    1. 去年夏天

      2025-05-15 10:38

      主要支持断点续传……下班前没搞定还可以第二天继续

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理