テクノロジー · 実用ガイド

Git LFS が「pointer であるべき」と警告?作業コピーを失わず索引を直す

まずファイルを保全し、属性と Git オブジェクトの不一致を証明してから、狭い正規化か協調した履歴移行を選び、新規 clone で検証します。

Git LFS の属性、索引、作業ツリー不一致を示すオリジナル図。
Watch at Ease オリジナルイラスト:LFS 規則は pointer を要求しますが索引には完全 blob があります。 Watch at Ease

この警告は通常、.gitattributes が LFS を要求する一方で、コミットまたは索引が完全なファイルを通常の Git blob として保持していることを示します。clean フィルターが比較用 pointer を作るため、reset 後も変更表示が戻ります。

git reset --hard、.git/lfs の削除、force push から始めてはいけません。作業バイトを保全し、規則とオブジェクトを確認して最小範囲を修正し、遠隔 LFS オブジェクトを証明します。

1. Git を変える前にバイトを保全

reset、checkout、移行の前に対象ファイルをリポジトリ外へコピーするか暗号学的ハッシュを記録し、git status、パス、現在のブランチも保存します。

無関係な変更があれば止めます。正規化は clean なブランチか使い捨て clone で行い、保全ファイルは外に置きます。

2. 属性とオブジェクトの不一致を証明

git check-attr -a -- path で入れ子の .gitattributes と大文字小文字を含む実効規則を確認し、作業ファイルを置換せず索引または HEAD の物体を調べます。

本物の LFS pointer は version、OID、size を持つ短い文字列です。LFS 対象なのに HEAD が完全 blob なら、作業バイトの変化ではなく表現の不一致です。

3. まず現在のブランチを修正

現在のブランチでは規則を明示し、clean な状態で git add --renormalize -- path を実行して staged diff を読みます。索引は pointer となり、作業ファイルは利用可能な内容を保つはずです。

確認した規則と pointer 修正だけをコミットします。この修正はそのコミット以降に効くため、他のブランチも意図的に処理します。

4. 必要な場合だけ履歴を書き換え

過去のコミット変換やホストの履歴制限が必要な場合だけ git lfs migrate を使います。使い捨て clone で --no-rewrite または import --fixup と正確な refs を試します。

履歴移行は commit ID を変え、force push や再 clone が必要です。refs をバックアップし切替を調整して、共有 remote で範囲を探索しません。

5. pointer と遠隔オブジェクトを検証

選んだ範囲に git lfs fsck --pointers を実行し、git lfs fsck でローカル物体を検査します。push 前に git lfs ls-files と pointer OID を確認します。

Git ref だけでなく LFS オブジェクトも送ります。Git push 成功や clean status は遠隔 LFS への到達証明ではありません。元と復元後のハッシュを保存します。

6. 新規 clone の結果だけを受入

空のディレクトリへ Git LFS 有効で新規 clone し、修正 ref を checkout して警告と見かけの変更がないこと、復元ファイルのハッシュとサイズが一致することを確かめます。

属性、pointer、遠隔物体、新しい作業ファイルが一致した場合だけ受入れ、別の協力者または CI の clone が通るまでバックアップを残します。

保全、修正、新規 clone の受入ゲートを示すオリジナル図。
Watch at Ease オリジナルイラスト:バイトを保全し最小範囲を直して新規 clone で確認します。 Watch at Ease