Git はソースコードの管理ツールのため、巨大なバイナリファイルの扱いが苦手でした。これに対応すべく開発されたのが LFS: Large file storage という機能です。
今回はこれをインストール&触ってみたいと思います。なお環境はすでに git for windows がインストールされた環境で行っています。
ちなみにこの記事の内容は Git for windows 2.7.2, git-lfs 1.1.1 を用いての内容となってます。バージョンが異なる場合、以下の内容とは変更になっている可能性があるのでご注意ください。
GIT LFSについて
扱いとしては git のエクステンションという形になってます。
提供する機能は、指定されたファイルタイプの場合に特殊な処理を行うようになります。
この処理というのが、バイナリファイルを指し示すリンクをソースコードの場合と同じように保持するようにして、バイナリファイル自体はそのリポジトリとは別の場所に管理させる、というようなものです。
このLFSですが、前身になるようなものとして、git-media, git-fat などがありました。これらを使用していた人は同じようなものだと考えてもらってよいと思います。
LFSのメリットはすでにGitHub や、ほかのホスティングサービスも対応を始めているため、バイナリファイルの扱いに対して準標準を得られるのでは、というところもあるかと思います。
git lfs のインストール
https://git-lfs.github.com/ からインストーラーをダウンロードします。
この記事を書いているときには、 git-lfs-windows-1.1.1.exe でした。
このインストーラーをダブルクリックで起動してインストールを行っていきます。
インストールする場所ですが、 Git for windows をインストールしたフォルダで、
mingw64/bin 以下になるようにします。以下の図では標準の場所を指していますが、Git for Windows を別の場所にインストールしている場合ではここを修正する必要があります。
(現時点ではすでにインストールされているgit のインストールパスは探索されない模様)
インストールが終わって Git Bash を開き、以下のコマンドを実行します。
$ git lfs install Git LFS initialized. $ git lfs version git-lfs/1.1.1 (GitHub; windows amd64; go 1.5.3; git 69d1419)
このように表示されればOKです。 git lfs init というコマンドもあったようですが、廃止扱いになっており、今は git lfs install が正しいようです。
動作を確認してみる
まずは適当な git リポジトリを用意して、動作を確認していきたいと思います。
$ mkdir -p /c/repos/mycheck $ cd /c/repos/mycheck $ git init Initialized empty Git repository in C:/repos/mycheck/.git/
Git lfs では LFS として管理させるファイルタイプを選択、設定します。
ここでは、よく使う画像ファイルを登録したいと思います。
この登録は以下のようなコマンドによって行います。
$ git lfs track "*.dds" $ git lfs track "*.png" $ git lfs track "*.jpg" $ git lfs track "*.psd"
これらの情報は .gitattributes に格納されます。上記の実行結果で以下のようになっていました。
*.dds filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text *.psd filter=lfs diff=lfs merge=lfs -text
この .gitattributes ファイルを開かずとも、 git lfs track コマンドで確認することもできます。
$ git lfs track Listing tracked paths *.dds (.gitattributes) *.png (.gitattributes) *.jpg (.gitattributes) *.psd (.gitattributes)
さて登録したタイプにあうような適当なファイルをコミットしてみます。
ここでは png のファイルを追加・コミットしてみます。
以下のように行いましたが、これは通常の git のファイル追加・コミットと変わらないです。
$ git add .gitattributes $ git add test.png $ git commit -m 'initial commit'
これが LFS の管理になっているかどうかを確認するのに以下のコマンドを実行します。
$ git lfs ls-files 42c7abc4d3 * test.png
正常に機能していれば上記のように、ファイル名とその何らかのハッシュ値が表示されます。
リモートリポジトリとのアクセス
ローカルでの機能確認ができたら、リモートとのアクセスを試してみたいと思います。
現時点では GitHub は、 1GB までは無料でLFSが使えるようなのでこちらを利用したいと思います。
GitHub で新規のリポジトリを作成し、そのリポジトリをリモートするように今回のリポジトリを設定しておきます。
$ git remote add (作成したリモートのURL)
そして普通に git push origin master を実行してみます。
$ git push origin master Git LFS: (0 of 1 files) 0 B / 11.80 KB Git LFS: (0 of 1 files) 0 B / 11.80 KB Git LFS: (0 of 1 files) 0 B / 11.80 KB Git LFS: (0 of 1 files) 0 B / 11.80 KB Counting objects: 3, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 318 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0)
というように普通に成功しました。
(ほかの設定も必要なのではと思っていましたので意外でした)
さて、正常にあがったところでこのリポジトリを別の場所で clone してみたいと思います。新規に取得してみることが目的なので、別PCでやってもかまいません。
$ git clone (作成したリモートURL)
内部的には追加したバイナリファイルは単なるテキストファイルに変わっています。
しかし、clone,pull などのコマンド実行の際には、LFSがうまく実行され、バイナリファイルが復元されます。
Downloading test.png (11.80 KB)
などと表示されている行がまさにバイナリファイルを取得している状態を示しています。
まとめ・感想など
準公式での巨大バイナリデータに対する対策が入ったことは大きいと思います。
最低限の LFS の動作を確認してきましたが、Git をコマンドで扱っている人にとってはすでに実用になるかなと思います。
tortoisegitとの組み合わせについて
1.8.16.0 のバージョンを使っている場合での話になりますが、ちょっとまずい点がありそうです。
「 TortoiseGit commit with git-lfs files, show me a error: “.git/index.lock” file exist」
というエラーがあるようで、これが 1.8.16.4 かそれ以降のバージョンで修正されるようです。
バイナリ状態がちょっと怪しい挙動
バイナリファイルを含むリポジトリを clone した際にバイナリファイルが復元されないケースがありました。このときファイルを試しにテキストエディタで開いたら以下のようになっていました。
version https://git-lfs.github.com/spec/v1 oid sha256:42c7abc4d351dd990f5cd087d08fcac7ca15472fb5e80c9d6f505faad46eaa98 size 12084
このときバイナリデータの復元はどうするかというと、以下のコマンドによって復元(再取得)が行えます。
$ git lfs pull Git LFS: (0 of 1 files) 0 B / 11.80 KB Git LFS: (0 of 1 files) 0 B / 11.80 KB Git LFS: (0 of 1 files) 0 B / 11.80 KB Git LFS: (1 of 1 files) 0 B / 11.80 KB
これによりデータが元のバイナリデータとして復元されます。
このような状態に陥っているときには、バイナリファイル復元した状態がすでに変更状態と見なされてしまうようで、最低限のデータ取り出しを行ったら、新規にリポジトリを作成・取得し直しといったことを行った方がよさそうでした。
対応プロトコルについて
Git LFSは大容量ファイルに対するサブのリポジトリを作ってそこにデータを放り込みます。このときの通信は http となるようで、前身の git-media のほうが対応種類が多くて状況によって適切に使い分けができた気がします。LFSもまた対応が広がってくれるとうれしいのですが。
LFSによる前提の崩壊?
従来からの使用者の感覚としては、ソースコードと大容量ファイル、それぞれ別管理という印象が強いですが、この機能が標準になってさえしまえば、これらをまとめた単位がリモートのリポジトリという1つのまとまりという認識に変わりそうです。
1つ気になった点としては、LFSリポジトリ(別の置き場を今はこう呼んでおきます)ができて、ここから必要なデータだけを復元するやり方によって、
開発者全員が全てのリポジトリデータのクローンを持つわけではなくなったと考えられます。
そのため、少々強引な表現ではありましたが「分散リポジトリだから開発者全員が同じリポジトリデータを持つ」は崩れてしまった前提になるのではないかなと感じます。
(そもそも公開されていないブランチもあるでしょうから、全員が同じリポジトリデータを持つわけではなく、単に公開されているものにおいては同じ、くらいなのですが)
LFSリポジトリデータ自体のクローンは行われないわけなので、ここにたまっているデータをきちんとバックアップしてあげる仕組みがないとトラブル時にバイナリを失ってしまうということになるのではと心配が残ります。
試しに適当な場所にリポジトリをcloneした後で、リモートリポジトリを削除し、ブランチの移動やら任意コミットへのcheckout を実行したところ、バイナリファイルの復元に失敗してしまうようでした。
コメント
[…] トURL : https://blog.techlab-xe.net/archives/4390 […]
[…] Git LFS を使ってみる | すらりん日記 […]