Git 大容量ファイル・ストレージ(LFS)

音声ファイルや動画ファイル、画像ファイルなどの大容量ファイルの管理は、Gitの欠点の一つでした。一般的には、パフォーマンスを保つために1GB以上のGitリポジトリは持たないことが推奨されています。

Git LFSクライアントはGitLabサーバーとHTTPSで通信します。クライアントのリクエストを承認するためにHTTPベーシック認証を使います。リクエストが承認された後、Git LFS クライアントは大きなファイルをフェッチする場所やプッシュする場所の指示を受け取ります。

リポジトリビューでは、Git LFSによって追跡されたファイルにはファイル名の横にLFSバッジが表示されます:

Git LFS tracking status

GitLab サーバーを Git LFS 用に設定します。

Git LFSを自分で管理するGitLabサーバーにインストールするには、GitLab Git Large File Storage(LFS) Administrationをご覧ください。

プロジェクトで Git LFS を有効にする

前提条件:

  • プロジェクトで少なくとも開発者ロールを持っている必要があります。

そのためには

  1. 左のサイドバーで「検索」または「移動」を選択してあなたのプロジェクトを検索します。
  2. 設定] > [全般]を選択します。
  3. 可視性、プロジェクト機能、権限セクションを展開します。
  4. Git Large File Storage(LFS)トグルをオンにします。
  5. 変更を保存を選択します。

Git LFS クライアントをローカルにインストールします。

お使いのオペレーションシステムに適したGit LFSクライアントをインストールしてください。GitLabはバージョン1.0.1以降のGit LFSクライアントを必要とします。

既知の制限

  • Git LFS v1 のオリジナル API は、LFS 開発の初期段階で非推奨となったため、サポートされていません。
  • SSH をリモートに設定した場合でも、Git LFS オブジェクトは HTTPS を経由します。
  • Git LFS のリクエストはすべて HTTPS の認証情報を要求するので、Git の認証情報をきちんと保存しておくことを推奨します。
  • Git LFSは常にHTTPSを想定しているので、GitLabサーバーがHTTPの場合は手動でGit設定にURLを追加する必要があります。
  • グループWikiはGit LFSをサポートしていません。

LFS オブジェクトがリポジトリサイズに与える影響

リポジトリにLFSオブジェクトを追加すると、GitLab:

  1. LFS オブジェクトを作成します。
  2. LFS オブジェクトをリポジトリに関連付けます。
  3. ストレージサイズと LFS オブジェクトストレージを含むプロジェクトの統計情報を再計算するジョブをキューに入れます。LFS オブジェクトストレージは、リポジトリに関連付けられたすべての LFS オブジェクトのサイズの合計です。

リポジトリがフォークされると、アップストリームプロジェクトの LFS オブジェクトがフォークに関連付けられます。フォークが作成されると、フォークの LFS オブジェクトストレージはアップストリームプロジェクトが使用するストレージと同じになります。フォークに新しい LFS オブジェクトが追加されると、フォークのオブジェクトストレージの合計は変更されますが、アップストリームプロジェクトは変更されません。

フォークからアップストリームプロジェクトへのマージリクエストを作成すると、フォーク内の新しいLFSオブジェクトはすべてアップストリームプロジェクトに関連付けられます。

Git LFS の使用法

Git LFS を使って Git リポジトリに大きなファイルをチェックするワークフローを見てみましょう。たとえば、とても大きなファイルをアップロードして Git リポジトリにチェックインしたいとしましょう:

git clone git@gitlab.example.com:group/my-sample-project.git
cd my-sample-project
git lfs install                       # initialize the Git LFS project
git lfs track "*.iso"                 # select the file extensions that you want to treat as large files

ファイルの拡張子を LFS オブジェクトとして追跡するようにマークした後は、同じ拡張子のファイルを追跡するコマンドをやり直すことなくいつもどおりに Git を使うことができます:

cp ~/tmp/debian.iso ./                # copy a large file into the current directory
git add .                             # add the large file to the project
git commit -am "Added Debian iso"     # commit the file meta data
git push origin main                # sync the git repo and large file to the GitLab server

.gitattributes が Git によって追跡されていることを確認しましょう。そうしないと、プロジェクトのクローンを作成するときに Git LFS が正しく動作しません:

git add .gitattributes
git commit -am "Added .gitattributes to capture LFS tracking"
git push origin main

リポジトリのクローンは、以前と同じように動作します。Git は LFS で追跡されたファイルを自動的に検出し、HTTP 経由でクローンします。SSH URL でgit clone コマンドを実行した場合は、HTTP 認証のために GitLab 認証情報を入力する必要があります。

git clone git@gitlab.example.com:group/my-sample-project.git

すでにリポジトリをクローンしていて、オリジンからのブランチなどリモートリポジトリにある最新の LFS オブジェクトを取得したい場合は、次のようにします:

git lfs fetch origin main

あなたのファイルが.gitignore にリストされていないことを確認してください。そうしないと、Git によって無視され、リモートリポジトリにプッシュされません。

既存のリポジトリを Git LFS にマイグレーションします。

既存の Git リポジトリを Git LFS にマイグレーションする方法は、こちらのドキュメントを参照ください。

LFS からのオブジェクトの削除

LFSからオブジェクトを削除するには

  1. git filter-repo を使用して、リポジトリからオブジェクトを削除します。
  2. .gitattributes ファイルから削除したオブジェクトに関連する LFS 行を削除し、変更をコミットします。

ファイルのロック

ファイルロックに関するドキュメントを参照してください。

プロジェクト・アーカイブの LFS オブジェクト

GitLab 13.5以前では、プロジェクトソースのダウンロードには実際のオブジェクトの代わりにGit LFSポインタが含まれていました。例えば、LFSポインタは以下のようになります:

version https://git-lfs.github.com/spec/v1
oid sha256:3ea5dd307f195f449f0e08234183b82e92c3d5f4cff11c2a6bb014f9e0de12aa
size 177735

GitLabバージョン13.5以降では、これらのポインタはアップロードされたLFSオブジェクトに変換されます。

この仕組みに関する技術的な詳細は、LFSの開発ドキュメントに記載されています。

トラブルシューティング

n 、ポインタであるはずのファイルがポインタでないことに遭遇。

このエラーは、ファイルが LFS で追跡されるはずなのに、リポジトリが LFS として追跡していないことを示しています。このイシューは、このエラーの潜在的な原因のひとつです:ウェブインタフェースからアップロードしたファイルが LFS で追跡されない

問題を解決するには、該当するファイルをマイグレーションし、リポジトリにプッシュバックしてください:

  1. ファイルを LFS にマイグレーションします:

    git lfs migrate import --yes --no-rewrite "<your-file>"
    
  2. リポジトリにプッシュバックします:

    git push
    
  3. オプションです。.git フォルダをクリーンアップします:

    git reflog expire --expire-unreachable=now --all
    git gc --prune=now
    

エラーが発生しました:リポジトリまたはオブジェクトが見つかりません。

このエラーは、以下のような理由で発生する可能性があります:

  • 特定のLFSオブジェクトにアクセスする権限がありません。

プロジェクトにプッシュする、またはプロジェクトからフェッチする権限があるかどうかを確認してください。

  • プロジェクトが LFS オブジェクトにアクセスできません。

プロジェクトにプッシュしようとしている、またはプロジェクトからフェッチしようとしている LFS オブジェクトが、プロジェクトで利用できなくなっています。オブジェクトがサーバーから削除された可能性があります。

  • ローカル Git リポジトリが非推奨の LFS API を使っています。

<url> のステータスが無効です : 501

Git LFS は、失敗をログファイルに記録します。このログファイルを見るには、プロジェクトディレクトリで

git lfs logs last

ステータスがerror 501 と表示されている場合は、それが原因です:

  • プロジェクトの設定で Git LFS が有効になっていません。プロジェクトの設定を確認して Git LFS を有効にしてください。

  • Git LFSサポートがGitLabサーバーで有効になっていません。Git LFSがサーバー上で有効になっていない理由をGitLab管理者に確認してください。LFSサポートを有効にする方法については、LFS管理ドキュメントを参照してください。

  • Git LFSクライアントのバージョンがGitLabサーバーでサポートされていません。git lfs version で Git LFS のバージョンを確認してください。プロジェクトの Git 設定に非推奨 API のトレースがないか、git lfs -l で確認してください。batch = false が設定されている場合は、その行を削除して Git LFS クライアントのアップデートを試してください。バージョン 1.0.1 以降のみがサポートされています。

getsockopt: connection refused

LFS オブジェクトをプロジェクトにプッシュして、このようなエラーが表示された場合、LFS クライアントは GitLab に HTTPS 経由でアクセスしようとしています。しかし、GitLabインスタンスはHTTPで提供されています:

Post <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused

この動作は、Gitの設定にlfsurl が設定されていない場合、Git LFSがデフォルトでHTTPS接続を使用するために起こります。

これを防ぐには、プロジェクトの Git 設定で LFS URL を設定します:

git config --add lfs.url "http://gitlab.example.com/group/my-sample-project.git/info/lfs"

オブジェクトをプッシュする際には常に認証が必要です。

note
GitLab は 8.12 で SSH に LFS サポートを追加しました。Git LFS 通信は相変わらず HTTP 経由ですが、SSH クライアントは正しい認証情報を Git LFS クライアントに渡すようになりました。ユーザーによるアクションは必要ありません。

Git LFS はオブジェクトをプッシュするたびに HTTP Basic 認証でユーザーを認証するので、ユーザーの HTTPS 認証情報が必要になります。

デフォルトでは、Git は使うリポジトリごとに認証情報を記憶するようになっています。詳しくはGit の公式ドキュメントを参照ください。

たとえば、Git にオブジェクトをプッシュする期間を指定してパスワードを記憶させることができます:

git config --global credential.helper 'cache --timeout=3600'

これは認証情報を一時間記憶し、その後 Git のオペレーションには再認証が必要になります。

OS X を使っている場合は、osxkeychain を使って認証情報を保存・暗号化することができます。Windows の場合は、wincred あるいは Microsoft のGit Credential Manager for Windows を使います。

ユーザー認証情報を保存するさまざまな方法の詳細については、Git Credential Storage ドキュメントを参照ください。

プッシュ時に LFS オブジェクトが見つからない

GitLabはプッシュ時にLFSポインタを検出するためにファイルをチェックします。LFSポインタが検出された場合、GitLabはそれらのファイルが既にGitLab上のLFSに存在するかどうかを確認しようとします。

LFSがローカルにインストールされていることを確認し、git lfs push --all を使って手動プッシュを検討してください。

GitLab の外部に LFS ファイルを保存している場合は、projects APIlfs_enabled: false を設定することで、プロジェクトの LFS を無効にすることができます。

LFS オブジェクトを外部でホスト

git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs でカスタム LFS URL を設定することで、LFS オブジェクトを内部でホストすることができます。

Nexus リポジトリのようなアプライアンスを使用して LFS データを保存している場合、この方法を選択することができます。外部のLFSストアを使うことにした場合、GitLabはLFSオブジェクトを検証できません。GitLab LFSサポートを有効にしている場合、プッシュは失敗します。

プッシュの失敗を止めるために、プロジェクト設定でLFSサポートを無効にすることができます。これはGitLab LFSバリューアド(Verifying LFS objects, UI integration for LFS)も無効にします。