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

Published at
564 words
3min read

状況#

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

Terminal window
$ 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 のキャッシュをクリアして、全てを再度コミットすることで無理やり解決した。

Terminal window
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 だけでなくアプリケーション毎にも扱いに差があるため非常に厄介だ。