更新

  • 2018/05/13 更新实践篇
  • 2017/12/03 初次发布

简介

Git Large File Storage (LFS) replaces large files such as audio samples, videos, datasets, and graphics with text pointers inside Git, while storing the file contents on a remote server like GitHub.com or GitHub Enterprise.

Git Large File Storage

Git LFS 官网上的介绍就是将大文件替换为 Git 中的文本指针,并将大文件的内容存储在远程服务器上。

可以说这种管理方式非常适合游戏项目:

  1. 仓库体积可以有效地减小,提升 Git 相关操作速度。
  2. 克隆仓库时由于不需要大文件的历史记录,可以有效减少传输数据大小。

本篇文章是测试,Git 迁移到 Git LFS 实践 - 狂飙 是实践,包含服务器配置、转换之后遇到的其他问题等等。

迁移

环境

  • macOS 10.12.6
  • Git 2.13.2
  • Git LFS 2.3.4
  • GitLab 10.1.3
  • git-lfs-migrate 0.2.5

安装

Git LFS

直接参考官网 Git Large File Storage 安装即可:

1
2
brew install git-lfs
git lfs install

git-lfs-migrate

Releases · bozaro/git-lfs-migrate · GitHub

步骤

查找大文件的扩展名

查找大于 1M 大小的所有文件的扩展名,可以根据需要修改此数值:

1
find Assets -type f -size +1M | grep -o -E "\.[^\.]+$" | sort | uniq -c | sort -rn

linux - Bash command for finding file extensions with largest size - Super User

转换仓库

将上一步得到的扩展名列表手工处理,转换成迁移工具需要的命令行参数形式。 将列表粘贴到 Vim 中,然后输出以下命令:

1
2
%s/^.*\./"*./
%s/$/"\\/

然后将其放在迁移命令的最后,执行命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
java -jar git-lfs-migrate.jar \
     -s /path/to/your/repository/.git \
     -d /path/to/converted/repository/.git \
     -g git@server:your/repository.git \
     "*.FBX"\
     "*.TGA"\
     "*.aar"\
     "*.asset"\
     "*.bmp"\
     "*.bundle"\
     "*.bytes"\
     "*.chm"\
     "*.chw"\
     "*.compute"\
     "*.controller"\
     "*.cubemap"\
     "*.dds"\
     "*.dll"\
     "*.exe"\
     "*.fbx"\
     "*.jpg"\
     "*.mdb"\
     "*.mel"\
     "*.mp3"\
     "*.otf"\
     "*.pdf"\
     "*.png"\
     "*.psd"\
     "*.swatch"\
     "*.tga"\
     "*.tif"\
     "*.ttf"\
     "*.unity"\
     "*.wav"\
     "*.xlsx"\
     "*.zip"

注意:如果仓库过大,迁移过程可能会花数小时。作为例子,30GiB 裸仓库迁移用时 2 小时 19 分钟。

检查结果

运行校验并推送:

1
2
cd /path/to/converted/repository
git fsck && git push --mirror git@server:your/repository.git

打开 GitLab 使用管理员账号检查仓库的 LFS 占用是否正确。

结果

转换前

整个大小 42G 裸仓库 30G objects 30G GitLab 统计 Storage: 28.1 GB ( 28.1 GB repository, 0 Bytes build artifacts, 0 Bytes LFS )

转换后

整个大小 15G 裸仓库 7.8G 其中 objects 788M lfs 7.0G GitLab 统计 Storage: 89.9 GB ( 1.1 GB repository, 0 Bytes build artifacts, 88.8 GB LFS )

通过数据可以看到,在排除掉 LFS 对象后,仓库实际大小由 30GiB 缩小到 788M,效果非常明显。

注:大小统计使用 du -sh . 命令。

使用

克隆仓库

转换前

克隆整个仓库 30 分钟以上。

转换后

1
2
3
4
5
6
7
8
9
git lfs clone git@server:your/repository.git
Cloning into 'repository'...
remote: Counting objects: 532778, done.
remote: Compressing objects: 100% (136135/136135), done.
remote: Total 532778 (delta 399207), reused 529501 (delta 396211)
Receiving objects: 100% (532778/532778), 773.86 MiB | 41.58 MiB/s, done.
Resolving deltas: 100% (399207/399207), done.
Checking out files: 100% (23520/23520), done.
Git LFS: (4555 of 4555 files) 6.97 GB / 6.97 GB

克隆整个仓库 7 分 27 秒。

由于使用了 git lfs clone,Git LFS 会使用并行下载来加速,可以看到提速十分明显。

注意事项

GitLab 官方文档建议使用 HTTPS 才可以下载 LFS 对象,但实际测试并不需要。如果有需要可以为服务器单独申请付费证书。

GitLab 对 LFS object 的管理还没到位,虽然文档中说明已在 8.14 中加入清理功能,但实际上功能未完成。 Prune unreferenced Git LFS objects (#30639) · Issues · GitLab.org / GitLab Community Edition · GitLab

Git LFS 默认使用 smudge clean 过滤器与 pre-push 本地钩子,如果使用了 pre-push 钩子,需要修改钩子调用 Git LFS 钩子。以下文章提到了此问题并给出了解决方案。 化繁为简的企业级 Git 管理实战(五):二进制大文件的版本控制 | HaHack

Download Zip 功能无法下载到存储在 Git LFS 中的对象 “Download ZIP” archiver does not resolve Git-LFS references (#14261) · Issues · GitLab.org / GitLab Community Edition · GitLab

扩展阅读

大文件管理相关探索,包含各种方式,最后一种是 Git LFS。 How to manage big Git repositories

此教程讲得很细,将每一步及其对应的输出都写了;而且 SourceTree 的创始人也是 Git LFS 的主要贡献者。 Git LFS - large file storage | Atlassian Git Tutorial

提交时检查是否包含过大文件。 GitHub - Ninjaccount/git-big-lfs-hook: Git hook to prevent commit if a file is too big and not tracked by lfs.

非常详细的实践操作,包含 Windows 平台内容。 Git LFS 操作指南