世界を動かす技術を、日本語で。

Git-Annex

概要

  • git-annex は、Gitで大容量ファイルを管理可能にするツール
  • オフライン・オンライン問わず同期、バックアップ、アーカイブを実現
  • チェックサムや暗号化による高いセキュリティ
  • コマンドライン派には柔軟な操作性、初心者向けにアシスタントも用意
  • 多様なユースケースに対応し、将来性・拡張性も確保

git-annexの特徴

  • 大容量ファイル管理 をGitで実現、ファイル内容はGitに直接保存しない設計
  • オフライン・オンライン環境での データ同期・バックアップ・アーカイブ に対応
  • チェックサム暗号化 によるデータの安全性
  • Gitの 分散型構造 を活かした大容量ファイルの管理
  • コマンドラインユーザー向けの高機能な操作性
  • git-annex assistant による、初心者でも使いやすいフォルダ同期機能
  • ウォークスルー で導入手順や使い方を簡単に体験可能

ユースケース:アーキビスト Bob

  • 多数のドライブにデータをアーカイブ、ほとんどをオフラインで安全に保管
  • 単一のディレクトリツリー で全ファイルを管理、内容はオフラインでもOK
  • ファイルの再編成や新バージョンのコミットも安全に実行
  • 必要なファイルが どのドライブにあるか を即時特定可能
    • 各ドライブが他の全ドライブの内容を把握
  • シンプルなリポジトリフォーマットで 将来の可用性 も確保
  • 夜間に cronジョブ で新ファイルを自動アーカイブ
  • 意図的・非意図的なコピーも追跡、バックアップ戦略の最適化に活用

ユースケース:ノマド Alice

  • ノートPCやUSBドライブ、クラウド、サーバーなど 多様なデータソース を持ち運び
  • すべてのデータソースを gitリモートのように一元管理
  • 手動同期やファイルの場所管理の手間を削減
  • 回線が弱い時はサーバーで ファイルをキューイング、後でUSBへダウンロード
  • モバイル環境や省電力時は USBからPCへコピー して効率的に利用
  • 作業終了後は 不要ファイルを削除、次回同期時に変更をサーバーへ反映
  • 分散バージョン管理 で、どこにいてもデータの整合性を維持

git-annexの将来性とコミュニティ

  • 小さな重要ファイル はGit、大容量ファイルはgit-annexで一元管理
  • Free Software としてHaskellで開発、誰でも貢献可能
  • Ikiwiki によるWiki、 Branchable でホスティングされた活発なコミュニティ
  • ドキュメントやユーザー事例も充実、導入・運用のハードルが低い

Hackerたちの意見

コマンドラインのドキュメントにユースケースがしっかり載ってるのを見ると嬉しいね。いつも「多分使わないようなマイナーなコマンドフラグ」から始まるけど。

git-annexを使って、すべてのドライブのデータを管理してるよ。どのファイルがどのドライブにあるか自動で追跡してくれるし、コピーも十分に確保してくれるし、すべてのファイルのチェックサムも取ってくれる。オフラインのドライブでも完璧に動くよ。git-annexはちょっと難しいかもしれないから、使い捨てのリポジトリを作って、ウォークスルーに従って試してみるのをおすすめするよ。[1] https://git-annex.branchable.com/walkthrough/ [2] https://git-annex.branchable.com/workflow/

どれくらいのデータを持ってるの?俺は写真にgit-annexを使ってて、約10万〜100万ファイル、数TBのデータがZFSにあるんだ。最初はすごく良かったけど、だんだん遅くなってきて、今では操作が数分(5〜30分くらい)かかるようになっちゃった。これがZFSのせいなのか、git-annexのせいなのか、もしくはディスクの問題なのか、ちょっと気になってる。

過去にこれをやろうと思ったことがあるけど、いくつかの問題にぶつかったんだ(その一つが、一度追加したファイルを永久に削除するのが面倒だったこと)。もし時間があれば、どう使ってるのか教えてもらえると興味あるな。

Git-Annexはすごくクールな技術だけど、個人用リポジトリに最適って印象があるな。例えば、@nolist_policyが別のコメントで説明してたように、いろんなデバイスで個人ファイルやドキュメント、音楽などを管理するのに向いてる。大きなファイルを共同作業のリポジトリで同期するために使ってみたけど、「マジック」ブランチの使い方はあまりスケールしなかったな。

人それぞれかもしれないけど、うちの組織ではうまくいってるよ。うちはアーカイブ機関で、デジタルリポジトリシステムのストレージバックエンドとして、10年以上もgit-annexを使ってる。正直、スタッフは15~20人しかいないけど、データは30TB以上、ファイル数は約75万(バイナリとメタデータを含む)、何百ものコレクションリポジトリがあるんだ。

9日前に「Gitの大きなファイルの未来はGitにある」についての関連ディスカッションがあったよ: https://news.ycombinator.com/item?id=44916783

ありがとう!あんまり関係ないけど、スレッドのコメントで書いた理由もあるんだ: https://news.ycombinator.com/item?id=44922405 つまり、annexは「gitの大きなファイル」とは別の問題領域にあるんだよね、明らかな重複があるけど。考え方としては、git-annexはLFSみたいなものの「サーバーサイド」でのストレージ問題に対する、gitネイティブで分散型の解決策って感じかな。そこから考えるといいよ。

ページには書いてないけど、git-annexは https://www.patreon.com/joeyh によって作られたもので、彼は素晴らしい https://joeyh.name/code/moreutils/ や https://etckeeper.branchable.com/ も作ったんだよ。

より有名な(俺にとっては)、彼は1996年から数十年にわたってDebianのコアコントリビューターだったんだ。Linuxの大部分は彼のキーボードから生まれたと言っても過言じゃないね。

自ホストのforgejoを使ってるけど、今のところgit-annexがLFSより優れてる点が見当たらないな。annexを簡単にセットアップできるかもわからないし。調べてみたら、git-annexはHaskellで書かれてるみたいで(あんまり好きじゃない)、50%遅いみたい(Haskellから来る予想だけど、今のところソースが1つだけだからあんまり信頼性はない)。コマンドの複雑さには魅力を感じないな。多分目的はあるんだろうけど。一度.git-LFSの.gitattributesを開けば、必要なことはほぼわかるし、あまりコマンドも必要なくなる。あと、.gitattributeを設定すると、.gitignoreと同じようにすべてが透明になるのが好きなんだ。git-annexにはその同等のものが見当たらないな。最後に、「git lfs ls-files」の同等のものを見せない「チュートリアル」やガイドは、絶対に魅力を感じないよ。俺は「git status」や「git lfs ls-files」を使って、すべてを確認したり再確認したりするのが好きだから。

Forgejoのソフトフォークがあって、git-annexのサポートが追加されてるよ: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo

annexが遅いのはHaskellで書かれてるからじゃなくて、I/Oと分散バックアップツールとしてのデフォルトの行動に伴う偏執的な理由から遅くなることが多いんだ。例えば、何かを落としたら、デフォルトでリアルタイムでアクセスできるリモートをチェックするから、実際には --fast みたいに使うと、かなり速くなることもあるよ。ちょっと危険だけど、ローカルにあるメタデータを信頼して、そのチェックをスキップする感じ。

LFSとgit-annexは、私の経験では微妙に使い方が違うんだ。LFSは、リポジトリに大きなファイルがあるような、ゲーム開発の例みたいなものを開発してるユーザー向け。git-annexは、音楽とか大きなファイルを含む重要なデータをバックアップするために使うもので、私の場合は後者を使ってるよ。

あなたのリポジトリはどれくらい大きいの?私が持ってる最大のgit-annexリポジトリは複数TB(複数のシステムに分散)で、10GBのファイルもあるよ。あなたが何をしてるのかはわからないけど、git-lfs-ls-filesのマニュアルを見た感じだと、git annex list --in hereが欲しいものかも?

git-annexに関して唯一の問題はHaskellなんだ。言語自体は嫌いじゃないけど、インストールしなきゃいけない依存関係の数がすごいんだよね。その依存関係の多くは他の何にも使われてなかったり、複数のアプリが使うとバージョンが不整合になったりすることもある。システムパッケージマネージャーでインストールするときが一番面倒。たった2つのHaskellアプリ - annexとpandoc - でも、日々のアップデートが小さなHaskellパッケージで埋まっちゃう。ソースからインストールするディストリビューションにいるなんて、神様が禁じてくれ!ほとんど、もし全部じゃなければ、アプリに直接静的リンクするのがかなり安全だよ。他のアプリと共有されてるやつもあるけどね。この不満は何度か聞いたことがある。Haskellの人たちの返事は、ライブラリエコシステムの細かいモジュール性のためだって言ってるけど、なんでHaskellがすべての始まりと終わりみたいに扱われるの?時にはシステム管理みたいな他の優先事項もあるのに。他のコンパイル言語にはこんな問題ないよ - Rust、Go、Zig、... それに、昔ながらのCやC++も依存関係に関してはこんなにイライラしない。Haskell言語やそのエコシステム、ユーザーに対して敵対的ではないことを明確にしておくね。自分も学ぶつもりなんだ。でも、なんでこの問題が存在するの?解決策はあるの?

どのパッケージマネージャー使ってるの?Haskellでapt系のシステムに問題があるのは見たことないけど?

ほとんど、もし全部じゃなければ、アプリに直接静的リンクするのがかなり安全だよ ディストリのリポジトリのことを言ってるなら、これはディストリとパッケージマネージャーのポリシーの問題じゃない?

フルタイムのHaskell開発者として、静的リンクされてないHaskellベースのディストリ包には同じように抵抗があるよ。AURには静的リンクされたHaskellパッケージもあるから、少なくとも可能ではあるね。パッケージャーがディストリ包の動的リンクにこだわる理由については、まだ詳しく調べてないけど、君が言う理由で避けてるよ。正確に何が理由かは自信を持って言えないけど、推測するしかないね。動的リンクは内部アプリケーションの配布において多くのケースで意味があるから、Haskellがよく使われるところでそれを誤ってディストリ包に投影してるのかもね。

そうだね!pacman -Syuを実行するたびに、更新の半分がHaskellパッケージだよ。確かpandocとshellcheckだったかな?

Haskellのツールはすでに依存関係を静的にリンクすることをサポートしてるよ。俺はSolusのHaskellスタックを維持してるし、pandocに関してはlibcだけに依存する単一のバイナリを持ってる。他のHaskellの依存関係はすべてバイナリの中に静的にリンクされてるから、Rustの依存関係と同じように動くんだ。だから、確実に実現可能だよ。これはディストリのメンテナの選択の問題だと思う。Solusでは依存関係の量が多すぎて俺には手に負えなかったから、静的リンクに頼ったんだ。

何年もこれを使ってるけど、俺にとっての大きなポイントはクラウドストレージプロバイダーとの統合だったんだ。バックアップの手段としてね。でも、それはいつも不安定で、メンテナンスされてないサードパーティのプラグインに依存してた。確か、データの不整合を引き起こすバグもあったから、結局やめちゃった。ここ5年でその辺の状況が改善されたか知ってる人いる?

クラウドストレージプロバイダーによると思うよ。S3やwebdav、sftpなどの標準的なプロトコルをサポートしてるところが一番可能性が高いかな。比較的新しい開発として、rcloneに組み込まれた特別なリモートがあって、これが他のサードパーティの特別なリモートよりもメンテナンスがしっかりしてるはずで、rcloneがサポートしてるすべてのリモートにアクセスできるよ。

SharePointやDropBoxにデータがあって、それを引っ張って(ローカルマシンと同期)使えるの?俺の使い方は主にETL関連で、全顧客データ(企業顧客)を引っ張って処理したいんだ。でも、データを常に更新したいから、引っ張る必要があるんだよね。

理想的な世界では、rcloneの特別なリモートがgit-annexのimporttree機能をサポートしてるはずなんだ。そうすれば、定期的にgit annex import : --from を実行してリモートから「引っ張る」ことができる(実際にはリモートからバージョン管理されたデータを取得してるわけじゃなくて、非バージョン管理のソースからインポートして新しいリビジョンとして記録することになるけど)。残念ながら、これが(まだ?)サポートされてないと思う。でも、こういうこともできるよ:rclone copy/sync : ./ && git annex add ./ && git commit -m