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

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

Git LFS tracking status

LFS アイコンは、ファイルが blob として保存されているか LFS ポインターとして保存されているかを示すために、Git LFS によって追跡されるファイルに表示されます。

どのように動作するか

Git LFSクライアントはGitLabサーバーとHTTPSで通信します。 HTTPベーシック認証を使ってクライアントのリクエストを承認します。 リクエストが承認されると、Git LFSクライアントはラージファイルのフェッチ先やプッシュ先の指示を受け取ります。

GitLab サーバーの設定

GitLab インスタンス管理者向けのドキュメントはLFS administration docにあります。

要件

  • Git LFSはバージョン8.2からGitLabでサポートされています。
  • プロジェクトの設定で git LFS を有効にする必要があります。
  • gitLFS クライアントバージョン 1.0.1 以上

既知の制限

  • Git LFS v1 のオリジナル API は、LFS 開発の初期に非推奨となったため、サポートされていません。
  • SSH がリモートとして設定されている場合でも、Git LFS オブジェクトは HTTPS を経由します。
  • Git LFS リクエストはすべて HTTPS 認証情報の提供を要求するので、Git 認証情報をきちんと保存しておくことを推奨します。
  • Git LFSは常にHTTPSを想定しているため、GitLabサーバーがHTTPの場合は手動でGitの設定にURLを追加する必要があります(トラブルシューティングを参照)。
注:GitLabは8.12でSSHにLFSのサポートを追加しました。 Git LFSの通信は依然としてHTTPで行われますが、SSHクライアントが正しい認証情報をGit LFSクライアントに渡すようになったので、ユーザーがアクションを起こす必要はありません。

git LFS の使い方

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

git clone git@gitlab.example.com:group/project.git
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 master                # sync the git repo and large file to the GitLab server

.gitattributes が Git で追跡されていることを確認してください。そうでないと、プロジェクトのクローンを作成するときに Git LFS が正しく機能しなくなります:

git add .gitattributes

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

git clone git@gitlab.example.com:group/project.git

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

git lfs fetch origin master

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

既存リポジトリの Git LFS への移行

Git LFS を使って既存の Git リポジトリを移行する方法については、こちらのドキュメントをご覧ください。

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

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

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

ファイルロック

GitLab 10.5 で導入されました

ファイルロックを使う前に最初にすべきことは、Git LFSにロック可能なファイルの種類を教えることです。 次のコマンドはPNGファイルをLFSに保存し、ロック可能なフラグを立てます:

git lfs track "*.png" --lockable

上記のコマンドを実行すると、.gitattributes という名前のファイルが以下の内容で作成または更新されます:

*.png filter=lfs diff=lfs merge=lfs -text lockable

LFSを使用せずにファイルタイプをロック可能として登録することもできます(ファイルをロック/アンロックするには、LFS File Locking APIを実装したリモートサーバーが必要です)。その場合は、.gitattributes ファイルを手動で編集してください:

*.pdf lockable

ファイルタイプがロック可能なものとして登録されると、git LFSはファイルシステム上でそれらを自動的に読み取り専用にします。 つまり、ファイルを編集する前にロックする必要があります。

ロックされたファイルの管理

ファイルを編集する準備ができたら、まずロックする必要があります:

git lfs lock images/banner.png
Locked images/banner.png

これにより、あなたの名前でロックされたファイルがサーバーに登録されます:

git lfs locks
images/banner.png  joe   ID:123

変更をプッシュしたら、他の人も編集できるように、ファイルのロックを解除することができます:

git lfs unlock images/banner.png

IDによるロック解除も可能です:

git lfs unlock --id=123

何らかの理由で、自分がロックしていないファイルのロックを解除する必要がある場合、プロジェクトにmaintainer アクセス権がある限り、--force フラグを使用できます:

git lfs unlock --id=123 --force

トラブルシューティング

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

このエラーが発生する理由はいくつかあります:

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

getsockopt: 接続が拒否されました

LFS オブジェクトをプロジェクトにプッシュしたときにPost <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refusedのようなエラーが表示された場合、LFS クライアントは GitLab に HTTPS でアクセスしようとしています。 しかし、GitLab インスタンスは HTTP で提供されています。

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

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

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

オブジェクトをプッシュする際には、常にクレデンシャルが必要です。

注:GitLabは8.12でSSHにLFSのサポートを追加しました。 Git LFSの通信は依然としてHTTPで行われますが、SSHクライアントが正しい認証情報をGit LFSクライアントに渡すようになったので、ユーザーがアクションを起こす必要はありません。

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

デフォルトでは、Git は使用するリポジトリごとに認証情報を記憶するようになっています。 これは、Git の認証情報の manページで説明されています。

例えば、オブジェクトをプッシュする期間だけパスワードを記憶するようにgitに指示することができます:

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

この認証情報は一時間保存され、その後gitオペレーションを行う際には再認証が必要になります。

OS X を使っている場合は、osxkeychain を使ってクレデンシャルを保存・暗号化することができます。Windows の場合は、wincred あるいは Microsoft のGit Credential Manager forWindows を使うことができます。

ユーザークレデンシャルを保存するさまざまな方法の詳細については、Git Credential Storage ドキュメントを参照ください。

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

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

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

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

LFSオブジェクトの外部ホスト

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

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

プッシュの失敗を止めるために、プロジェクト設定でLFSサポートを無効にすることができます。 これはGitLab LFSの付加価値(LFSオブジェクトの検証、LFSのためのUIインテグレーション)を失うことを意味します。