PrettierとGitで改行コードを統一:EOLトラブルシューティング

2025-06-06

Prettierにおける「End of Line」とは?

Prettierにおける「End of Line」(略してEOL)とは、ファイルの各行の末尾をどのように表現するかを指します。これは、オペレーティングシステム(OS)によって行末の記号が異なることに由来する問題であり、Prettierがコードのフォーマットを統一する上で重要な設定項目の一つです。

OSごとの行末表現の違い

  • CR (Carriage Return): \r で表現されます。非常に稀で、古いmacOSなどで使われていましたが、現在はほとんど見られません。
  • CRLF (Carriage Return + Line Feed): \r\n で表現されます。主にWindows OSで使われます。
  • LF (Line Feed): \n で表現されます。主にUnix系OS(macOS, Linuxなど)で使われます。

これらの違いがあると、例えばWindowsで作成されたコードをLinuxで開いた際に、行末の記号が意図せず表示されたり、Gitなどのバージョン管理システムで差分が余計に発生したりする問題が起こります。

Prettierが「End of Line」を扱う理由

Prettierは、どんな環境で開発されたコードであっても、最終的に同じフォーマットになることを目指しています。そのため、行末の記号も統一することで、以下のようなメリットがあります。

  1. 一貫性の確保: 開発チーム内で異なるOSを使っている場合でも、コードの行末表現が統一され、どこで開いても同じ見た目になります。
  2. Gitの差分問題の解消: Gitでコードを管理する際、行末の違いによって不必要な差分("whitespace changes")が表示されるのを防ぎ、純粋なコードの変更点のみに集中できます。
  3. エディタやツールの互換性: 特定の行末記号に依存するエディタやツールとの互換性が向上します。

PrettierのendOfLine設定

Prettierは、endOfLineという設定オプションを提供しており、これによりどの行末記号を使用するかを明示的に指定できます。

設定可能な値は以下の通りです。

  • "preserve": 既存の行末記号を維持します。基本的にはフォーマットしないという意味合いが強いです。
  • "auto": 既存の行末記号を推測し、それに基づいてフォーマットします。ファイルにLFとCRLFが混在している場合、最初の行の行末を基準にします。
  • "crlf": 強制的にCRLF (\r\n) に統一します。Windows OSでの一般的な設定です。
  • "lf": 強制的にLF (\n) に統一します。Unix系OSでの一般的な設定です。

推奨される設定

ほとんどの現代的な開発環境では、"lf"を使用することが推奨されています。これは、Gitがデフォルトで行末をLFに変換する(core.autocrlf設定がtrueの場合)ことや、ウェブ開発の多くのツールがUnix系の環境を前提としているためです。



Prettier の「End of Line」に関する一般的なエラーとトラブルシューティング

Prettier の「End of Line」(EOL)設定は、異なるOS間でコードを共有する際に特に問題を引き起こしやすい部分です。ここでは、よくあるエラーとその解決策について説明します。

よくあるエラー

    • 現象: ESLint (特に eslint-plugin-prettier と連携している場合) やVS Codeなどのエディタで、各行の末尾に「CR を削除してください」といった警告やエラーが表示される。
    • 原因: Windowsで作成されたファイルがCRLF(\r\n)の行末を使用しているにもかかわらず、PrettierやESLintの設定がLF(\n)を期待している場合に発生します。または、その逆のパターン(LFのファイルをCRLFとして扱おうとしている)も考えられます。
    • なぜ問題になるか: Gitで管理しているリポジトリにCRLFのファイルが混ざると、他のOSを使っている開発者がプルした際に、行末の違いだけで大量の差分が表示され、マージの際に不必要なコンフリクトが発生する原因となります。
  1. Prettier が行末を自動的に変換しない

    • 現象: .prettierrcendOfLine: "lf" のように設定しているにもかかわらず、既存のCRLFのファイルを開いてフォーマットしても、行末がLFに変換されない。
    • 原因: Prettier の設定が正しく適用されていない、またはGitの設定がPrettierの動作を上書きしている可能性があります。特に、VS Code などのエディタの「Format on Save」機能とGitの自動変換設定が絡み合っている場合によく起こります。
  2. Git の差分で不必要な変更が表示される

    • 現象: ファイルの内容を変更していないのに、git diff を実行すると行末の違いだけが大量に表示される。
    • 原因: 開発チーム内で異なるOSを使用しており、各メンバーのGitの core.autocrlf 設定が統一されていないか、または .gitattributes ファイルが行末の扱いを明示的に指定していないため。

トラブルシューティング

これらの問題に対処するためには、Prettier、エディタ、Git の3つの設定を連携させる必要があります。

Prettier の設定を確認・修正する

  • .prettierrc ファイルで endOfLine を設定する
    プロジェクトのルートにある .prettierrc(または prettier.config.js など)ファイルで、endOfLine オプションを明示的に設定します。

    // .prettierrc
    {
      "singleQuote": true,
      "trailingComma": "all",
      "printWidth": 80,
      "endOfLine": "lf" // または "crlf"
    }
    
    • 推奨: ほとんどのWebプロジェクトや現代的な開発環境では、"lf" が推奨されます。
    • Windows環境の場合: チーム全員がWindowsを使用している、またはGitの自動変換を完全に避けたい場合は、"crlf" も選択肢に入ります。しかし、異なるOSのメンバーが参加する可能性がある場合は "lf" に統一し、Gitで変換させるのが一般的です。
    • "auto" は、既存のファイルから行末を推測するため、一貫性を保つ上ではあまり推奨されません。新しいファイルはOSのデフォルト行末で作成され、古いファイルは元の行末が維持されるため、混在する原因になります。

エディタ(特にVS Code)の設定を統一する

Prettier がファイル保存時に自動的にフォーマットされるように設定していても、エディタ自体の行末設定が異なる場合、問題が発生することがあります。

  • VS Code の場合:
    • ワークスペース設定 (.vscode/settings.json): プロジェクト固有の設定として、files.eol を設定します。

      // .vscode/settings.json
      {
        "files.eol": "\n", // LF を使用する場合
        // "files.eol": "\r\n" // CRLF を使用する場合
      }
      

      この設定は、そのワークスペースで作成される新しいファイルの行末を制御します。

    • 既存ファイルの行末を変換する: VS Code の右下にあるステータスバーで、現在のファイルの行末(LF/CRLF)が表示されます。ここをクリックして、LF または CRLF に手動で変換できます。この作業は既存のすべてのファイルに対して行う必要があります。

    • デフォルトフォーマッタの設定: editor.defaultFormatteresbenp.prettier-vscode に設定し、editor.formatOnSavetrue に設定していることを確認します。

Git の設定を適切に行う

Git は、異なるOS間でファイルを行き来させる際に、行末の自動変換を行う機能を持っています。これが Prettier やエディタの設定と齟齬をきたすと問題になります。

  • .gitattributes ファイルの利用(推奨): プロジェクトのルートに .gitattributes ファイルを作成し、リポジトリ全体で行末の扱いを明示的に指定することが最も強力で推奨される方法です。これは、チームメンバーの core.autocrlf 設定に依存せずに、一貫性を保つことができます。

    # .gitattributes
    * text=auto eol=lf
    
    • * text=auto: すべてのテキストファイルに対してGitの自動行末検出を有効にします。
    • eol=lf: テキストファイルの行末をLFに正規化します。これにより、Windowsユーザーがコミットする際にも、Gitが自動的にLFに変換してくれます。

    .gitattributes を変更した場合は、既存のファイルを一度全てLFに変換し直す必要がある場合があります。これは、以下のコマンドで実行できます(Gitのワーキングツリーをクリーンな状態にしてから実行してください)。

    git rm --cached -r .
    git reset --hard
    

    または、手動で全てのファイルをLFに変換するスクリプトを実行することもできます。

  • core.autocrlf の設定: これはGitのグローバル設定であり、すべてのリポジトリに影響します。

    • Windowsユーザー: git config --global core.autocrlf true (チェックアウト時にCRLFに変換、コミット時にLFに変換) Gitが自動的にCRLFに変換してくれるため、Windowsでコードを編集しても、LFでコミットされるようになります。
    • macOS/Linuxユーザー: git config --global core.autocrlf input (コミット時にのみLFに変換、チェックアウト時は変換しない) これにより、LF以外の行末がコミットされるのを防ぎます。
    • 一貫性を強く求める場合: git config --global core.autocrlf false (自動変換を完全に無効にする) この場合、Gitは行末を一切変更しないため、Prettierやエディタの設定が完全に統一されている必要があります。

ESLint と Prettier の連携設定を確認する

eslint-plugin-prettier を使用している場合、ESLint のルールで prettier/prettier ルールに endOfLine オプションを渡すこともできます。

// .eslintrc.js
module.exports = {
  // ...その他の設定
  rules: {
    'prettier/prettier': [
      'error',
      {
        endOfLine: 'lf', // Prettierの設定と合わせる
      },
    ],
    'linebreak-style': ['error', 'unix'], // ESLint自体の行末ルールもLFに合わせる('windows'も選択肢)
  },
};
  1. プロジェクト全体で endOfLine: "lf" を採用する.prettierrc にこれを設定します。
  2. .gitattributes ファイルを配置する:プロジェクトのルートに * text=auto eol=lf を含む .gitattributes ファイルを作成します。これにより、すべてのGitユーザーに対して行末がLFに統一されます。
  3. 既存ファイルの行末をクリーンアップする:もし既にCRLFのファイルが混在している場合は、git rm --cached -r .git reset --hard を実行して、リポジトリの行末をクリーンな状態にすることをお勧めします。
  4. エディタの設定を統一する:VS Codeを使用している場合は、ワークスペースの settings.jsonfiles.eol: "\n" を設定します。
  5. ESLint の設定を確認するlinebreak-style ルールも 'unix' に設定し、Prettier の endOfLine と整合性を保ちます。


Prettierにおける「End of Line」の設定例

Prettier の endOfLine オプションは、コードの行末記号を統一するために使用されます。この設定は、主に .prettierrc ファイル(または package.jsonprettier フィールドなど)で定義します。

.prettierrc ファイルでの設定

最も一般的な方法は、プロジェクトのルートディレクトリに .prettierrc ファイルを作成し、JSON形式で設定を記述することです。

例1: 行末をLF (\n) に統一する (推奨)

// .prettierrc
{
  "singleQuote": true,
  "semi": false,
  "tabWidth": 2,
  "printWidth": 80,
  "endOfLine": "lf" // 行末をLFに統一
}
  • 説明: この設定は、すべてのテキストファイルの行末をLF(Line Feed、\n)に統一します。これは、macOSやLinuxなどのUnix系OSで一般的に使用される行末記号であり、現代のWeb開発やGitリポジトリで最も推奨される設定です。

例2: 行末をCRLF (\r\n) に統一する

// .prettierrc
{
  "singleQuote": true,
  "semi": false,
  "tabWidth": 2,
  "printWidth": 80,
  "endOfLine": "crlf" // 行末をCRLFに統一
}
  • 説明: この設定は、すべてのテキストファイルの行末をCRLF(Carriage Return + Line Feed、\r\n)に統一します。これはWindows OSで伝統的に使用される行末記号です。チーム全体がWindows環境で開発している場合や、特定のレガシーシステムとの互換性が必要な場合に選択されることがあります。

例3: 行末を自動検出 ("auto") にする

// .prettierrc
{
  "singleQuote": true,
  "semi": false,
  "tabWidth": 2,
  "printWidth": 80,
  "endOfLine": "auto" // 既存の行末記号を推測
}
  • 注意点: 既存のファイル間でLFとCRLFが混在している場合に、その混在が維持される可能性があります。また、新しいファイルはOSのデフォルトに従うため、チーム内でOSが異なる場合に一貫性が失われることがあります。そのため、明示的に "lf" または "crlf" を指定することが推奨されます。
  • 説明: auto は、既存のファイルに含まれる最初の行の行末記号を検出し、それに基づいてフォーマットします。新しいファイルについては、使用しているOSのデフォルトの行末記号を使用します。

例4: 行末を維持 ("preserve") する

// .prettierrc
{
  "singleQuote": true,
  "semi": false,
  "tabWidth": 2,
  "printWidth": 80,
  "endOfLine": "preserve" // 既存の行末記号を維持
}
  • 説明: preserve は、Prettier が行末記号の変更をしないことを意味します。これは、Prettierによる行末の自動修正を完全に無効にしたい場合にのみ使用します。

package.json での設定

.prettierrc ファイルの代わりに、package.jsonprettier フィールドに直接設定を記述することも可能です。

// package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "prettier": {
    "singleQuote": true,
    "semi": false,
    "tabWidth": 2,
    "printWidth": 80,
    "endOfLine": "lf"
  },
  "scripts": {
    "format": "prettier --write ."
  },
  "devDependencies": {
    "prettier": "^3.0.0"
  }
}

Prettier の endOfLine 設定と合わせて、Git の end of line 変換設定を .gitattributes ファイルで明示的に指定することが非常に重要です。これにより、OSや個々のGit設定に依存せず、リポジトリ内の行末を統一できます。

例: すべてのテキストファイルをLFに統一する

プロジェクトのルートに .gitattributes ファイルを作成し、以下を記述します。

# .gitattributes
# テキストファイルを自動的に認識し、行末をLFに統一する
* text=auto eol=lf
  • 重要性: WindowsユーザーがCRLFのファイルを作成しても、この設定があればGitがコミット時に自動的にLFに変換してくれます。これにより、Mac/Linuxユーザーとの間でGitの差分で行末の問題が発生するのを防ぎます。
  • 説明:
    • * text=auto: すべてのファイルに対して、Gitがテキストファイルかどうかを自動的に判断します。テキストファイルと判断された場合、行末の変換対象となります。
    • eol=lf: Gitがリポジトリにコミットする際に、行末をLF (\n) に正規化するように指示します。

Prettier の endOfLine 設定は、コードのフォーマットを統一し、異なるOS間での開発における行末の問題を解消するために不可欠です。

  • 推奨されるアプローチ:
    1. .prettierrcendOfLine: "lf" を設定する。
    2. .gitattributes ファイルで * text=auto eol=lf を設定し、GitレベルでLFへの統一を強制する。


Prettier の「End of Line」に関する代替管理方法

Prettier はコードフォーマットの一環としてEOLを自動的に管理してくれますが、Prettierを使用しない場合や、PrettierのEOL管理が何らかの理由で不十分な場合に、EOLを制御するための代替手段がいくつか存在します。これらは主に、エディタ、バージョン管理システム(Git)、そして個別のツールに依存します。

エディタの設定によるEOL管理

ほとんどのモダンなテキストエディタやIDEには、ファイルのEOLを制御する機能が組み込まれています。

  • Sublime Text, Atom など
    同様に、各エディタの設定やパッケージを通じてEOLを管理する機能が提供されています。

  • IntelliJ IDEA / WebStorm などのJetBrains IDEの例
    これらのIDEでも、「Editor」→「Code Style」→「Line Separators」などの設定で、プロジェクト全体のEOLを統一できます。また、個々のファイルに対して右クリックメニューなどからEOLを変換する機能も提供されています。

  • VS Code (Visual Studio Code) の例
    VS Codeでは、ワークスペース設定(.vscode/settings.json)またはユーザー設定で、新しく作成されるファイルのEOLや、既存ファイルのEOLの扱いを設定できます。

    // .vscode/settings.json (プロジェクトごとの設定)
    {
      "files.eol": "\n" // 新しいファイルはLF(Line Feed)で作成
      // または "\r\n" でCRLF(Carriage Return + Line Feed)
    }
    
    • 既存ファイルの変換: VS Codeのステータスバー(右下)には、現在開いているファイルのEOLが表示されます(例:「LF」または「CRLF」)。ここをクリックすると、そのファイルのEOLをLFまたはCRLFに手動で変換することができます。
    • 「Format on Save」と連携: Prettierを拡張機能として導入している場合、editor.formatOnSavetrue に設定しておけば、Prettierの設定に従ってEOLも自動的に変換されます。Prettierが設定されていない場合でも、files.eol の設定が新しいファイルに適用されます。

メリット

  • プロジェクト単位でEOLを設定できるため、チーム内での一貫性を保ちやすい。
  • 開発者がコードを記述する際に、エディタが自動的に正しいEOLを適用してくれる。

デメリット

  • 既存のファイルが異なるEOLを持っている場合、手動での変換作業が必要になることがある。
  • 開発者全員が同じエディタを使い、同じ設定を適用していることを保証する必要がある。

Git の設定によるEOL管理 (.gitattributes)

Gitは、バージョン管理システムとして、異なるOS間でのEOLの違いを吸収するための強力なメカニズムを提供しています。特に .gitattributes ファイルは、Prettierを使わない場合でもEOLを統一するための最も推奨される方法の一つです。

  • core.autocrlf 設定 (Gitのグローバル設定)
    これは個々の開発者のGitクライアントの設定ですが、EOLの問題を避けるために適切な設定を推奨します。

    • Windowsユーザーの場合
      git config --global core.autocrlf true (チェックアウト時にCRLFに変換、コミット時にLFに変換)
    • macOS/Linuxユーザーの場合
      git config --global core.autocrlf input (コミット時にのみLFに変換、チェックアウト時は変換しない)
  • .gitattributes ファイルの例
    プロジェクトのルートディレクトリに .gitattributes という名前のファイルを作成し、以下のように記述します。

    # .gitattributes
    # すべてのテキストファイルの行末をLFに正規化する
    * text=auto eol=lf
    
    # バイナリファイルは行末変換しない(例:画像ファイルなど)
    *.png binary
    *.jpg binary
    
    • * text=auto eol=lf: これが最も重要な設定です。
      • *: すべてのファイルに適用。
      • text=auto: Gitがファイルをテキストファイルと判断した場合に、EOL変換の対象とします。
      • eol=lf: Gitがリポジトリにコミットする際、ファイルのEOLをLF (\n) に正規化します。そして、ユーザーがリポジトリからチェックアウトする際、そのユーザーの core.autocrlf 設定に基づいて適切なEOLに変換されるようになります。

メリット

  • チームメンバーの環境に依存せず、一貫したEOLを保証できる。
  • Gitの差分がEOLの違いによって汚染されるのを防ぎ、純粋なコード変更のみに集中できる。
  • バージョン管理システムレベルでEOLが強制されるため、開発者のOSやエディタの設定に依存しない。

デメリット

  • バイナリファイルを誤って text=auto に含めないよう注意が必要。
  • .gitattributes を変更した場合、既存のファイルに対して一度 git rm --cached -r .git reset --hard を実行して、リポジトリをクリーンな状態にする必要がある場合がある。

JavaScript/TypeScript のプロジェクトでは、ESLint を使用してコードスタイルを強制できます。ESLintには、行末のスタイルをチェックする linebreak-style ルールがあります。

メリット

  • Prettierと併用しない場合に、EOLの統一を強制する手段として有効。
  • コードのリンティング時にEOLの問題を検出し、開発者に警告またはエラーとして通知できる。

デメリット

  • ESLintが実行されるJavaScript/TypeScriptファイルに限定される。
  • フォーマットツールではないため、自動的にEOLを修正する機能は持たない(一部のエディタのESLint拡張機能は修正できる場合もある)。
  • Pre-commit フック (Huskyなどと連携)
    Gitのpre-commitフックを使用して、コミット前にファイルのEOLをチェックし、必要に応じて修正するスクリプトを実行できます。lint-staged のようなツールと組み合わせることで、ステージングされたファイルのみに処理を適用できます。

  • dos2unix / unix2dos コマンドラインツール
    これらのツールは、特定のファイルをLFからCRLF、またはCRLFからLFへ一括変換するために使用できます。CI/CDパイプラインやPre-commitフックなどでスクリプトとして利用することも可能です。

    dos2unix your_file.js # CRLFをLFに変換
    unix2dos your_file.js # LFをCRLFに変換
    

Prettierの endOfLine 設定は、EOL管理を非常にシンプルにしてくれますが、代替手段としては以下の組み合わせが強力です。

  1. 最も推奨される方法: Gitの .gitattributes ファイル を使用して、リポジトリ全体でEOLを統一する。これは、どのOSやエディタを使用しているかに関わらず、最も堅牢な方法です。
  2. 補助的な方法:
    • 開発者のエディタ設定で、新しいファイルのEOLを統一する。
    • ESLintの linebreak-style ルールで、JavaScript/TypeScriptファイルのEOLをチェックする。