Git LFSのリポジトリへの導入手順

# はじめに
GitHubのリポジトリの上限である5GB（推奨は1GB以下）を超える原因になりうるようなファイルを出力することになったので，Git LFSを利用することにしました．
ところが，想定外にエラー対処に時間が掛かったのと，遭遇したエラーの対処法を記述した記事が見当たらなかったので，その際の対処法を備忘録的にまとめたいと思います．


# TL; DR
- エラー内容
    - `git lfs track <file_pattern>`で指定したが`git lfs ls-files`で確認できない
- 対処法
    - `git rm --cached <file_pattern>`


# Git LFSとは
Gitはその時点でのスナップショットによって履歴を保存するため，大きなファイル（GitHubでは500MB以上）を扱うには不向きです．

そこで登場するのがGit LFSで，Git LFSは大きなファイル本体をGitリポジトリに保存せず，代わりのGit LFS専用のリモートサーバに保存します．Gitリポジトリは，そのファイルのポインタ情報のみを管理することで，リポジトリ本体のサイズを小さく保ったまま，全体の変更を管理することができるようになります．

以上，簡単に説明しましたが，より詳細を知りたい方はこちらを参照されるのが良いかもしれません．

https://git-lfs.com/


# Git LFSのインストール
OSによってインストールの方法が異なります．
それぞれの手法を以下に示しておきますが，個別具体的な対処についてはご自身で調べてみてください．

- Windows
    - [公式ページ](https://git-lfs.com/)よりインストーラーをダウンロード
- Mac
    - `brew install git-lfs`
- Ubuntu
    - `apt install git-lfs`

:::note warn
本章であつかうインストールとは，Git LFS自体のインストールのことです．なぜ，わざわざ明記するかというと，後に`git lfs install`というコマンドが登場するのですが，私自身，初めて勉強したときにはこれらと混同してしまい，何度も失敗したからです．
:::

Git LFSのインストールに成功すれば以下のような出力が得られます．

```bash: git_lfs_version
~$ git lfs version
git-lfs/3.5.1 (GitHub; linux amd64; go 1.21.8)
```


# Git LFSの基本的な使い方
先ずは，Git LFSの基本的な使い方について紹介します．今回，詰まったポイントは次章で説明するので，そちらが目的の方は飛ばされてください．

## 1. Git LFSの導入
Git LFSを対象のリポジトリで利用するために，Git LFSの初期化を実施します．

```bash: git_lfs_install
~$ cd /path/to/repo_root    # 対象のリポジトリのルートディレクトリに移動
~$ git lfs install 
Updated Git hooks.
Git LFS initialized.
```

以上のようなログが出力されれば成功です．

## 2. 追跡対象のファイルを指定
Git LFSで追跡するファイルを指定します．基本的なコマンドは以下の通り．

```bash: git_lfs_track
~$ git lfs track <files>
```

以上のコマンドを実行して，リポジトリのルートディレクトリに`.gitattributes`が作成されていれば成功です．

また，よく使う使い方を以下にいくつか示しておきます．

```bash: git_lfs_track_extension
~$ git lfs track "*.jpg"               # 拡張子で指定
~$ git lfs track /path/to/track_dir    # ディレクトリで指定
```

## 3. `.gitattributes`ファイルのコミット
Git LFSの追跡情報をリポジトリに反映させるために，先程の操作で作成された`.gitattributes`をコミットします．

```bash: add_gitattributes
~$ git add .gitattributes                # .gitattributesのみをステージング
~$ git commit -m "add .gitattributes"    # commitして変更を反映
~$ git push                              # これはどちらでも良い
```

:::note warn
`git add .gitattributes`についてですが，`git add .`としてしまうとGit LFSで追跡されずに，通常のGitで追跡されてしまうようです．（$n$敗）
:::

## 4. 全体のコミット
最後に全体を通常通りにコミットすれば，指定したファイルをGit LFSが管理してくれます．

```bash: git_commit
~$ git add .
~$ git commit -m "your comment"
~$ git push
```


# 【本題】Git LFSによる追跡の設定が反映されない
先ずは，今回遭遇したエラーについて．

```bash: git_track
~$ git lfs track              # 現在の設定を出力
Listing tracked patterns
    *.pdf (.gitattributes)
    *.csv (.gitattributes)
Listing excluded patterns
~$ git lfs ls-files           # 実際にGit LFSで管理されているファイルの一覧を出力
```

上に示すように，Git LFSの「設定」は正しくされているものの，該当するファイルが存在しないというものでした．

これについて調査をすると，概ね以下の点で問題が発生している可能性が挙げられます．

- `.gitattributes`の位置が正しくないのではないか？
    - リポジトリのルートにあるため，今回のエラーとは異なる
- `git lfs install`がされていないのではないか？
    - 再度コマンドを叩いたが変化せず

以上のいずれにも該当しませんでしたが，他にも色々と検証していくうちに，次に紹介する方法で解決しました．

```bash: git_lfs_import
~$ git rm --cached <file_pattern>    # Gitの追跡から明示的に削除する
~$ git add .
~$ git commit -m "re-commit large files"
~$ git push
```

どうやら通常のGitの追跡情報が残っていたのが原因のようでした．

私の環境で，当該のファイルは1度もステージング & コミットをしたことがなく，また，`git lfs install`を実行した後に作成されたファイルでした．そのため，Gitの追跡情報が残っており，Gitによる追跡が優先されていることが原因だとは全く思いませんでした．
思い込みって怖いですね……


# 最後に
本記事ではGit LFSの導入手順について説明してみました．Git関連は抽象的で分かりにくい部分が多いですが，今回のGit LFSは上手く利用できれば使い勝手が良いものなので，積極的に利用していきたいですね．