guide/line-endings.md

改行コード(CRLF・LF)と見えない差分 — すべての行が変わったと表示されるとき

見た目は同じなのに diff ですべての行が違うと表示される原因となる CRLF・LF の改行、ファイル末尾の改行、BOM、タブとスペース、特殊な空白、Unicode 正規化と、その解決方法をまとめました。

最終更新: 2026-09-23

2つのファイルを開いてみると1文字も違わないのに、diff がすべての行が変わったと言ったり、最初の行や最後の行だけが違うと言ったりすることがあります。原因はたいてい、画面に見えない文字です。この記事では、そうした「見えない差分」の種類と解決方法をまとめます。

改行文字:CRLF、LF、CR

行を改める方法は、OS によって慣習が異なります。

表記バイト主に使われる場所
LF0A (\n)Linux、macOS、ほとんどの開発ツール
CRLF0D 0A (\r\n)Windows のメモ帳など多くのプログラム、メール・HTTP などのインターネットプロトコル
CR0D (\r)ごく古い Mac OS(バージョン9以前)

一方のファイルが CRLF、もう一方が LF で保存されていると、行単位で比較したときにすべての行末にある見えない \r が1つずつ差分として検出され、全体が変わったように見えます。GNU diff では --strip-trailing-cr、git diff では --ignore-cr-at-eol でこの違いを無視できます。

ファイル末尾の改行

POSIX の慣習では、テキストファイルの各行は改行文字で終わります。そのため多くのツールは最終行の後にも改行を入れますが、入れないエディタもあります。この違いは unified diff では次のように表示されます。

@@ -1,2 +1,2 @@ host=example.com-port=8080\ No newline at end of file+port=8080

\ No newline at end of file は、すぐ上の行の末尾に改行がないという意味です。上の例では内容は同じで、変更後のファイルにだけ最後の改行が追加されました。多くのコーディング規約はファイル末尾の改行を求めており、エディタの「ファイル末尾に改行を挿入」設定で統一できます。

BOM:最初の行だけが違うとき

UTF-8 ファイルの先頭に EF BB BF の3バイトが付いていることがあります。これをバイトオーダーマーク(BOM)と呼びます。UTF-8 ではバイト順の指定は不要ですが、一部のプログラムが「このファイルは UTF-8」という目印として付けます。BOM は画面に表示されないので、最初の行だけが違うと出たら BOM を疑ってみてください。このサイトはファイルを読み込むときに先頭の BOM を取り除き、空白無視オプションをオンにすると、貼り付けたテキスト内の BOM(U+FEFF)も空白と同じように扱います。

タブとスペース、特殊な空白

これらの文字は、空白無視オプションをオンにすればほとんど取り除かれます(ただし U+200B のように空白文字に分類されない文字は、オプションをオンにしても残ることがあります)。行内比較を文字単位に切り替えると、見えない文字がどの位置にあるかを強調表示で見つけられます。

Unicode の正規化:同じ文字、違うバイト

日本語の「が」は、1文字の合成済み文字(U+304C)としても、「か」(U+304B)の後に結合用濁点(U+3099)を続けた形としても表せます。韓国語のハングル「가」も同様に、1文字(U+AC00)でも、子音 ㄱ(U+1100)と母音 ㅏ(U+1161)の組み合わせでも表せます。Unicode は前者を NFC、後者を NFD の正規化形式と呼びます(UAX #15)。2つのテキストは画面上ではまったく同じに見えますが、比較すると別の文字です。macOS で作ったファイル名が、ほかの OS で濁点が分かれた形になって見える現象が代表的な例です。比較の前に一方を NFC に変換して揃えるのが解決策です。

git で改行を統一する

複数の OS で共同作業するリポジトリなら、git の設定で改行を統一できます。

* text=auto
*.sh text eol=lf
*.bat text eol=crlf

text=auto は、git がテキストファイルと判断したファイルの改行をリポジトリ内で LF に正規化し、eol=lfeol=crlf は作業フォルダに取り出すときの改行を指定します。

このツールで試す

テキスト比較ツール改行コードを正規化は既定でオンになっており、CRLF・CR・LF をすべて同じ改行とみなし、ファイル末尾の改行の有無も無視します。このオプションをオフにすると、行末の CR は で、最終改行のない行は で表示され、見えなかった差分を確認できます。空白関連のオプションは 空白無視オプションに、結果の記号の意味は unified diff の読み方にまとめています。

テキスト比較ツールを使う