【git LFS】Encountered N file(s) that should have been pointers, but weren't

Encountered N file(s) that should have been pointers, but weren't

Git LFS を使用していると遭遇するエラー.

和訳すると, 「ポインターでなければならないが, そうなっていない\N個のファイルに遭遇した」
とのこと.

Git FLS は, サイズの大きいファイルを直接Git上で管理するのではなく,
実ファイルを指し示すポインターファイルを管理し,
checkout 時に実ファイルを別の場所から, ダウンロードする機構です.

どうやら, ポインターファイルになっていないファイルが
あると出るエラーのようです.

issue

GitHub上でこのエラーについての issue がありました.
英語は読めないので翻訳で頑張ります.
github.com

結論

以下コマンドを実行すると修正できるそうです.
issue 内で Git LFS の開発者が言ってました.

$ git add --renormalize .
$ git commit -m "Fix broken LFS files"

--renormalize を使用することで,
履歴を書き換えずに修正することができるようです.

issue で書かれている通り,
GitのFAQ にも記載されているようでした. git-scm.com

その他の対応方法

issue 内で他の方法での解決事例も投稿されていました.

uninstall -> install

git lfs uninstall # アンインストール
git reset --hard # ファイルを削除
git lfs intall # 再度インストール
git lfs pull # 実ファイルをダウンロード

→ issue 内ではこれでは解決しない人もいるようでした.

git lfs migrate

migrate を使用することで修正できた, という投稿もちらほらありました.
migrate コマンドは, gitファイル(blob) を Git LFS に変換するためのコマンドとのことです.

以下のようにいくつか投稿されていましたが,
migrate コマンドのドキュメントを見ると履歴を書き換える的なことが書かれているので,
結構実行には抵抗があります...

git lfs migrate import # 壊れたコミットの範囲にわたってこのコマンドを実行する.
git lfs migrate import --include="*.問題のあるファイルの拡張子"
git lfs migrate import --everything --include='*.deb'

migrate コマンドのドキュメントを見てみると,

When converting files to or from Git LFS, the git lfs migrate command will only make changes to your local repository and working copy, never any remotes.

Git LFS ファイルへの変換, または Git LFS ファイルからの変換を行う際,
git lfs migrate コマンドは ローカルリポジトリと作業コピーにのみ変更を加え,
リモートには変更を加えない.

This is intentional as the import and export modes are generally "destructive" in the sense that they rewrite your Git history, changing commits and generating new commit SHAs.

これは意図的な挙動で, インポートモードとエクスポートモードは一般的に「破壊的」であるとされています.
これは, Gitの履歴を書き換え, コミットを変更し, 新しいコミットSHAを生成するためです.
(「履歴を書き換えない」インポートサブモードもあるらしい.)

とのこと. github.com

git 管理対象のファイルを全削除→復元

git rm --cached -rf .
git reset HEAD --hard

git 管理対象のファイルを一度全て削除した後に,
reset --hard で復元することで治ったという報告です.
ファイル数の多いリポジトリでは時間がかかりそうな印象です.

オプション解説

--cached:
ファイルをワーキングディレクトリに残しつつ, リポジトリからのみ削除するオプション.
つまり, 実行後は, rm対象のファイルの削除差分と新規追加差分(Untracked file)が git status で表示される.
-r:
ディレクトリとその中のファイルをすべて削除するオプション.
-f:
強制的に削除するオプション.
変更されていないファイルに対して警告無しに削除する.

.gitattributes を削除→復元

.gitattributes はGitリポジトリ内の特定のファイルやディレクトリに対して,
カスタム属性を設定するためのファイルらしいです.

git lfs track で登録した設定もこのファイルに書き込まれます.
そのファイルを削除した後, reset --hard で解消するという報告が記載されていました.
個人的には他のに比べると比較的容易に試せそうな印象です.

git rm .gitattributes
git reset --hard HEAD

https://stackoverflow.com/questions/11383094/unstaged-changes-left-after-git-reset-hard