改行コードCRLFとLFの違いと統一方法
改行コードは LF(\n・0x0A)とCRLF(\r\n・0x0D 0x0A)の2種類が現役です。 Unix/Mac/Gitの内部表現はLF、WindowsはCRLFが標準。混在するとdiffが全行差分になる・シェルスクリプトが動かないなどの実害が出ます。
LF (\n) is the Unix/Git standard; CRLF (\r\n) is the Windows standard. This guide covers the real-world breakage and how to normalize line endings with .gitattributes.
TL;DR
- チーム統一は
.gitattributesに* text=auto(リポジトリ側で強制、個人設定に依存しない) - 既存ファイルの一括統一は
git add --renormalize .してコミット - シェルスクリプトの
bad interpreter: ^MはCRLFが原因。LFに変換すれば直る
1. 何が起きるか / What breaks
| 症状 / Symptom | 原因 / Cause |
|---|---|
| 1文字も変えていないのにdiffが全行差分になる | エディタが保存時に改行コードを変換した |
bad interpreter: /bin/bash^M | CRLFのシェルスクリプト。shebang行末の\rがパス扱いされる |
ESLintの linebreak-style で大量エラー | ルールはLF想定、ファイルがCRLF(またはその逆) |
| Dockerにコピーしたスクリプトだけ動かない | Windowsで編集したCRLFファイルをLinuxコンテナで実行 |
| ファイルのハッシュ値が環境で変わる | 改行1バイト差でもハッシュは別物になる |
「同じに見えるのに違う」状態の確認には差分チェッカー、\r がどこにあるかの特定にはUnicode Inspectorが使えます (どちらもブラウザ内で完結し、コードを外部送信しません)。
2. 現在の改行コードを確認する / How to check
- VS Code: 右下ステータスバーに「LF」「CRLF」と常時表示。クリックで変換可能
- Git:
git ls-files --eolでリポジトリ内/作業ツリーの改行を一覧表示 - コマンド:
file script.sh(「with CRLF line terminators」と出る)、cat -Aなら行末に^M$
3. Gitでの統一方法 / Normalizing with Git
推奨: リポジトリに .gitattributes を置く。全員の個人設定に関係なく同じ挙動になります。
# .gitattributes
# テキストファイルはコミット時にLFへ正規化(チェックアウトはOS依存)
* text=auto
# 常にLFでチェックアウトしたいもの(シェルスクリプト等)
*.sh text eol=lf
# 常にCRLFが必要なもの(バッチファイル)
*.bat text eol=crlf
# バイナリは変換しない
*.png binary追加したら既存ファイルを一括で正規化します。
git add --renormalize .
git commit -m "normalize line endings"個人設定の core.autocrlf を使う場合の挙動は次のとおりです。
| 設定 / Setting | コミット時 / On commit | チェックアウト時 / On checkout | 想定 / For |
|---|---|---|---|
true | LFに変換 | CRLFに変換 | Windows(CRLF前提のツールを使う) |
input | LFに変換 | 変換しない | Mac/Linux、WindowsでもLF統一なら可 |
false(既定) | 変換しない | 変換しない | .gitattributesで管理する場合 |
4. エディタ側の統一 / Editor configuration
# .editorconfig (主要エディタが標準対応)
root = true
[*]
end_of_line = lf
[*.bat]
end_of_line = crlfVS Codeなら "files.eol": "\n" でも新規ファイルをLFにできますが、 チームで共有できる .editorconfig の方が確実です。
5. English summary
LF (0x0A) is the Unix and Git-internal standard; CRLF (0x0D 0x0A) is the Windows standard. Mixed endings cause whole-file diffs, ESLint linebreak-style noise, differing hashes, and the classicbad interpreter: /bin/bash^M failure when a CRLF script runs on Linux. Check the current state with the VS Code status bar or git ls-files --eol. The robust fix is a committed .gitattributes with * text=auto (plus eol=lf for shell scripts), followed by git add --renormalize .. Per-usercore.autocrlf works but depends on every member configuring it correctly, so prefer the repository-level approach.
関連ツール / Related tools
- Diff Checker - 改行・空白差を含む差分の可視化
- Unicode Inspector - \r などの不可視文字を特定
- Hex Converter - 0x0D 0x0A をバイト列で確認