web-dev-qa-db-ja.com

異なるオペレーティングシステム間のgit core.autocrlfでの行末変換の動作

スタックオーバーフローに関するさまざまな質問と回答、およびcore.autocrlf設定の方法に関するgitドキュメントを読みました。動作します。

これは私が読んだものからの私の理解です:

UnixおよびMac OSX(OSX以前はCRを使用)クライアントはLF行末記号を使用します。
WindowsクライアントはCRLF行末記号を使用します。

クライアントでcore.autocrlfがtrueに設定されている場合、gitリポジトリは常にファイルをLF行末形式で保存し、クライアント上のファイルの行末はクライアントのチェックアウト/コミット時に前後に変換されます(すなわち、Windows)クライアントでの行末ファイルの形式に関係なく、非LF行末を使用します(これはTim Clemの定義と一致しません-以下の更新を参照してください)。

これは、行末の変換動作がわからないところで疑問符を付けてcore.autocrlfの 'input'および 'false'設定について同じことを文書化しようとするマトリックスです。

私の質問は:

  1. 疑問符は何にすべきですか?
  2. この行列は「非疑問符」に対して正しいですか?

コンセンサスが形成されたように見えるので、回答から疑問符を更新します。

 core.autocrlf value 
 true input false 
 ---------------------------- ------------------------------ 
 commit |変換しますか? ?
 new | LF(LFに変換しますか?)(変換なし?)
 
 commit |に変換        ? 
は存在しません| LF(LFに変換しますか?)変換
 
チェックアウト|に変換        ? no 
 existing | CRLF(変換なし?)変換
 

さまざまな設定の長所と短所に関する意見を実際に探しているわけではありません。 gitが3つの設定のそれぞれでどのように動作するかを明確にするデータを探しています。

-

Update 04/17/2012Tim Clemによる記事 を読んでJJDがコメントにリンクしているので、「上記の表の「不明」値、および「クライアントへの変換ではなくCRLFに変換するための既存のチェックアウト| true」の変更。彼が提供する定義は次のとおりです。これは、私が他の場所で見たものよりも明確です。

core.autocrlf = false

これはデフォルトですが、ほとんどの人はこれをすぐに変更することをお勧めします。 falseを使用した結果、Gitはファイルの行末を混乱させません。 LF、CRLF、CR、またはこれら3つのランダムな組み合わせでファイルをチェックインできますが、Gitは気にしません。これにより、差分の読み取りが難しくなり、マージが難しくなります。 Unix/Linuxの世界で働くほとんどの人は、CRLFの問題がなく、ファイルがオブジェクトデータベースに書き込まれたり作業ディレクトリに書き込まれたりするたびにGitが余分な作業をする必要がないため、この値を使用します。

core.autocrlf = true

これは、Gitがすべてのテキストファイルを処理し、そのファイルをオブジェクトデータベースに書き込むときにCRLFがLFに置き換えられ、ファイルに書き込むときにすべてのLFをCRLFに戻すことを意味する作業ディレクトリ。これは、作業ディレクトリにCRLFを保持しながら、リポジトリを他のプラットフォームで使用できるようにするため、Windowsで推奨される設定です。

core.autocrlf = input

これは、Gitがすべてのテキストファイルを処理し、そのファイルをオブジェクトデータベースに書き込むときにCRLFがLFに置き換えられることを意味します。ただし、逆は行いません。オブジェクトデータベースからファイルを読み戻し、作業ディレクトリに書き込むと、行の終わりを示すLFがまだあります。この設定は通常、Unix/Linux/OS Xで使用され、CRLFがリポジトリに書き込まれないようにします。 Webブラウザーからコードを貼り付けて、誤ってCRLFをファイルの1つに入れてしまった場合、Gitはオブジェクトデータベースに書き込んだときにそれらがLFに置き換えられることを確認します。

ティムの記事は素晴らしいです。私が考えていないことは、リポジトリがLF形式であると仮定していることだけです。これは、特にWindowsのみのプロジェクトでは必ずしも当てはまりません。

Timの記事とjmlaneのこれまでで最も投票数の多い回答を比較すると、true設定と入力設定について完全に一致し、false設定について不一致が示されています。

200
Michael Maddox

core.autocrlfの動作の最良の説明は、 gitattributes manページのtext属性セクションにあります。

これは、core.autocrlfが現在どのように動作するように見えるかです(少なくとも、私の知る限りv1.7.2以降)。

  • core.autocrlf = true
    1. リポジトリからチェックアウトされたLF文字のみを含むテキストファイルは、作業ツリーでCRLFに正規化されます。リポジトリにCRLFを含むファイルは変更されません
    2. リポジトリ内にLF文字のみを含むテキストファイルは、リポジトリにコミットされたときにCRLFからLFに正規化されます。リポジトリにCRLFを含むファイルはそのままコミットされます。
  • core.autocrlf = input
    1. リポジトリからチェックアウトされたテキストファイルは、作業ツリーに元のEOL文字を保持します。
    2. 作業ツリー内のCRLF文字を含むテキストファイルは、リポジトリにコミットされたときにLFに正規化されます。
  • core.autocrlf = false
    1. core.eolは、作業ツリーのテキストファイル内のEOL文字を示します。
    2. core.eol = nativeはデフォルトで、つまり、Windows EOLはCRLFであり、* nix EOLはLF作業ツリーです。
    3. リポジトリgitattributes設定は、リポジトリへのコミットのEOL文字の正規化を決定します(デフォルトはLF文字への正規化です)。

私はこの問題を最近調査したばかりで、状況が非常に複雑であることがわかりました。 core.eol設定は、EOL文字がgitでどのように処理されるかを明確にするのに役立ちました。

119
jmlane

混合プラットフォームプロジェクトでのEOLの問題は、私の人生を長い間悲惨にしてきました。問題は通常、異なるEOLが混在したファイルが既に存在する場合に発生しますalreadyリポジトリにあります。この意味は:

  1. リポジトリには、異なるEOLを持つ異なるファイルがある場合があります
  2. リポジトリ内の一部のファイルには、EOLが混在している場合があります。同じファイル内のCRLFLFの組み合わせ。

これがどのように起こるかはここでは問題ではありませんが、実際には起こります。

さまざまなモードとそれらの組み合わせについて、Windowsでいくつかの変換テストを実行しました。
ここに私が得たものを少し修正した表で示します。

 | | 
の場合の変換結果|さまざまなファイルをコミットする| FROMリポジトリをチェックアウトEOLs INTO repo and |混合ファイルと
 | core.autocrlf値:| core.autocrlf値:
 ---------------------------------------- ---------------------------------------- 
ファイル|真|入力|偽|真|入力| false 
 -------------------------------------------- ------------------------------------ 
 Windows-CRLF | CRLF-> LF | CRLF-> LF |現状のまま|現状のまま|現状のまま|現状のまま
 Unix -LF |現状のまま|現状のまま|現状のまま| LF-> CRLF |現状のまま|現状のまま
 Mac -CR |現状のまま|現状のまま|現状のまま|現状のまま|現状のまま| as-is 
 Mixed-CRLF + LF |現状のまま|現状のまま|現状のまま|現状のまま|現状のまま| as-is 
 Mixed-CRLF + LF + CR |現状のまま|現状のまま|現状のまま|現状のまま|現状のまま|そのまま

ご覧のとおり、コミット時に変換が発生するのは2つのケースです(左の3列)。残りのケースでは、ファイルはそのままコミットされます。

チェックアウト時(右3列)に、次の場合に変換が発生するケースは1つだけです。

  1. core.autocrlftrue ---(および
  2. リポジトリ内のファイルにはLF EOLがあります。

私にとって最も驚いたのは、多くのEOL問題の原因は、CRLF + LFのような混合EOLが正規化される構成がないことです。

また、CRの「古い」Mac EOLも変換されないことに注意してください。
これは、誤って記述されたEOL変換スクリプトが、CRLFsをLFsに変換するだけで、LFs + CRLFsの混合終了ファイルを変換しようとする場合、その後、CRCRLFに変換された場所で、ファイルを「孤独な」CRCRLFsとの混合モードのままにします。
Gitはtrueモードであっても何も変換せず、EOLの大混乱が続きます。一部のエディターやコンパイラー(例:VS2010)はMac EOLを好まないため、これは実際に私に起こり、私のファイルを本当にひどく混乱させました。

これらの問題を実際に処理する唯一の方法は、時折inputまたはfalseモードですべてのファイルをチェックアウトし、適切な正規化を実行してリポジトリ全体を正規化し、 -変更されたファイルのコミット(ある場合)。 Windowsでは、おそらくcore.autocrlf trueの処理を再開します。

57
Adi Shavit

近日リリースのGit 1.7.2 で、「eol変換」の面で物事が変更されようとしています

新しい構成設定 core.eolが追加/進化しています

これは、現在pu(私のシリーズの最後のもの)にある「Add "core.eol" config variable」コミットの代わりになります。
core.autocrlf=true」が「* text=auto」の代わりであることを暗示する代わりに、autocrlfが作業ディレクトリでCRLFを使用したいユーザーだけのためであるという事実を明示しますテキストファイルの正規化がないリポジトリ
有効にすると、「core.eol」は無視されます。

新しい構成変数「core.eol」を導入します。これにより、ユーザーは、作業ディレクトリ内の行末正規化ファイルに使用する行末を設定できます。
デフォルトは「native」です。これは、WindowsではCRLF、それ以外ではLFを意味します。 「core.autocrlf」はcore.eolをオーバーライドすることに注意してください。
この意味は:

[core]
  autocrlf = true

core.eolが "lf"に設定されている場合でも、作業ディレクトリにCRLFを配置します。

core.eol:

textプロパティが設定されているファイルの作業ディレクトリで使用する行末タイプを設定します。
代替は「lf」、「crlf」、および「native」であり、プラットフォームのネイティブの行末を使用します。
デフォルト値はnativeです。


その他の進化 検討中

1.8の場合、core.autocrlfで正規化を有効にし、作業ディレクトリ行の終了決定をcore.eolに任せることを検討しますが、それはwill人々の設定を壊します。


git 2.8(2016年3月)は、core.autocrlfがeolに与える影響を改善します。

commit 817a0c7 (2016年2月23日)、 commit 6e336a5commit df747b8commit df747b8 (2016年2月10日)を参照、 コミットdf747b8コミットdf747b8 (2016年2月10日)、および コミット4b4024fコミットbb211b4commit 92cce1commit 320d39ccommit 4b4024fcommit bb211b4commit 92cce1コミット320d39c (2016年2月5日)by TorstenBögershausen(tboegi .
C浜野順夫-gitster- in commit c6b94eb 、2016年2月26日)

convert.c:リファクタリングcrlf_action

crlf_actionの決定と使用をリファクタリングします。
今日、ファイルに「crlf」属性が設定されていない場合、crlf_actionCRLF_GUESSに設定されます。代わりにCRLF_UNDEFINEDを使用し、前述のように「text」または「eol」を検索します。

古いCRLF_GUESSの使用法を置き換えます。

CRLF_GUESS && core.autocrlf=true -> CRLF_AUTO_CRLF
CRLF_GUESS && core.autocrlf=false -> CRLF_BINARY
CRLF_GUESS && core.autocrlf=input -> CRLF_AUTO_INPUT

以下を定義して、何が何であるかをより明確にします。

- CRLF_UNDEFINED : No attributes set. Temparally used, until core.autocrlf
                   and core.eol is evaluated and one of CRLF_BINARY,
                   CRLF_AUTO_INPUT or CRLF_AUTO_CRLF is selected
- CRLF_BINARY    : No processing of line endings.
- CRLF_TEXT      : attribute "text" is set, line endings are processed.
- CRLF_TEXT_INPUT: attribute "input" or "eol=lf" is set. This implies text.
- CRLF_TEXT_CRLF : attribute "eol=crlf" is set. This implies text.
- CRLF_AUTO      : attribute "auto" is set.
- CRLF_AUTO_INPUT: core.autocrlf=input (no attributes)
- CRLF_AUTO_CRLF : core.autocrlf=true  (no attributes)

torek を追加 コメント内

これらのすべての変換(eol=またはautocrlf設定からのEOL変換、および「clean」フィルター)は、ファイルがワークツリーからインデックスに移動するときに実行されます。 、git addの時間ではなく、git commitの間に。
(ただし、git commit -aまたは--onlyまたは--includeは、その時点でインデックスにファイルを追加することに注意してください。)

詳細については、「 autocrlfとeolの違い 」を参照してください。

38
VonC

core.autocrlf値はOSタイプに依存しませんが、Windowsのデフォルト値はtrueで、Linuxの場合はinputです。コミットおよびチェックアウトの場合に考えられる3つの値を調査しましたが、これが結果の表です。

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => LF   ║
║ git commit    ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => CRLF ║
║ git checkout  ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝
28
pratt

誰かを助けるために、これまでの私の理解はここにあります。

core.autocrlf=trueおよびcore.safecrlf = true

すべての行末が同じリポジトリがありますが、異なるプラットフォームで作業しています。 Gitは、行末がプラットフォームのデフォルトに確実に変換されるようにします。なぜこれが重要なのですか?新しいファイルを作成するとします。プラットフォームのテキストエディタは、デフォルトの行末を使用します。チェックインするときに、core.autocrlfをtrueに設定していない場合、デフォルトのプラットフォームでは別の行末に設定されているため、行末の不整合が発生しています。 crlf操作は可逆的であることを知りたいため、safecrlfも常に設定します。これらの2つの設定では、gitはファイルを変更していますが、変更が元に戻せることを確認しています

core.autocrlf=false

すでに行末が混在しているリポジトリがチェックインされていて、間違った行末を修正すると他のことが壊れる可能性があります。この場合、行末を変換するようにgitに指示しないことが最善です。これは、解決するように設計された問題を悪化させるためです。diffを読みやすくし、痛みを軽減します。この設定では、gitはファイルを変更しません

core.autocrlf=input

この理由は、デフォルトでLF行終端になっているプラ​​ットフォームでCRLF行終端を持つファイルを作成したユースケースをカバーするためであるため、これを使用しません。代わりに、テキストエディターで常にプラットフォームの行末のデフォルトで新しいファイルを保存することをお勧めします。

6
Carl

いいえ、@ jmlaneの答えは間違っています。

Checkin (git add, git commit)の場合:

  1. textプロパティがSet, Set value to 'auto'の場合、ファイルが 'CRLF'でコミットされたときに変換が行われます
  2. textプロパティがUnsetの場合、何も起こりません。Checkoutの場合はenen
  3. textプロパティがUnspecifiedの場合、変換はcore.autocrlf に依存します
    1. autocrlf = input or autocrlf = trueの場合、変換はリポジトリ内のファイルが 'LF'の場合にのみ行われ、 'CRLF'の場合は何も起こりません。
    2. autocrlf = falseの場合、何も起こりません

Checkoutの場合:

  1. textプロパティがUnsetの場合:何も起こりません。
  2. textプロパティがSet, Set value to 'autoの場合:core.autocrlfcore.eol。に依存します
    1. core.autocrlf = input:何も起こりません
    2. core.autocrlf = true:リポジトリ内のファイルが「LF」、「LF」->「CRLF」の場合にのみ変換が発生します
    3. core.autocrlf = false:変換は、リポジトリ内のファイルが「LF」、「LF」-> core.eolの場合にのみ行われます
  3. textプロパティがUnspecifiedの場合、core.autocrlf。に依存します
    1. 2.1と同じ
    2. 2.2と同じ
    3. なし、何も起こりません。textプロパティがUnspecifiedの場合、core.eolは無効です

デフォルトの動作

したがって、デフォルトの動作はtextプロパティはUnspecifiedおよびcore.autocrlf = falseです。

  1. チェックインの場合、何も起こりません
  2. チェックアウトの場合、何も起こりません

結論

  1. textプロパティが設定されている場合、チェックインの動作はautocrlfではなく、自身に依存します
  2. autocrlfまたはcore.eolはチェックアウト動作用であり、autocrlf> core.eol
2
ViciOs

LinuxとWindowsの両方でいくつかのテストを行いました。 LFで終わる行とCRLFで終わる行を含むテストファイルを使用します。
ファイルはコミットされ、削除され、チェックアウトされます。 core.autocrlfの値は、コミット前およびチェックアウト前に設定されます。結果は以下のとおりです。

commit core.autocrlf false, remove, checkout core.autocrlf false: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf input: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf true : LF=>LF   CRLF=>CRLF  
commit core.autocrlf input, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
commit core.autocrlf true, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf true, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf true,  remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
2
Luc Depoorter