Bitbucket の Git LFS でバイナリファイルをバージョン管理する
2020年10月12日(2023年10月06日 更新)
こんにちは。これを読んでいる方の中には、設計書などのドキュメントをExcelファイルで作成していたり、成果物と呼ぶファイルをソースコードと一緒にバージョン管理をしている(したい)方がいらっしゃるかと思います。このブログでは、そのようなお客様からよく質問される Git LFS についてご紹介します。
Git で バイナリファイル や 大容量のファイル を取り扱うときに困る事
Bitbucket のお問合せも増えてきて、改めて Git の導入を検討しているユーザーが増えてきているなと実感しています。それと同時に様々なご相談を頂くことも増えました。その中でも特に頂くご相談の一つに「Gitで成果物も管理してトレーサビリティを向上させたい。」というご要望があります。
ここで言う成果物とは「Excelなどで作成した設計書などのドキュメント」「VisioやCADといった作図ツールで出力した図面ファイル」あるいは「画像や音声、そして動画ファイル」といった、いわゆる「バイナリファイル」を指します。
ソースコードファイルのように文字を扱う「テキストファイル」と異なる性質を持つ「バイナリファイル」を Gitでバージョン管理すると、バイナリファイル特有の問題が起こります。代表的なものとして次の2つを挙げます。
ファイルサイズが大きいため、Gitリポジトリの転送に時間が掛かってしまう
Gitリポジトリはファイルの種類だけでなく、ファイルごとの過去のバージョンも履歴として全て保管されています。そのGitリポジトリをクローンするには時間が掛かることはもちろん、タイムアウトによってクローン出来ないこともあります。
更にクローンした後は、個々の端末(PC)にバイナリファイルの全ての履歴データも作られますので、端末のディスク容量を不必要に占有してしまうという副作用もあります。
ファイル内の差分マージができないため、ファイル全体を上書きすることになる
テキストファイルであれば、変更前後の文字列を比較してマージすることができます。ですがバイナリデータは変更点をピンポイントで検出できませんので差分比較 は出来ず、マージも ファイルの上書き更新 となります。
これは Gitに限ったことではありませんが、Subversion だと、複数人が同時に編集してコミットすることを防ぐ ファイルの編集ロックという機能があります。ですが 分散型リポジトリで 同じファイルを個々の端末が複製して持っている Gitでは 同様の機能は持っておりません。
Git LFS (Large File Storage) とは
Git LFS はGitの拡張機能です。Gitは動画など、1GBを超えるようなサイズの大きいファイルの管理には向いていません。Git LFSは、 Large File Storage (大容量ファイル倉庫)という言葉の通り、大容量ファイルを Git のリポジトリではなく専用のストレージで保管することができます。
Git LFS の仕組み
1.ユーザーがファイルを作成し、ローカルのGitリポジトリに追加 (`git add`) してバージョン管理対象にすると、Git LFSはそのファイルを専用ディレクトリ(以下、LFS)でキャッシュします。
またローカルのGitリポジトリではファイルの代わりに、LFSにキャッシュされたファイルの場所を示す ポインタファイルを追加します。
2.ローカルGitリポジトリをリモートにプッシュ (`git push`) すると、まずLFSで保管するファイルが リモートのLFSにアップロードします。その後 リモートGitリポジトリがプッシュされますがこのリポジトリには実際のファイルは含まずポイントファイルに置き換わっています。
これを積み重ねることでリモートサーバーのLFSに対象ファイルが全て履歴管理されます。
3.ローカルのGitリポジトリで あるブランチをチェックアウト (`git checkout `) して展開するときに、そのブランチにあるポインタファイルを参照して、ローカルのLFSにあるキャッシュを探して実体のファイルに置き換えます。
該当ファイルのキャッシュが ローカルのLFSに無い場合、リモートサーバーのLFSからダウンロードしてキャッシュします。
このGit LFS の仕組みをまとめると次のようになります。
- Git LFS で管理するファイルは、Git リポジトリから隔離される。
- Gitリポジトリでは実際のファイルの代わりに、Git LFS 上のファイルの在処を示すポインタファイルを管理する。
- ローカルには必要最低限のファイルだけが存在する。
Git LFS によって解決できること
冒頭に上げたバイナリファイルや大容量ファイルを Git でバージョン管理したときに困ることの解決策の一つとして利用できます。
ローカルのGitリポジトリ のサイズを最適化する
Gitリポジトリに バイナリや大容量のファイルが含まれないのでクローンに時間が掛からなくなります。
更には、端末上に不必要なファイルまでコピーされなくなります。
ファイルの編集ロックが実現できる
Git LFS には ファイルロック機能があります。これはローカルリポジトリの対象ファイルを強制的に "読み取り専用" にし、ファイルのロックを取得した一人のユーザーだけに編集を許可する機能です。
このファイルロック機能はまだ先行リリースという位置づけであり、Subversion のロック機能とは仕組みや使い方が異なることに注意が必要です。
ですが 正しく運用することで同時編集によるコンフリクト(ファイルの上書き)を防ぐことが出来ます。
Bitbucket Server で Git LFS を利用する方法
Atlassianの Gitホスティングツール 「Bitbucket」は Git LFS に対応しています。 ここからは オンプレミス版の「Bitbucket Server」を使って、Git LFSの導入方法と使い方をご案内します。
その前に 2点ほど 注意事項を記載します。
- Bitbucket Cloud は、LFSに標準対応していますが、ファイルの編集ロックは未対応です。(2022年7月時点)
- Gitのクライアントツール SourceTree は LFSの操作は行えますが、ファイルの編集ロック操作には未対応です。(2022年7月時点)
そのため編集ロックを行う場合は、コマンドプロンプトやターミナルなどから コマンドで実行してください。
Git LFS を設定する
Git LFS を利用するには、リモート/ローカル の全ての環境で Git LFSをインストールする必要があります。 Bitbucket ではデフォルトで Git LFSがインストール済みですのでリモート側は別途インストールが不要です。
Git LFS をインストールする
Git LFS がインストールされているか確認する
インストール済みのGit に、Git LFSがプリインストールされている場合がありますので、まずは以下のコマンドを実行してバージョンが表示されるかを確認してください。
バージョンが表示されればインストール済みですので、別途インストールしなくてもお使い頂けます。
$ git lfs versiongit-lfs/2.12.0 (GitHub; windows amd64; go 1.14.7; git dad7b9e6) |
Git LFS をダウンロードしてインストールする
インストールされていなければ、公式サイト や GitHubのページ を参考にインストールします。
尚、最新のGit LFSをインストールしたのに、 `git lfs version` で最新バージョンにならない場合、Git にプリインストールされている Git LFSが起動していると考えられます。この場合は Gitが参照しているパスを変えたり、参照先の実行ファイルを最新版に置き換えるなどを行ってみてください。
Git リポジトリで Git LFS を有効にする
Bitbucket (リモート)で 作成したリポジトリの場合
リポジトリ設定 > リポジトリ詳細 ページの ラージファイルストレージ (LFS) から、 LFSを許可する をチェックし保存します。
LFSを許可する がチェックできなければ、Bitbucket の管理者ユーザーでアクセスし、管理 > サーバー設定 ページの ラージファイルストレージ (LFS) で、 LFSを許可する がチェックされているかを確認してください。
ローカル側で作成したリポジトリの場合
リポジトリのルートディレクトリに移動し、以下のコマンドを実行します。
git lfs install |
Source Tree を利用している場合は、Repositry > Git LFS > Initialize Repository からでも有効にできます。
以上で、Git リポジトリでGit LFS が利用できるようになりました。この後のファイルの登録やロックなどは ローカルリポジトリでの操作となります。
Git LFS でバイナリファイルを管理する
LFSで管理するファイルを登録する
Git LFS でファイルを管理することを トラッキング と呼びます。ファイルのトラッキングを開始するには 次のコマンドを実行してください。
トラッキングするファイルは、特定のファイル名(ファイルパス)だけではなく、 '*.xlsx' や '*.dat' のように特定の拡張子を持つ全てのファイルを指定することができます。
git lfs track '<トラッキングするファイル>' |
トラッキングを行うと、.gitattributes というファイルが作成されます。この ファイルにトラッキングしているファイルの情報が書き込まれ、LFSはこの内容を基にファイルを管理しますんので .gitattributes ファイルもGitリポジトリで管理します。
トラッキングしたファイルは、`git add` を実行してGitの管理対象としたタイミングで、GitリポジトリからLFSに移動し、ポインタファイルに置き換わります。
以降は 従来通りのGitの操作 (`git commit`, `git push` など) を実行だけで、Git LFS が処理を行います。
他のユーザーも従来の操作で、ローカルリポジトリを更新やブランチをチェックアウトすると トラッキングしているファイルを Git LFSが "いい感じに" 処理してくれます。
Bitbucket ではトラッキングしているファイルを閲覧すると Git LFS で管理していることが分かります。
Git LFS のファイルロック機能を使う
はじめに
Git LFS のファイルロック機能はSubverionの同機能と比べて、運用ルールに依存する点が多く、ユーザーがそのルールを破ると簡単に同時編集してコンフリクトが発生します。Git LFS のファイルロック機能を利用する時は "運用ルール"を決め、プロジェクトメンバー全員に"周知" して使うようにしてください。
編集ロックを行うファイルを指定する
まず初めに「編集を制限するファイル」を指定します。これには 前述の track コマンドを使います。
git lfs track --lockable '<編集を制限するファイル>' |
--lockable オプションを付けて トラッキングすると、.gtiattributes では "lockable" が付与されます。この状態で Gitリポジトリをコミット・プッシュし、各ユーザーがローカルでマージすると lockable 対象のファイルの属性 "読み取り専用" がオンになります。
"読み取り専用" となることで、ユーザーが編集しようとファイルを開いても保存ができなくなります。
ちなみに この「編集を制限するファイル」ですが、LFSでトラッキングしているファイルだけでなく、Gitリポジトリで管理しているファイルにも適用できます。その場合は .gitattributes ファイルを以下のように直接編集してください。
(※lfsに関する定義は書かずに、ファイル と lockable オプションだけ指定します。)
<編集を制限するファイル> lockable |
ファイルのロックを取得する
"読み取り専用" のファイルを編集するためには、ファイルのロックを取得します。ファイルのロックを取得するには次のコマンドを実行します。
git lfs lock '<ロックを取得するファイル>' |
ロックを取得すると、そのユーザーのローカル環境のファイルのみ "読み取り専用" が外れて編集することができます。
ロックの取得は同時に1ユーザーに限定されるので、他のユーザーがロックを取得しているファイルに対して、ロックを取得しようとコマンドを実行してもエラーとなります。
ファイルの編集が完了し、リモートにプッシュしたら次のコマンドを実行してロックの取得を開放してください。
git lfs unlock '<ロックを取得していたファイル>' |
運用する時に注意すること
一連のファイルロックの中でイレギュラーな操作を行うとロックの状態に不整合が起こり、ファイルの同時編集およびファイルの更新が出来てしまいます。これらの操作は実施しないようにしてください。
(注: ここに書いたことは、ブログの執筆時点(2020年10月)のバージョンで確認しています。以降のバージョンアップでは再現しない場合があります。)
- ファイルの"読み取り専用" 属性を 直接解除する。
→ ロックの取得状態に関係なく、編集が出来てしまいます。 - ロックを取得していないのに、対象ファイルを編集し、リモートにプッシュする。
→ ロックの取得状態に関係なく、リモートにファイルがプッシュできます。(警告メッセージは出力しますが、アップロード自体は行われてしまいます。) - Bitbucket の画面上にある 「ロック (ロック解除)ボタン」を押す。
→ ローカル側のロック状態が更新されないため、ロックの取得状況に不整合が発生します。
Gitリポジトリで管理していたファイルを途中からGit LFS で管理する
既にバイナリファイルをバージョン管理していて後から Git LFS を導入して LFSで管理したいことがあると思います。
この場合、トラッキングを実行したタイミングでファイルをLFSによる管理に切り替えることが出来ます。ですが、トラッキングする前に Gitで管理していた過去のバージョンのファイルは LFSでは管理されません。
過去のファイルも含めて LFSで管理するためには 次のような操作を行ってください。
- `git lfs migrate` コマンドを使って過去の履歴に遡ってLFSに置き換える。更に Git リポジトリで管理していたコミット履歴を削除するなどの 履歴の改変操作を行う。
- Git LFS を有効にしたGit リポジトリを新たに作り、そのリポジトリに移管する。
前者は特に過去の履歴を改変することになるので、整合性はもちろん 既に多くの履歴情報を持っているリポジトリでは現実的では無いと思いますので、可能であれば後者をお薦めします。
Git LFS を利用する前にご検討頂きたいこと
Git の拡張機能であるGit LFS によって、ソースコードと一緒に バイナリファイルなどの大容量ファイルのバージョン管理を扱いやすくはなりました。ですがこれで、全てのファイルをGit で管理した方が良いと 一概に言えるわけではありません。ファイルの整合性やインテグリティと言った点を重要視する場合は Git以外の選択の方が良いと考えます。
一方で、バージョン管理システムにおいて Git が隆盛を極める中で「Gitを使って、様々なプロジェクトの成果物も一元管理したい。」という要望が挙がることも理解できます。それほどGit には魅力があり、Bitbucket や GitHubといったGitのサービスやサポートが充実していて、多くのシステムとの親和性があることも間違いありません。
他のツールと同じくバージョン管理においても、管理するファイルや成果物の性質だけでなく、要求や運用ルールなどの業務全体で最適となる方法を考えていかなければなりません。どんな組織にも通用できる方法などは無く、Git そして Git LFS もその選択肢の一つに過ぎません。
これを検討することはとても難しいと思います。弊社も Bitbucket + Git LFS といった手段ありきではなく、お客様の問題を解決するためのより良い提案を行うことを心掛けてまりますので、お困りの際にはご相談ください。
あわせて読みたい!
★チームでの情報共有にはツールの導入がおすすめ!定着するツールの選び方を解説
★業務の属人化とは?懸念されるリスクや属人化の解消・防止方法を解説
この記事を読んだ⼈におすすめのページ
-

Bitbucket Code Insights は、コードレビューの質とスピードに貢献します
-

GitとSubversionの構造的な違い|GitのブランチはSubversionのブランチとは全く違うモノ
-

「Jiraに自動化機能(Jira Automation)が搭載! ロードマップほかJira新機能をお知らせ!2022年夏」
-

【Jiraの自動化やってみた】期限切れの課題を見つけて課題から直接 Slack で担当者に喝を入れる
-

Jira(クラウド版)のワークフローをテンプレからカスタマイズしてみた
-
「Jiraの使い方がわからない」そんなあなたに。リニューアルした「eラーニング Jira入門コース」(日本語)をお知らせします
本情報はブログを公開した時点の情報となります。
Software Collection
Jira Service Management
Customer Service Management
Assets
Rovo
Focus
Jira Align
Talent

2026年春、ベトナムで感じた「AI熱」とBiplusの本気度 ――ベトナムITイベントレポ
5,000名以上のエンタープライズで Jira / Confluenceを選ぶ理由 ― 情報ガバナンスとセキュリティを両立する Atlassian Guard活用術
モダン開発の落とし穴『認知負荷』の正体――。複雑なエンジニアリング環境を救うIDP (Compass)の価値を一般家庭に例える
SFA・Excel・データ整形の限界を突破!Workatoで予実管理を自動化する方法|月末の「あの作業」がなくなる