(The English version follows the Japanese version.)
Windows で開発していると、エディタや PowerShell (以降: pwsh) の設定によって、同じリポジトリ内に CRLF と LF が混在しやすくなります。
この混在は、見た目では気づきにくい一方で、次の問題を引き起こします。
- 小さな修正なのにファイル全体が変更扱いになる
git diff --checkが大量の末尾空白を報告する- CI とローカルで差分の見え方が変わる
- Markdown や設定ファイルのレビューが難しくなる
- pwsh で保存しただけで、意図しない CRLF 変換が発生する
本方針では、今後作るファイルは LF に統一し、既存ファイルは必要な範囲だけ安全に変更します。
リポジトリのルートに、次の3つを用意します。
AGENTS.mdまたは同等の開発者向け指示書.editorconfig.gitattributes
ただし、これらを追加しただけで既存ファイルが自動修正されるわけではありません。既存ファイルを一括変換する場合は、専用の変更として扱います。
自動設定だけでは、エージェント、スクリプト、エディタごとの挙動を完全には揃えられません。リポジトリの指示書に、次を明記します。
## テキストファイルの正規化
- 新規作成および意図的に編集されたすべてのテキストファイルは、BOMなしのUTF-8形式を使用し、改行文字としてLF(`\n`)を使用する必要があります。
- CRLF形式のファイルを作成したり、1つのファイル内でCRLFとLFを混在させたりしないでください。
- 既存のファイルを編集する際は、タスクで明示的に正規化が求められていない限り、現在のエンコーディングと改行形式を維持してください。
- わずかな変更が必要なだけで、既存のファイル全体を正規化してはなりません。
- 編集には`apply_patch`を優先して使用してください。
- 変更を完了として報告する前に、`git diff --check`を実行してください。
- 末尾の空白や改行形式に関する警告は、修正に失敗したものとみなしてください。特に重要なのは、既存ファイルを無関係に全面変換しないことです。改行統一を一度に行う場合は、機能変更と分けた専用コミットにします。
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{png,jpg,jpeg,gif,ico,webp,woff,woff2,ttf,eot,pdf,zip,tar,gz,mp3,mp4}]
charset = unset
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset.editorconfig は、対応しているエディタがファイルを保存するときの既定値を揃えます。
設定する項目は次のとおりです。
charset = utf-8: UTF-8 で保存するend_of_line = lf: 改行を LF にするinsert_final_newline = true: ファイル末尾に改行を置くtrim_trailing_whitespace = true: 行末の不要な空白を除去する
画像やフォントなどのバイナリファイルには、テキスト向け設定を適用しません。
* text=auto eol=lf特定のファイルだけ指定する場合は、次のように書けます。
*.json text eol=lf
*.md text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.css text eol=lfeol=lf は、Git のチェックアウト時にテキストファイルを LF として扱うための設定です。
ただし、.gitattributes を追加しただけで、作業ツリーにある既存ファイルがすぐ全面変換されるわけではありません。既存ファイルを全体変換する場合は、差分量とレビュー負荷を確認してから、専用のコミットで実行します。
pwsh の通常の書き込みコマンドは、環境やバージョンによって改行やエンコーディングの挙動が異なります。
特に、次のような処理を無確認で使わないようにします。
Set-Content path/to/file.md $content
Out-File path/to/file.md既存ファイルの部分編集では、まず apply_patch を使います。pwsh から保存する必要がある場合は、UTF-8 BOMなしと LF を明示し、保存後にバイト列と Git 差分を確認します。
git diff --check
git diff --numstat
git status --short新規ファイルの改行を確認する例です。
$path = Resolve-Path '.\\walkthrough.md'
$bytes = [System.IO.File]::ReadAllBytes($path)
$hasBom = $bytes.Length -ge 3 -and
$bytes[0] -eq 0xEF -and
$bytes[1] -eq 0xBB -and
$bytes[2] -eq 0xBF
$hasCr = $bytes -contains 0x0D
Write-Output "BOM=$hasBom CR=$hasCr"新規 LF ファイルでは、次の状態が期待値です。
BOM=False CR=False
変更完了前に、次を実行します。
git diff --check何も出力されず、終了コードが 0 なら、通常の末尾空白検査を通過しています。
次のような出力が出た場合は、完了扱いにしません。
file.md:12: trailing whitespace.
pwsh で保存した直後に、追加した行のほぼすべてが trailing whitespace になった場合は、次を疑います。
- CRLF の
CRを Git が末尾空白として扱っている - ファイルが既存の混在エンコーディングである
- 保存処理がファイル全体を変換した
この場合は、さらに書き込む前にバイト列と git diff を確認します。
既存ファイルに小さな変更を加える場合は、次の順番にします。
git status --shortで作業ツリーを確認する- 対象ファイルの現在の改行とエンコーディングを確認する
- 必要な行だけを編集する
git diff --statで変更量を確認するgit diff --checkを実行する- 意図しない全体差分があれば、そこで停止する
改行を統一すること自体が目的の場合は、機能変更と分けます。
Commit 1: chore: normalize text file line endings
Commit 2: feat: implement the actual feature change
こうすると、レビュー時に「改行変更」と「ロジック変更」を分けて確認できます。
一括変換は、次の条件が揃った場合だけ実行します。
- 対象ファイルの範囲が明確である
- 生成ファイルやバイナリを除外できる
- 差分が改行だけであることを確認できる
- チームまたは保守担当者が専用コミットを確認できる
- CI と主要テストを再実行できる
一括変換後は、少なくとも次を確認します。
git diff --check
git diff --stat
git diff --numstat
npm test
npm run typecheck
npm run build既存ファイルに CP932 や特殊な改行が含まれている場合は、無理に自動変換しません。まず対象ファイルを限定し、エンコーディングを確認してから個別に対応します。
変更を完了と報告する前に、次を確認します。
- 新規テキストファイルは UTF-8 BOMなしである
- 新規・編集ファイルは LF である
- CRLF と LF を同じファイルに混在させていない
- 既存ファイルを無関係に全面変換していない
-
.editorconfigと.gitattributesの方針に従っている -
git diff --checkが成功している -
git diff --statの変更量が意図どおりである - 必要なテストとビルドを実行している
- 改行変更と機能変更を別コミットに分けている
Windows では、改行を「エディタの設定だけ」に任せません。
AGENTS.md 人とエージェントへのルール
.editorconfig エディタの保存設定
.gitattributes Git のテキスト扱い
git diff --check 完了前の検査
この4段階を揃え、既存ファイルの一括変換は専用の変更として扱うことが、CRLF / LF 混在を長期的に防ぐ最も安全な方法です。
When developing on Windows, editor and PowerShell(pwsh) settings can easily introduce both CRLF and LF into the same repository.
This is easy to miss visually, but it causes several problems:
- A small edit appears as a change to the entire file
git diff --checkreports a large number of trailing-whitespace errors- Local and CI diffs look different
- Markdown and configuration-file reviews become harder
- Saving a file with pwsh unexpectedly converts its line endings to CRLF
This policy uses LF for newly created and intentionally edited files, while existing files are changed only as far as the task requires.
Add the following three files or policies at the repository root:
AGENTS.mdor an equivalent developer instruction file.editorconfig.gitattributes
Adding these files does not automatically rewrite every existing file. A full conversion of existing files must be handled as a dedicated change.
Automatic settings cannot fully align the behavior of agents, scripts, and editors. Add rules like these to the repository instruction file:
## Text file normalization
- All newly created and intentionally edited text files must use UTF-8 without a BOM and LF (`\n`) line endings.
- Do not introduce CRLF files or mix CRLF and LF in one file.
- Before editing an existing file, preserve its current encoding and line-ending style unless the task explicitly requests normalization.
- Do not normalize an entire existing file merely because a small change is needed.
- Prefer `apply_patch` for edits.
- Run `git diff --check` before reporting a change as complete.
- Treat any trailing-whitespace or line-ending warning as a failure to fix.The most important rule is not to rewrite unrelated existing files. If line-ending normalization is required, keep it separate from feature changes in its own commit.
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{png,jpg,jpeg,gif,ico,webp,woff,woff2,ttf,eot,pdf,zip,tar,gz,mp3,mp4}]
charset = unset
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset.editorconfig aligns the defaults used by editors that support it when they save files.
The important settings are:
charset = utf-8: save text as UTF-8end_of_line = lf: use LF line endingsinsert_final_newline = true: add a final newlinetrim_trailing_whitespace = true: remove unnecessary trailing spaces
Binary files such as images and fonts must not receive text-file settings.
* text=auto eol=lfFor a narrower policy, use explicit file patterns:
*.json text eol=lf
*.md text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.css text eol=lfeol=lf tells Git to treat text files as LF when checking them out.
Adding .gitattributes does not immediately rewrite every existing file in the working tree. If existing files must be converted, review the diff size first and use a dedicated commit.
The behavior of common pwsh write commands varies by environment and version, especially for line endings and encoding.
Do not use the following without checking the result:
Set-Content path/to/file.md $content
Out-File path/to/file.mdFor partial edits to existing files, prefer apply_patch. If pwsh must write the file, explicitly use UTF-8 without a BOM and LF, then inspect the bytes and Git diff afterward.
git diff --check
git diff --numstat
git status --shortExample byte-level check for a new file:
$path = Resolve-Path '.\\walkthrough.md'
$bytes = [System.IO.File]::ReadAllBytes($path)
$hasBom = $bytes.Length -ge 3 -and
$bytes[0] -eq 0xEF -and
$bytes[1] -eq 0xBB -and
$bytes[2] -eq 0xBF
$hasCr = $bytes -contains 0x0D
Write-Output "BOM=$hasBom CR=$hasCr"For a new LF file, the expected result is:
BOM=False CR=False
Run this before declaring a change complete:
git diff --checkNo output and exit code 0 indicate that the normal trailing-whitespace check passed.
Do not mark the change complete if you see output such as:
file.md:12: trailing whitespace.
If almost every newly added line becomes trailing whitespace immediately after saving with pwsh, check for these causes:
- Git is treating the CR in CRLF as trailing whitespace
- The file already contains mixed encoding or line endings
- The save operation rewrote the entire file
Inspect the bytes and git diff before writing again.
For a small edit to an existing file, use this order:
- Check the working tree with
git status --short - Check the file's current encoding and line endings
- Edit only the required lines
- Check the change size with
git diff --stat - Run
git diff --check - Stop if an unintended full-file diff appears
If line-ending normalization itself is the goal, separate it from the feature change:
Commit 1: chore: normalize text file line endings
Commit 2: feat: implement the actual feature change
This makes it possible to review line-ending changes separately from logic changes.
Perform a full conversion only when all of the following are true:
- The target file set is clearly defined
- Generated files and binaries can be excluded
- The diff can be verified to contain only line-ending changes
- The dedicated commit can be reviewed by the team or maintainer
- CI and the main test suite can be run again
After a full conversion, run at least:
git diff --check
git diff --stat
git diff --numstat
npm test
npm run typecheck
npm run buildIf existing files contain CP932 or unusual line endings, do not force an automatic conversion. First narrow the file set and identify the encoding.
Before reporting a change as complete, verify the following:
- New text files use UTF-8 without a BOM
- New and edited files use LF
- CRLF and LF are not mixed in the same file
- Unrelated existing files were not rewritten
- The
.editorconfigand.gitattributespolicies were followed -
git diff --checksucceeds - The size of the change is expected according to
git diff --stat - Required tests and builds were run
- Line-ending changes and feature changes are in separate commits
On Windows, do not rely on editor settings alone for line endings.
AGENTS.md Rules for people and agents
.editorconfig Editor save settings
.gitattributes Git text-file handling
git diff --check The pre-completion check
These four layers, combined with dedicated commits for full-file normalization, are the safest long-term way to prevent CRLF / LF mixing.