2022/10/15

[git] LFS を使ってみたい。できれば Google Drive で。

GitHub で Android のプロジェクトを管理していたのだが、その中に他で作った AAR ファイルも管理していた。
頻繁に変わるからバージョン管理が面倒になって追加していたのだが、git clone するときにかなり負担になってしまうことに今さら気づいた。遅くなるだけならまだしも、時間がかかりすぎるためか切断されて失敗することすらあるのだった。

git にバイナリファイルを別扱いにするしくみがあったような気がする、ということで調査し始めた。
別の場所に置くとしてもそんなに候補がないので、できれば Google Drive に置いておきたい。そしてプライベートリポジトリでもできるようにしたいし、Github Actions でビルドするときに使えるようになっていてほしい。

要望が多いね。


まずはここか。

About large files on GitHub - GitHub Docs
https://docs.github.com/ja/repositories/working-with-files/managing-large-files/about-large-files-on-github

LFS というしくみは GitHub が進めていたようだった。
とりあえず、書いてあるとおりにやってみる。

https://github.com/hirokuma/lfstest/blob/c0a6e955f949a213101aa78bf6fe3a4522ae1bc6/app-debug.apk

image

LFS 領域?に置かれたようだ。
Settings からもそうなっている。

image

Windows からできたので他の環境でもたぶんできるだろう。


これだと GitHub の LFS を使うようになっている。
無料で使うには容量に制限があるので、これを Google Drive に置きたいというわけだ。 Free版だと 2GB までなので Google Drive の無料版と変わらんのだが、お仕事では Google Workspace を使っているのでまだ余裕がある。

GitHub を使ってるのなら GitHub の LFS しか使えないのでは?と思ったが、説明には Dropbox や Google Drive も書いてあるので、きっとできるのだろう。

Git Large File Storage でのコラボレーション - GitHub Docs
https://docs.github.com/ja/repositories/working-with-files/managing-large-files/collaboration-with-git-large-file-storage

.gitconfig に lfs.url を設定すると、そこに対して LFS API でうまいこと push なり pull なりしてくれるらしい。

Git LFSの使用方法 – Backlog ヘルプセンター
https://support-ja.backlog.com/hc/ja/articles/360038329474-Git-LFS%E3%81%AE%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95#LFS%E3%81%AE%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E3%81%84%E6%96%B9

こちらを使うと Dropbox や Google Drive をインストールしている環境でローカルのフォルダと同期するようであればプラグインのようなものを使うことで同じようなことをしてくれるのだと思う。

sinbad/lfs-folderstore: git-lfs custom transfer adapter which simply uses a folder as the remote LFS media store (e.g. a shared NAS folder)
https://github.com/sinbad/lfs-folderstore

これはこれで使えそうなのでやっておく。
既存のリポジトリを使う場合は面倒そうなので新規でやった。

https://github.com/hirokuma/lfsdrive2/blob/fee886e081b7c1cd867a4db81d00fbde0f106439/app-debug.apk

ポインタファイルになっていた。Settings を見ても Git LFS Data はそのままだ。
このテストでは Google Drive をローカルドライブでマッピングしているフォルダを指定したのだが、そこにはフォルダがいくつか作られ、oid sha256 に書いてあるハッシュ値と同じファイル名で同じサイズのファイルが置かれていた。「G:\マイドライブ\lfstest」みたいなフォルダ名だったが問題ないようだ。

この方式はローカルで作業する分には問題ないと思う。チームで作業するときも同じ Google Drive などのフォルダにアクセスできるなら各人に git config で設定してもらえばよいだけだろう。
もちろん、GitHub Actions でダウンロードなどはできない。がんばればできるのかもしれんが、Google Drive へのアクセスを許したりダウンロードさせたり しないといけないだろうからほぼ無理だと思う。それくらいだったら直接 Google Drive からダウンロードする方が楽だ。


そうだ、直接ダウンロードすれば良いのだ。

私が期待したのは git でバイナリファイルそのものの履歴管理はしなくてよいが、それを別のところからダウンロードするしくみがあって、そのダウンロード先については履歴管理してほしい、というわがままなものだ。
そういうことをしたかったら API を使って curl でアクセスするようなものの方がやりやすいと思う。ダウンロードするだけしかしないのだったら Git のフック機能を使って clone やら checkout やらのタイミングでダウンロードすればよいのではなかろうか。

Google Drive上の公開されたファイルをダウンロードする - Qiita
https://qiita.com/tanaike/items/f609a29ccb8d764d74b3

なんでもかんでもダウンロードするのもなんだから、ファイルがなければダウンロード、あってもハッシュ値か何かが不一致ならダウンロード、みたいなのを仕込むことになるだろう。

ただ・・・Windows と Linux, Mac とではスクリプトが共通化できなさそうだ。 curl は Windows10 でも使えるようになったが sha256sum はないし、あったとしても戻り値を比較するのは文法が違いそうだ。それなら Git for Windows をインストールしたときに使える bash.exe を使って Linux系のスクリプトで共通化させるのがよさそうだ。

 

git hook はリポジトリに埋め込むことができないのかな。。。
それだったらダウンロードするようなスクリプトを一緒に commit しておいて、 clone なり pull なりした後は実行してね、でよいかもしれん。忘れそうだけど。

https://github.com/hirokuma/lfsdrive3

これは、main ブランチで README の commit までやったあと、another-apk というブランチで app-debug.apk を差し替えてプルリクしてマージされ、そのあと git pull で mainブランチを更新する、というシナリオだった。

image

git pull は fetch と merge をまとめたコマンドだから、post-merge にも同じように仕込まないといけない。

image

こちらは git pull でダウンロードが行われた。

もうちょっと格好良くできそうな感じもするのだが、まあこのくらいできればよいかな。