O hirunewani blog

Q. Git pullすると、いくつかのファイルのトラッキングが解除される

Created at

Git pullするといくつかのファイルのトラッキングが解除されたように見える状況の調査についてまとめた。

Table of Contents

状況

Notionのページをエクスポートしたマークダウンファイルを、WindowsまたはLinux環境からリモートリポジトリにプッシュし、この変更をmacOS環境でpullした場合に、日本語名のファイルの内いくつかのトラッキングが解除された状態になる。

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        src/content/ばびぶべぼ 9676d430076041ffb91b47bce6041745.md
        ...

対処

日本語名のファイルでのみ発生していたため、文字コードの問題であろうと推測したが。とりあえずGitのキャッシュをクリアして、全てを再度コミットすることで無理やり解決した。

git rm -r --cached .
git add .
git commit -m "chore: clear gits cache"

この状態で、リモートリポジトリにpushすると、ファイルを同じ名前から同じ名前に変更する差分が発生するが、 この対応を行なったファイルについては、同様の問題が再発しなくなった。

原因

ファイル名の差分が出たことから、文字コードの問題であることが確認できた。 実際に文字列を比較していくと、濁点文字の文字コードが異なっていた。

文字状況Unicode
でWindowsからpushされたファイル\u3066\u3099
macOSでpullしたファイル\u3067

環境によるUnicode正規化の違いによって、このような状況になっていると推測した。

まずNotionからエクスポートし、WindowsやLinux環境からリモートリポジトリにpushするまでのどこかで、NFD相当の処理が行われていると思われる。WindowsでNFDが採用されているという話は聞いたことがないので、Notionの処理なのかもしれない。 次に、リモートリポジトリでは結合文字列であった文字がmacOSにpullすると合成済み文字に変換されたため、GitかmacOSによってNFC相当の処理が行われたと思われる。

このような問題は、NFC/NFD問題と呼ばれているようだが、見かけ上は区別が出来ず、OSだけでなくアプリケーション毎にも扱いに差があるため非常に厄介だ。