Git Annex から Git LFS への移行ガイド

注:GitLab Enterprise Edition 9.0 (2017/03/22)でGit Annexのサポートは削除されました。

Git Annexも Git LFSも、Gitで大きなファイルを管理するためのツールです。

沿革

Git AnnexはGitLab Enterprise Edition 7.8で導入されましたが、当時はまだGit LFSは存在していませんでした。 数ヶ月後、GitLabはGitLab 8.2でGit LFSをサポートし、Community EditionとEnterprise Editionの両方で利用できるようになりました。

Git Annex と Git LFS の違い

以下のいくつかの項目は2つのプロトコルの一般的な違いであり、いくつかはGitLabが開発したものです。

  • Git AnnexはSSHでのみ動作しますが、Git LFSはSSHとHTTPSの両方で動作します(SSHのサポートはGitLab 8.12で追加されました)。
  • Annex ファイルは通常のリポジトリのサブ・ディレクトリに保存されますが、LFS ファイルはリポジトリの外側の定義した場所に保存されます。
  • Git Annex はより複雑な設定を必要としますが、Git LFS よりもはるかに多くのオプションがあります。man git-annexman git-lfsを実行することで、それぞれのコマンドを比較することができます。
  • Annex ファイルは GitLab のインターフェイスで直接参照することができませんが、LFS ファイルは可能です。

移行手順

注意: Git Annex ファイルは通常のリポジトリ (.git/annex/objects) のサブディレクトリに保存され、LFS ファイルはリポジトリの外部に保存されるため、両者は異なるスキームを使っており互換性がありません。 そのため、移行はリポジトリごとに手動で行う必要があります。

Git Annex から Git LFS に移行するには、基本的に二つのステップが必要です。

TL; DR

自分が何をしているのかわかっていて、読むのを省きたい場合は、次のようにします (リポジトリでgit-annex を有効にしていて、何か問題が発生したときのためにバックアップを取っていることを前提としています)。 ターミナルを起動し、Git リポジトリに移動します:

  1. git-annexを無効にします:

    git annex sync --content
    git annex direct
    git annex uninit
    git annex indirect
    
  2. git-lfsを有効にします:

    git lfs install
    git lfs track <files>
    git add .
    git commit -m "commit message"
    git push
    

リポジトリの Git Annex を無効にする

何かを変更する前に、まずリポジトリのバックアップをとっておきましょう。 その方法はいくつかありますが、単純に別のローカルパスにクローンし、リモートバックアップも必要なら GitLab にプッシュすることもできます。 ここでは、git-annexポジトリを外付けハードドライブにバックアップする方法を説明します。

Annexファイルはシンボリックリンクを持つオブジェクトとして保存されており、直接変更することができないため、まずシンボリックリンクを削除する必要があります。

注意:direct モード については必ず読んでおきましょう。annex direct は Git Annex バージョン 6 で非推奨となりました。サーバーにも Git Annex 6 がインストールされている場合は、リポジトリをアップグレードする必要があるかもしれません。詳しくは](https://git-annex.branchable.com/direct_mode/)Git Annex のトラブルシューティング](https://git-annex.branchable.com/direct_mode/)を参照ください。
  1. リポジトリのバックアップ

    cd repository
    git annex sync --content
    cd ..
    git clone repository repository-backup
    cd repository-backup
    git annex get
    cd ..
    
  2. annex directを使用してください:

    cd repository
    git annex direct
    

    出力はこのようになるはずです:

    commit
    On branch master
    Your branch is up-to-date with 'origin/master'.
    nothing to commit, working tree clean
    ok
    direct debian.iso ok
    direct  ok
    
  3. annex uninitでGit Annexを無効にします:

    git annex uninit
    

    出力はこのようになるはずです:

    unannex debian.iso ok
    Deleted branch git-annex (was 2534d2c).
    

    これはリポジトリ内のすべてのファイルをunannex 、元のファイルを残します。

  4. indirect モードに切り替えます:

    git annex indirect
    

    出力はこのようになるはずです:

    (merging origin/git-annex into git-annex...)
    (recording state in git...)
    commit  (recording state in git...)
    
    ok
    (recording state in git...)
    [master fac3194] commit before switching to indirect mode
     1 file changed, 1 deletion(-)
     delete mode 120000 alpine-virt-3.4.4-x86_64.iso
    ok
    indirect  ok
    ok
    

この時点で、ファイルを追加してコミットし、GitLab に直接プッシュするか、Git LFS に切り替えるか、2 つの選択肢があります。 LFS への切り替えについては次のセクションで説明します。

Git LFS の有効化

Git LFSはすべてのGitLab製品(GitLab CE、GitLab EE、GitLab.com)でデフォルトで有効になっているため、サーバーサイドで何かをする必要はありません。

  1. まず、git-lfs がローカルにインストールされていることを確認してください:

    git lfs help
    

    ターミナルでgit-lfs コマンドを実行しても完全な応答が得られない場合は、まずGit LFS クライアントをインストールしてください。

  2. リポジトリ内で以下のコマンドを実行し、LFSを開始します:

    git lfs install
    
  3. 追跡したいファイルグループに対して、git-lfs を有効にします。 特定のファイル、同じ拡張子を含むすべてのファイル、またはディレクトリ全体を追跡できます:

    git lfs track images/01.png   # per file
    git lfs track **/*.png        # per extension
    git lfs track images/         # per directory
    

    そうしたら、git status を実行すると、.gitattributes がリポジトリに追加されます。これは、git-lfsで追跡することにしたすべてのファイルパターンを収集します。

  4. ファイルを追加し、コミットして GitLab にプッシュします:

    git add .
    git commit -m "commit message"
    git push
    

    リモートがHTTPで設定されている場合は、ログイン認証情報の入力が求められます。2FAを有効にしている場合は、パスワードの代わりに個人アクセストークンを使用してください。

Git Annexブランチの削除

移行が成功したら、リポジトリからgit-annex関連のブランチをすべて削除できます。

GitLab でプロジェクトのリポジトリブランチに移動し、Git Annex で作成したブランチをすべて削除します。git-annexsynced/以下のブランチもすべて削除します。

repository branches

コマンドラインでもできます:

git branch -d synced/master
git branch -d synced/git-annex
git push origin :synced/master
git push origin :synced/git-annex
git push origin :git-annex
git remote prune origin

リポジトリ内部(.git/annex/)にAnnexオブジェクトが残っていたり、.git/configの内部を参照している場合は、annex uninit を再度実行してください:

git annex uninit

さらに読む