Git Annex入門(1)

Date: 2020/04/22 (initial publish), 2021/07/13 (last update)

Source: jp/note-00023.md

Previous Post Top Next Post

TOC

正直なところ、今は Git Annexを 使っていません。rsync と btrfs の 組み合わせでバックアップしています。(2021/07/07)

Git関連ツールで、写真等の大きなデーターの分散保存・世代管理をする Git Annexというツールを walkthrough を読みながら学びました。間違っているかもしれませんが、 自分なりに簡単に以下にまとめて見ます。

Git Annexの基本コンセプト

Gitはデーターの分散管理では非常に便利ですが、 大きなデーターを直接扱うのが不得意 です。そこで、このGitが不得意な部分のデーターの分散管理を協調的に補完す るのがGit Annexです。

写真等の大きなファイルを含むデーターは、ソースコードなどのテキスト ファイルを含むデーターと違い、ファイル自体がすでに圧縮されていて 保存の際のさらなるデーター圧縮のメリットが少ないことや、世代間の 詳細なデーター差分の検出には大きな労力が必要な割に、詳細な差分は サイズも大きくなりがちでメリットが少ないという特徴があります。

そこで大きなファイルは、Gitの本体で直接扱かわずに、労力とのバランス を考えGitの上に構築したGit Annexで扱うのが望ましいです。Git Annexでは データー保存の効率化対象を単純なファイルの重複保存や世代間のファイル の位置移動に絞ります。この制約の下では、ファイル実体によって決まる 「ユニークな特定パスに保存する」ことで、ファイル実体の効率的な保存 が実現できます。「ユニーク」ということはファイル内容のハッシュ値 等を用いた文字列(Key)で実現します。Git Annexではファイル実体データー (Value)をGit本来のデーター保存インフラとは別の.git/annex/objects/ 以下に書き込み禁止のファイルパーミッションで保存します。

一方、作業ディレクトリーツリー中のファイルがあった場所には Git Annex管理下に保存されたファイルへのシムリンクを置きます。 このシムリンクのデーターサイズは小さいので、本来のGitで問題なく 場所の保存や世代管理ができます。

このままでは他のプログラムによるデーターの編集・更新ができな いので、Git Annexはシムリンクをファイルで置き換え編集可能化する unlock機能と、Git Annexに編集結果を戻すlock機能を提供します。

さらにGit Annexは、「特定パスに保存する」という部分に関して、 「分散保存を管理するインフラを提供する」とすることで、すべての 分散管理レポジトリー内に全ファイルを保持しなくても良い とします。ここは全ファイルを保持する本来のGitレポジトリーと 大きく異なるところです。Git Annexは、分散管理レポジトリー間で それぞれが保存するファイルに関するメタ情報を交換するインフラも 提供します。

Git Annexがチェックアウトした作業ディレクトリーツリー中で、 ローカルに保持していないファイルは、ダングリングシムリンク (宙ぶらりシムリンク)となってしまいます。その際に、保有するメタ 情報に基づき指定範囲のファイル実体をリモートサイトから簡単に オンディマンドでコピーしてくる部分チェックアウト機能や、 作業ディレクトリーツリー中ダングリングシムリンクを簡単に消す 機能もサポートします。

Git Annexによるリモートサイトへのアクセスは抽象化されていて、 単純なファイルシステム経由のアクセスはもちろん、SSH経由のアクセス、 Amazon S3等の各種クラウドへのアクセスが、既成のバックエンドを 利用し、ほぼ同じ手順で簡単に実現出来るようになっています。

Git Annexの注意点

Git Annexは、バックアップファイルの数を自由に設定できたり、保存 ファイルのコピーの代わりに保存ファイルへのハードリンクを利用する ように設定できたり、ユーザーが自由にカスタマイズできる機能が多い 汎用性のあるツールです。それだけに、しっかり基本機能を学ぶことや、 良く各機能の動作を考えて使うことが重要です。

Git Annexは、大きなファイルをチャンクに分割して保存しません。これは ファイルシステムのトラブルの際等に被害範囲を限定的にできるので大きな メリットがあります。確かにこれは成長する巨大ログファイル等のデーター ではデメリットがある保存手法です。もしそのような成長するデーターを Git Annexが扱い保存することが避けられない際には、事前にそのデーターに logrotate(8) を適用してチャンクに分割・圧縮しておきましょう。 参考情報:2019年 参考情報:2019年

Git Annexは、ファイルを圧縮してて保存することをしません。圧縮が必須な ケースは限定的でしょうが、Git Annexのレポジトリーを作るファイルシステム に透過的な圧縮をサポートする、 NTFS (NT File System) (Linux上ではNTFS-3G経由で利用)・ F2FS (Flash-Friendly File System)ZFSBtrfsを利用し設定すれば、ファイルは 圧縮してディスクに保存されます。

作業ディレクトリーツリー中でシムリンクではない本来のファイルを 安全に他のソフトにGit Annexが提供するのは難しい問題です。また 当初はUnix系のファイルシステム上の操作のみが対象でしたが、FATや NTFSシステム上の操作も対象にしてきました。そういった経緯も有り Git Annexのサポートデーターを保持するレポジトリーは、 バージョンアップ が繰り替えされ、2020年(Debian buster + buster-backports) の「git-annex version: 8.2020033」では V8 になっています。

チョット古いネット情報は現行バージョンには当てはまらないことがある ので要注意です。(「direct mode」はもう存在しません)

Git Annexの基本操作

Git Annexレポジトリーの初期化(init)

Git Annexレポジトリーの初期化は、ベースとなるGitの初期化と、Git Annex の初期化の2段階で行われます。

$ mkdir ~/annex
$ cd ~/annex
$ git init
$ git annex init "my laptop"

Git Annexレポジトリーは、上記のように区別できるdescriptionを与えることが 望ましいです。

最初のdescription設定に関わらず、git annex describe "my laptop" と後からも設定・変更できます。

ファイル実体のGit Annexへの追加(add)

作業ディレクトリーツリー中にGit Annexに管理させる新規ファイル fooを追加するのは、ファイルを目的位置に移動し、その場所で

$ git annex add foo

とします。こうするとファイルがシムリンクで置き換えられます。 さらにシムリンク先のGit Annexがファイル実体を保持するファイルは、 書き込み禁止にファイルパーミッションが設定され保護(「lock」)され ています。

作業ディレクトリーツリー中のファイルの編集・更新(unlock/lock)

作業ディレクトリーツリー中のシムリンクに対応するGit Annexが保持 するファイルを編集するには、まず対応するシムリンクの場所で

$ git annex unlock foo

とします。こうするとシムリンクがファイルのコピーで置き換えられ、 ファイルパーミッションは書き込み可能に設定され保護解除(「unlock」) されます。このファイルを他のソフトに提供し編集します。編集後の ファイルに

$ git annex lock foo

とします。こうするとファイルはシムリンクで置き換えられます。 さらにシムリンク先のGit Annexがファイル実体を保持するファイルが 新たな場所に作成され、Git Annexのデーターが更新されます。

作業ディレクトリーツリー中のファイル移動・複製

作業ディレクトリーツリー中のGit Annexが保持するデーターを 移動・複製する際には、ファイルの内容には変更が無いので、 Git AnnexのコマンドではなくGitのコマンド操作で充分です。

移動:

$ git mv foo bar

複製:

$ git cp foo bar

サブディレクトリーに移動・複製する際には、シムリンクがおかしく なりそうですが、Git Annexがpre-commit hookを導入しているので 丸く収まりますので安心しましょう。

後述するように、Git Annexのmovecopyは、レポジトリー間の ファイルの移動です。混乱しないようにしましょう。

リモートの追加と初期化(init)

それぞれレポジトリーは、Gitのレポジトリーとして初期化や クローン後、Git Annexとしての初期化をします。

レポジトリー間のリモート設定の追加方法は通常のGitと変わりなく git remote add <name> <url>です。ただ、Git Annexに保存した ファイルは、必ずしも全レポジトリーが常に保有するわけではなく、 レポジトリー間で双方向に授受しながら保存するので、リモート設定 を双方向でしましょう。

例えばUSBメモリーを差し込み、それが/media/usbに自動マウント される場合は以下のようにします。

$ cd /media/usb
$ git clone ~/annex
$ cd annex
$ git annex init "portable USB drive"
$ git remote add laptop ~/annex
$ cd ~/annex
$ git remote add usbdrive /media/usb/annex

注: 上記では分かり易い様にlaptopというremoteを設定しているが、わざわざ 設定しなくともcloneしているのでoriginというremoteが設定されている。

Git Annexレポジトリー間の同期(sync)

Git Annexが管理する大きなデーターのレポジトリー間の操作の前に、 大きなデーターに関するメタデーターを、登録されたリモートレポジトリー 最新情報を問い合わせて更新する同期操作が必要です。

例えば、laptop上の~/annexにあるGit Annexレポジトリーの場合には 以下のように操作します。

$ cd ~/annex
$ git annex sync
 ...

例えば、USBメモリー上のローカルのGit Annexレポジトリーの場合には USBメモリーを差し込んだあとに以下のように操作します。

$ cd /media/usb/annex
$ git annex sync
 ...

メタデーターだけでなく、Git Annexが管理するファイル実体の更新も同時 に行いたい時にはgit annex sync --contentとします。

ファイル実体のGit Annexレポジトリー間移動(move)

USBメモリーを差し込んだまま、laptop上の~/annexにあるGit Annex レポジトリーからmy_cool_big_file1をusbdriveに移動(move)するには 以下のように操作します。

$ cd ~/annex
$ git annex move my_cool_big_file1 --to usbdrive

ファイル実体のGit Annexレポジトリー間複製(copy)

USBメモリーを差し込んだまま、laptop上の~/annexにあるGit Annex レポジトリーからmy_cool_big_file2をusbdriveに複製(copy)するには 以下のように操作します。

$ cd ~/annex
$ git annex copy my_cool_big_file2 --to usbdrive

ファイル実体のGit Annexレポジトリーからの削除(drop)

USBメモリーを差し込んだまま、laptop上の~/annexにあるGit Annex レポジトリーからmy_cool_big_file2ファイル実体を削除(drop)する には以下のように操作します。

$ cd ~/annex
$ git annex drop my_cool_big_file2

この時もしUSBメモリーを差し込んでいないと、Git Annexは重複データー の存在を確認できないので削除を拒否します。

ファイル実体の他Git Annexレポジトリーからの獲得(get)

USBメモリーを差し込んだまま、laptop上の~/annexにあるGit Annex レポジトリーのファイル実体がなくなりダングリングシムリンクとなった my_cool_big_file2のファイルの実体を外からの獲得(get)する には以下のように操作します。

$ cd ~/annex
$ git annex get my_cool_big_file2

この時もしUSBメモリーを差し込んでいないと、Git Annexは外部の重複 データーにアクセスできない旨のメッセージを表示します。

未使用ファイル実体のGit Annexレポジトリーからの整理(unused)

Git Annexレポジトリーの未使用ファイル実体の確認は以下のように操作します。

$ git annex unused

未使用ファイルを効率的にGit Annexレポジトリーから削除dropするには、 例えば以下のように操作します。

$ git annex dropunused 1-1000

未使用ファイルを効率的に移動moveや複製copyするには、以下のように操作します。

移動:

$ git annex move --unused --to archive

複製:

$ git annex copy --unused --to backup

Git Annex操作のヒント集

Git AnnexのGUI操作

コマンドラインでのGit Annexの基本操作がある程度分かると、 もう少し使いやすいGUIでの操作がしたくなります。

git-annex webapp を実行すると、Git Annexレポジトリーと git-annex assistant の実行コントロールのセットアップがウエッブブラウザーから簡単にできます。

GNOME等のGUI環境では git-annex assistant がバックグラウンドで自動実行されリモートとの同期がとられるとともに、 GUIファイラーコンソールのmc からGit Annexのdropgetの操作ができます。

Git Annexレポジトリーの重複保存数

全レポジトリーに対して以下でファイルの重複保存数をNに設定します。

$ git annex numcopies N

デフォルトは N=1 です。レポジトリーの 信頼性 にも注意しましょう。

.gitattributesファイルを使って、ファイル毎にオーバーライドできます。 – 情報源

Git Annexレポジトリーのファイルの探索や適度の冗長保存

保存状況の重複も含めた探索確認を以下でします。

$ git annex whereis

例えばそれぞれ2つづつの適度の冗長保存は以下でできます。 – 情報源

$ git annex get --auto --numcopies=2
 ...
$ git annex drop --auto --numcopies=2
 ...

Git Annexレポジトリーの整合性確認

レポジトリーデーターの整合性確認は以下のように操作します。 – 情報源

git annex fsck

Git Annexレポジトリーの変更回復(undo)

Git Annexのundoをするとファイルやディレクトリーにした変更をもとに 戻しますが、マルチレベルundoではないので、2回目の実行はundoをundo します。

作業ディレクトリーからのダングリングシムリンク削除

ダングリングシムリンクがあると混乱するソフト (例えばDebian 10 BusterのShotwell 0.30.1)には、 ダングリングシムリンクを削除して対応できます。 – 情報源

$ git annex adjust --hide-missing

git configgit annex configの違い

git configの設定はコマンドを実行したレポジトリーにのみ有効だが、 git annex configの設定はクローンしたレポジトリーにも有効です。

ハードリンク利用によるディスクスペース節約

もちろん使う際には常識的注意は必要ですが、ファイルのコピーの 代わりにハードリンクを利用するとディスクスペースが節約できます。

同一ファイルシステム上のレポジトリー間だと下記のように設定した 共有cacheをハードリンクを利用して作成してダウンロードとディスク スペースの両方を節約できます。 – 情報源

$ git config annex.hardlink true
$ git annex untrust here

Unlockした作業ディレクトリー中のファイルとGit Annexのレポジトリー間 だとハードリンクを利用してディスクスペースを節約できます。 – 情報源

$ git config annex.thin true
$ git annex fix

レポジトリーの連結

複数のディレクトリーのデーターの連結してGit Annexのレポジトリーにするには、 それぞれをGit Annexのレポジトリーとして、リーモートを設定しsyncimport をして連結するのが効率的手法です。

この他に、リーモートを設定しgit merge --allow-unrelated-histories ...と gitを直接操作する手法もあります。 – 情報源

ファイル数の多いレポジトリー

ファイルの自動振り分け保存

作業ディレクトリーツリー中に異種のコンテントを含み、 コンテント内容によってGit AnnexとGitのいずれかに保存したい 際には、これを設定で自動化できます。

かなりGit Annexに精通するまでは、Git AnnexとGitの両方データーをレポジトリー内で混ぜない方がシンプルなので賢明な感があります。

ファイルパーミッションやタイムスタンプ

Git Annexが通常使うハッシュから生成するkeyにはファイルパーミッションや タイムスタンプ情報が含まれません。だから、ファイルパーミッションや タイムスタンプの違いが区別されないはずなので、そこは理解して使うのが 良いようです。

暗号化保存

git-remote-gcryptパッケージを導入するとgpgを使った暗号化保存ができます。 – 情報源

暗号化保存した際には、使用したパスワードや暗号化キーが後で自分自身で分からなくならないように注意しましょう。(笑)

MetadataとView

まだよく分からないが、Git Annexの MetadataView は面白そうです。GUIエディターもあるようです。 – Git-Annex-Metadata-Gui

Git Annexを使っての所感

ちょっと使ってみただけなので、判断が怪しいところがありますが、現状の所感をまとめてみました。

Git Annexの良い点は:

ちょっと使ったあとのGit Annexの所感は:

因みにDebianにある、バックアップツール以外の気になるdedupツールはfdupes, jdupes, duperemove, duff, hardlink, rdfind, rmlint, rmlint-guiでした。 歴史的には圧倒的にfdupesが人気ですが、 最近(2020年5月)はjdupesが急に伸びてきていますし、duperemoveやduffやrmlint-guiも健闘しています

画像が同じだが日付等変更をしたEXIFファイルの重複検出は目に入らなかったので、昔書いたスクリプトをここに特化して書き直すのも良いかもと思いました。

Previous Post Top Next Post