改行(line ending)とは? 改行文字の解説
改行とは、ファイル内のテキスト行の終わりを示す、不可視の文字(または複数の文字)です。
テキストファイルの各行は、特別な不可視の文字で終わります。どの文字か - あるいは複数の文字か - はオペレーティングシステムによって異なり、そのWindowsとUnixの食い違いは、CIの頭痛の種の絶えざる原因です。謎めいて失敗するスクリプト、すべての行が変更されたと表示されるdiff、はぐれたキャリッジリターンに詰まるツールです。
改行とは何か
改行は、ある行がどこで止まり、次がどこで始まるかをプログラムに伝える制御文字です。画面上では不可視ですが、ファイル内の実際のバイトです。関係する2つの文字はライン フィードとキャリッジ リターンで、プラットフォームはそれらを異なるやり方で組み合わせます。
LF、CR、CRLF
Unix、Linux、macOSは単一のライン フィード(LF)を使います。Windowsはキャリッジ リターンに続くライン フィード(CRLF)を使います。古いMacのシステムは単独のキャリッジ リターン(CR)を使っていました。したがって同じテキストファイルでも、どのプラットフォームが書いたかによってバイトが異なります。
混在した改行が問題を起こす理由
Windowsで書かれたファイルがUnixのrunnerで実行されると、末尾のキャリッジ リターンが各行の一部になります。すると、shellスクリプトはインタープリタのパスに不可視のCRが付いたものを見て失敗します。diffは膨れ上がり、見えない文字のせいで文字列比較が食い違います。
CIにおける改行
クロスプラットフォームなCIこそ、これが最も痛手を与えるところです。Gitは.gitattributesファイルを介してチェックアウト時に改行を正規化でき、これが最もきれいな修正です。jobの中でキャリッジ リターンを取り除くこともできますが、すべてのスクリプトにパッチを当てるより、大元で正規化する方が信頼できます。
# .gitattributes to normalize line endings for CI
* text=auto
*.sh text eol=lf
*.bat text eol=crlfLatchkeyについての注記
LatchkeyはLinux、Windows、macOSのrunnerを提供するため、同じリポジトリが異なるプラットフォームでチェックアウトされることがあります。コミットされた.gitattributesがあれば、どのrunnerのOSがjobを拾おうと、改行を一貫して保てます。
重要なポイント
- 改行は、テキスト行の終わりを示す不可視の文字です。
- UnixはLF、WindowsはCRLF、古いMacはCRを使っていたため、ファイルはプラットフォームによって異なります。
- 混在した改行は、クロスプラットフォームなCIでスクリプトとdiffを壊します - .gitattributesで正規化します。