GitHubでLFSを使ってリポジトリを管理する

技術

前回の記事でBitBucketからGitHubへのリポジトリ移行に失敗しました。

100MBを超える大きなファイルがリポジトリに含まれていたのが原因だったので、今回はLFS(Large File Storage)を使ってみます。

こむ太郎
こむ太郎

ずっとGitを使ってるけどLFSは使ったことなかった。

LFS(Large File Storage)とは

LFSはGitの拡張仕様で、大容量ファイルを効率的に管理するためのものです。

通常のGitリポジトリでは、全てのファイルのバージョンがリポジトリ内に保存されますが、これは大容量ファイルに対しては不適切で、リポジトリの肥大化を引き起こす可能性があります。LFSを使用すると、大容量ファイルはリポジトリ外のLFSサーバーに保存され、Gitリポジトリにはその参照情報だけが保存されます

LFSを使う場合の動作としては、リソースをPushした際にフックされ、サイズの大きなファイルはGitリポジトリとは別に用意されたLFSサーバーに実態が格納されます。Gitリポジトリ内にはLFS内のファイルへの参照だけが記録されます。

こむ太郎
こむ太郎

サイズの大きなファイルと書きましたが、正確にはあらかじめLFSの管理対象にするファイルの拡張子を指定しておきます。指定すればサイズに関係なくLFS管理になります。

これにより、リポジトリの肥大化を防ぎつつ、大容量ファイルのバージョン管理を効率的に行うことが可能になります。

ただし、LFSを使うにあたっては考慮、解決すべき問題があります。

LFSの問題点

僕がLFSを使おうと思って立ち塞がった問題点です。

LFSの問題点
  • 既存のリポジトリを移行する場合、すでに過去にコミット済の履歴のファイルはLFS管理にうつらない
  • 利用するのには費用がかかる
  • LFSに対応しているGitサーバーが必要

順に説明します。

既存のリポジトリを移行する場合、すでにコミット済みのファイルはLFS管理できない

これは過去にすでにコミットされてリポジトリに入っているファイルをどうするかという問題です。

新規でリポジトリを作るなら良いのですが、すでに過去にコミットしてGitリポジトリに格納されている100MBを超えるサイズのファイルはLFSに移行できないので、結局、サイズ制限でGitHubへの移行はできません。

こむ太郎
こむ太郎

Pushされる際にフックされるので、すでにGitに格納されているファイルまではLFSに移りません。

過去のコミット履歴を改竄するという荒技はあるようですが、あまりスマートな方法ではありません。

今回は諦めて過去のコミット履歴を捨て、最新のファイル一式だけを移行する方針にしました。

こむ太郎
こむ太郎

これを機にリポジトリを綺麗にしようと思います。

利用するのには費用がかかる

いままでGitを無料で使えていたので使用料が発生するのは抵抗ありますが仕方ないです。ただ、なるべく費用は抑えたいし、どのくらいの費用がかかるのか把握できるところまで、まずはやってみます。

こむ太郎
こむ太郎

便利なサービスをいままで無料で使えてたのは、BitBucketさん太っ腹すぎですね。

GitHubもLFSを使わなければ無料ですし。

LFSに対応しているGitサーバーが必要

GitHubやBitBucketなどメジャーどころはLFSに対応してます。また、Gitの基本サービスはGitHubを使ってLFSサーバーだけは外部に用意して使うことも可能なようです。

ですがGitサーバー自体がLFSに対応している必要があります。レンタルサーバーが提供しているGitサーバーを使う場合はLFSに対応してない場合もあります。

こむ太郎
こむ太郎

サービス内容と費用を考えると、あまり選択肢は多くないと思います。

ということで費用のこともあわせて検討してみます。

まずはGitHubでLFSを使ってみた

ローカル側の準備

最初に書いたようにLFSはGitの拡張仕様ですが、Gitとは別にGit-LFSのインストールが必要です。

僕はMacBookを開発環境に使っていますので、とりあえずMacBook側にGit-LFSをインストールします。

僕はbrewを使ってMacBookを管理しているのでbrewでインストールします。といっても下のコマンドを実行するだけです。

brew install git-lfs
こむ太郎
こむ太郎

ちなみにWindowsだとGitをインストールするとGit-LFSも一緒にインストールされるらしいです。

Git-LFSをインストールしただけではLFSを使うことができるようになっただけで、実際にリポジトリでLFSを使うための設定というかおまじないが必要です。

次のコマンドを実行します。これでLFSを使えるようになります。②の場合はローカルにクローンしたGitのリポジトリのディレクトリの中で実行します

//①全てのリポジトリで使用する場合
git lfs install
//②特定のリポジトリでだけ使用する場合
git lfs install --local
こむ太郎
こむ太郎

②の場合はLFSを使用するリポジトリそれぞれで実行する必要があります。
詳しく知りたい方は下のサイトも参考にしてください。

Bitbucket で Git LFS を使用する | Bitbucket Cloud | アトラシアン サポート
Bitbucket Cloud は、大容量ファイルの処理を高速化する、Git の Large File Storage (LFS) 拡張機能をサポートします。この機能の開始方法をご覧ください。

今回は試しにBitBucketからクローンしたローカルのリポジトリ内で実行してみました。Pushするまではoriginのリモートリポジトリの方には何もおきません。

ここで移行前のリポジトリで実際にサイズの大きいファイルやバイナリのファイルがどのくらいあるのかを把握しておきたかったので、動作確認がてらlfsのコマンドでリポジトリに含まれるファイルの拡張子別サイズの集計を調べてみました。

以下のコマンドを実行してみます。

git lfs migrate info --top=100 --everything

–everythingオプションは履歴を含めて集計してくれるオプションだそうです。

こむ太郎
こむ太郎

最新リビジョンだけでの集計の仕方が分かりませんでした。

知ってる人がいたら教えてください。

結果は多いので端折ってますが、下のような結果でした。

migrate: Sorting commits: …, done.

migrate: Examining commits: 100% (183/183), done.

.so 1.0 GB 35/35 files 100%

.png 658 MB 6170/6170 files 100%

.bundle 573 MB 32/32 files 100%

.a 550 MB 43/43 files 100%

.tga 255 MB 59/59 files 100%

.prefab 185 MB 1641/1641 files 100%

.unity 165 MB 312/312 files 100%

.fbx 142 MB 533/533 files 100%

.dll 140 MB 292/292 files 100%

.aar 133 MB 380/380 files 100%

.srcaar 114 MB 35/35 files 100%

.zip 80 MB 10/10 files 100%

.wav 64 MB 55/55 files 100%

.psd 36 MB 39/39 files 100%

.bytes 36 MB 231/231 files 100%

.cs 36 MB 4660/4660 files 100%

.exe 32 MB 4/4 files 100%

.ttf 28 MB 110/110 files 100%

.anim 28 MB 196/196 files 100%

.asset 22 MB 819/819 files 100%

.jpg 22 MB 58/58 files 100%

.meta 20 MB 17823/17823 files 100%

.mp3 17 MB 167/167 files 100%

.jar 15 MB 69/69 files 100%

.pdf 14 MB 12/12 files 100%

上位の拡張子はえげつないですね。GitHubのLFSでは1GB以上は有料になるので、やはり過去の履歴を含めると無料枠を軽く超えそうです。

最新リビジョンだけ移行すれば無料枠に収まるかもしれませんが、将来的には月額料金を払うかLFSサーバーを別に用意することを検討する必要がありそうです。

LFS管理対象にするファイルの検討

LFSを使うにはLFSの管理対象にするファイルを拡張子で指定します。

このため、どの拡張子をLFSで扱うかを検討します。

サイズの大きくなりそうなファイルは確実に管理対象に含めますが、バイナリのファイルはGitで管理するメリットがあまりないので、できるだけLFS管理にしたいところです。

あとで対象を変更することはできるはずですが、あとで変更してもコミット済みの履歴までは修正できないので、LFSを使い始める前にちゃんと検討して管理対象を決めておいた方が良いです。

将来のことを予測して事前に対象の拡張子を決めるのはなかなか難しいのですが、ここは先人たちの知恵を拝借します。

LFS対象の拡張子は.gitattributesファイルで設定するのですが、下の2つのサイトからプログラミング言語ごとの.gitattributesの雛形を入手できます。

gitattributes
gitattributes has 3 repositories available. Follow their code on GitHub.
.gitattributes for Unity projects
.gitattributes for Unity projects. GitHub Gist: instantly share code, notes, and snippets.

僕のプロジェクトはUnityのプロジェクトですが、Unity用の雛形もありました。

だいたい、雛形通りに設定してしまえば良さそうですが、僕のリポジトリにあったbundleaarsrcaarといった拡張子は雛形には含まれてませんでしたので、必要に応じて多少の見直しが必要かもしれないですね。

今回はひとつ目のサイトから持ってきた.gitattributesの雛形にbundle、aar、 srcaarを追加して使うことにしました。

こむ太郎
こむ太郎

拡張子をひとつずつ自分で登録していくのは大変なので、雛形を公開してくれている方がいるのは助かります。

LFSを有効にしてGitHubにリポジトリをPushしてみた

事前の準備が済んだのでいよいよGitHubにLFSを有効にしてリポジトリを移行してみます。

まずGitHub側には移行先の空のリポジトリを事前に用意しておきます。

僕は前の記事の時に移行に失敗した空のリポジトリがあるのでそこを使います。

まずGitHubからローカルに移行先の空のリポジトリをクローンしておきます。

中身は空っぽなのでクローンしたディレクトリに移行元のリポジトリの最新ソース一式を全部格納しました。

そしてリポジトリごとにLFSの使用を設定する場合は、クローンしたディレクトリでもLFSを有効にするおまじないをします。

git lfs install --local

さらにディレクトリの直下にLFSの管理対象の拡張子を設定した.gitattributeも格納します。.gitignoreファイルと同じ場所です。

そして移行するファイル一式をCommitしたあとにGitHubへPushしてみました。僕はいつもSourceTreeを使っているので今回もSourceTreeから実行しました。

無事成功。ですが、メッセージを見るとどうも最新のソースだけでもLFSに1GB近いオブジェクトが登録されたようです。

いちおうGitHubの管理画面でも確認したら、やはり無料枠をほぼ使い切ってしまったようです。

下の管理画面はGitHubのアカウントのアイコンをクリックしたメニューのSettingからAccess > Billing and plans > Plans and usageで確認できます。

Strageを969MB使ってしまいました。見出しの横の数値は0.00GB of 1GBとなっていますが、少しあとでもう一度確認したら0.95GBに更新されていました。表示にはちょっとタイムラグがあるようです。

Bandwidth(帯域)の方は0.0GBになってますが、アップロードするときには加算されないのかな?

Pushされた画像ファイルの一つをGitHub側で確認してみましたが、Stored with git LFSと出ているのでちゃんとLFS管理になっているようです。

ということで、履歴を捨てた最新リビジョンのリソースのみで無料枠の1GBをほぼ使い切りました。

ちなみにローカルでは.git配下のlfs/objects/以下にLFS管理になったファイルが格納されているようです。

そして、LFSサーバーに関する情報はローカル側では.git/config/configファイルに設定が書き込まれているようです。

一部マスクしてますが、以下のような記載がありました。

[branch "main"]
	remote = origin
	merge = refs/heads/main
[lfs]
	repositoryformatversion = 0
[lfs "https://github.com/アカウント名/リポジトリ名.git/info/lfs"]
	access = basic

今回は特に指定しなかったのでGitHub内部のLFSサーバーが使われましたが、自分で用意した外部のLFSサーバーを使いたい場合は、この中のlfsのURLを変更すれば良さそうです。

ということで、LFSを使ってみましたが、結果は一気にGitHubの無料枠を使い切ることになってしまいました。

履歴なしの初期リポジトリだけでちょうど使い切った感じです。

リポジトリには不要なファイルもかなり含まれていると思うので、あとはお掃除して不要ファイルを消すしかないですね。

LFSのデータ削除

とりあえず、LFSの使い方はわかったのでGitHubで使い切ってしまったLFS領域は解放します。

解放するにはリポジトリを削除してしまえば、LFSのデータもろとも削除されるようです。

リポジトリを削除するにはリポジトリの設定画面から一番下のDelete this repositoryで削除できます。

リポジトリを削除して少し経ったら、LFSのデータも削除されていましたので、また1GB枠が使えるようになっていると思います。

結局LFSの運用はどうするのか

今回LFSを試してみて、GitHubの無料枠の中でLFSを使うというのはどうも無理らしいということがわかりました。

あくまでも僕の場合ということではあるのですが、LFSを使おうといういう人はおそらくサイズの大きなファイルの扱いに困っている人だと思うので、そういう人向けに1GBまでという無料枠は心許ないです。

おそらくLFSを使う場合は課金をすることになるでしょう。

GitHubでは課金すると50GBまで使えて$5/月だそうです。50GBを超えるとさらに課金が必要です。

50GBならしばらくは大丈夫かもしれないですが、履歴が増えていったりリポジトリが増えていったりするとどこまで持つか怪しいです。が、$5という料金も絶妙で、払ってもいいかな思える金額です。

他の案も考えてみる

GitHubで$5ドル払う以外の方法も検討してみました。

GitHub以外でLFSを使う代案
  • LFSサーバーを自前で別に用意する
  • GitHub以外のサービスを使う
  • LFSは諦める

AWSのS3などを使って自前で構築したLFSサーバーで運用をすることを考えました。

通常のファイルはGItHubを使ってLFS対象のファイルはS3に格納するということです。

上の方に書いたようにLFSサーバーはGitHubの外に用意したものを使うこともできるようですし、実際にやってる人もいるようです。

「Git LFS × AWS S3」で大容量ファイルを構成管理する - 電通総研 テックブログ
こんにちは、ISID 金融ソリューション事業部の孫です。 皆さんはGitでソースコードの構成管理を行う中で、バイナリファイルのサイズが大きすぎてGitHubなどのホスティングサービスからブロックされたりした経験はないでしょうか。 実は、最近...
こむ太郎
こむ太郎

何をするにも、たいてい先駆者が道を開いてくれているので助かりますね

S3は安いイメージがあったので、S3で運用する方法を調べてみたら確かにできそうです。

ただ、計算してみるとS3を使っても肝心の費用の方が思ったほど安くはならないかもしれないです。

S3だとファイルを置いておくだけならGitHubより安くなりそうですが、頻繁にクローンしたりしてると割と簡単にGitHubの$5ドルを超えてしまいそうです。

ちょっと気を遣いながら使うことになりそうで、開発しながら余計なことに気を揉むのはいやですよね。

それにS3をLFSに使うとなれば、そのための仕組みも作って運用する必要があるので手間暇を考えると多少安く済む程度ならGitHubにお金を払ってもよいと思います。

こむ太郎
こむ太郎

本来の開発作業に集中したいですよね。

余計なことはなるべく考えたくない。

では、GitHub以外のサービスを使うのはどうかというと、たとえば今お世話になっているBitBucketもGitHubと同じような感じです。

LFSの無料枠はやはり1GBまでで、超過した場合の料金は容量・費用ともにGitHubの倍程度なのでLFSに必要なサイズと他のサービスの充実度でどちらかを選ぶようになるかなと思います。

あと僕はロリポップという安いレンタルサーバーを契約してて、容量があまりまくっているのですが実はGitが使えることを知りました。

灯台下暗しということで使ってみたのですが、ロリポップのGitはLFSに対応していませんでした。

さらに自宅でSynologyのNASを使用していて、こちらもGitを使えることがわかったのですが、やはりLFSが未対応。

自分のNASなので、がんばればLFSもつかえるようにできると思いますが、使い始めてからNASが壊れちゃったりしたら目も当てられないし、それにそなえて外部サービスを使ってバックアップを取ったりしたら、また費用がかさむ。

ということで、いろいろ考えるとGitHubの$5というのは結構いい線だと思えてきました。一食抜けば捻出できる額です。

とりあえず新規のプロジェクトではGitHubでLFSを使ってみて、既存のプロジェクトはとりあえずいまのままBitBucketでLFSなしの運用で様子をみようかなぁという感じです。。

なんか、検討した割にははっきりしない結論になっちゃいましたが、いままでなんとなく使ってきたGitやLFSのことが分かったことと、良いサービスを使うのは金がかかるということを再認識できたので良しとしよう。

コメント

タイトルとURLをコピーしました