Git-LFSのファイルをいっこだけ手動DLする
いやこれみんなどうやってんの。。無いと絶対困ると思うんだけど。。
今回はこういう感じに写真のバックアップをGit-LFSなGitリポジトリに取っている。このGit-LFSに格納した写真のメタデータを完全なチェックアウトなしで抽出していきたい。
手順
とりあえず、
git clone --no-checkout <REPOSITORY-URL>
- (LFSサーバに別途認証が必要な場合は、ここで認証する)
git cat-file --filters HEAD:sync/DCIM/Camera/PXL_20220331_052024030.jpg | git lfs smudge > temp.jpg
とすることで抽出はできる。もうちょっと簡単なコマンドが有るかもしれない。
cat-file --filters
通常のチェックアウトがある場合は、 git cat-file --filters
によって直接ファイルを抽出できる。が、これは Git のsmudgeフィルタが裏で自動起動する必要があり、そのためには正当な内容のindexを持つ = チェックアウト自体は済んでいる 必要があるため、今回の目的には使えない。
チェックアウトの無い状態で cat-file --filters
を行うと、Git-LFSのポインタファイルを取り出せる。
$ git cat-file --filters HEAD:sync/DCIM/Camera/PXL_20220331_052024030.jpg
version https://git-lfs.github.com/spec/v1
oid sha256:732a758621cc15b0fc990437170b06386af1879640e5a4a38457419a7e67f067
size 3955210
このファイルを手動で Git-LFS のsmudgeフィルタに投入することで元のファイルを得られる。
bareリポジトリはダメ
上記の手順を bare リポジトリ(git clone --mirror
等で作ったリポジトリ)に対して実行すると、 git-lfs
コマンドがクラッシュしてしまう。
$ git cat-file --filters HEAD:sync/DCIM/Camera/PXL_20220331_052024030.jpg | git lfs smudge > temp.jpg
Error: Failed to call git rev-parse --git-dir --show-toplevel: "fatal: this oper
ation must be run in a work tree\n"
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x71a5c5]
goroutine 1 [running]:
github.com/git-lfs/git-lfs/localstorage.localObjectDir(0x0, 0xc04212effb, 0x40,
0x917db0, 0xc0421b8400)
C:/Users/techn/go/src/github.com/git-lfs/git-lfs/localstorage/localstora
ge.go:59 +0x65
もうちょいgracefulに失敗しても良くない。。?
同様に、bareリポジトリに git lfs install
することもできない。
$ git lfs install --local
Error: Failed to call git rev-parse --git-dir --show-toplevel: "fatal: this oper
ation must be run in a work tree\n"
Not in a git repository.
ガチの手動
git-lfsのHTTP REST APIを手で叩くことも論理的には可能ではある。Git-LFSには ディスカバリプロトコル が存在して、URLから機械的にoidのURLを得られる。このURLを元に直接アクセスすれば、そもそもGitリポジトリをcloneしてくる必要もない。
http://<giteaのURL>/private/photos.git/info/lfs/objects/732a758621cc15b0fc990437170b06386af1879640e5a4a38457419a7e67f067
のように、 ベースURL
+ リポジトリのパス
+ .git/info/lfs/objects/
+ <ファイルのSHA256>
でDLできる。 (基本的には別途 バッチAPI を叩いてURLを得るのが正しいようだ -- 例えば このGist ではGitHubは直接S3のURLを返却しているように見える)
リポジトリのアクセスに認証が必要な場合、DL用のトークンの発行はSSH経由で行える。サーバー側の git-lfs-authenticate
を呼べば良い。
$ ssh git@<giteaのSSHホスト> git-lfs-authenticate private/photos download
{"header":{"Authorization":"Bearer ey....."},"href":"http://<URL>/private/photos.git/info/lfs"}
この header
オブジェクトの内容を付けてHTTPでリクエストすれば同様の結果になる。
$ curl -H "Authorization: Bearer ey...." http://<giteaのURL>/private/photos.git/info/lfs/objects/732a758621cc15b0fc990437170b06386af1879640e5a4a38457419a7e67f067 --output temp.jpg
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3862k 100 3862k 0 0 5919k 0 --:--:-- --:--:-- --:--:-- 5924k