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


220

Stack Overflowに関するさまざまな質問と回答、およびcore.autocrlf設定がどのように機能するかに関するgitのドキュメントを読みました

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

UnixおよびMac OSX(OSX以前のバージョンではCRを使用)クライアントはLF行末を使用します。
WindowsクライアントはCRLF行末を使用します。

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

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

私の質問は:

  1. 疑問符はどうあるべきですか?
  2. このマトリックスは「非疑問符」に対して正しいですか?

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

                       core.autocrlf値
            true入力false
-------------------------------------------------- --------
コミット| 変換しますか??
新しい| LFに変換(LFに変換?)(変換なし?)

コミット| に変換 ?番号
既存| LF(LFに変換?)変換

チェックアウト| に変換 ?番号
既存| CRLF(変換なし?)変換

私は実際にはさまざまな設定の長所と短所についての意見を探しているのではありません。私はgitが3つの設定のそれぞれで動作することを期待する方法を明確にするデータを探しています。

-

アップデート04/17/2012:コメントでJJDによってリンクされたTim Clemによる記事を読んだ後上記の表の「不明」値の一部の値を変更し、「既存のチェックアウト|変換してtrue」を変更しましたクライアントに変換する代わりにCRLFに変換します。」彼の定義は次のとおりです。これは、他のどこかで見たものよりも明確です。

core.autocrlf = false

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

core.autocrlf = true

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

core.autocrlf =入力

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

Timの記事はすばらしいです。欠けていると私が考えることができる唯一のことは、彼がリポジトリがLF形式であることを前提としていることです。

Timの記事をjmlaneがこれまでに最も投票された回答と比較すると、trueおよびinput設定については完全に一致しており、false設定については一致していません。


7
維持autocrlffalseにすることはそんなに簡単に思える;)stackoverflow.com/questions/2333424/...
VonC

@VonC:読んだので理解できたと思うが、必ずしも選択できるとは限らない。特定の方法で値を設定する必要がある人を制御していないgitリポジトリを使用しています。
マイケル・マドックス2010

5
WindowsもLFに正規化されていたらいいのではないでしょうか。Macは以前はCR(v10より前)でしたが、現在はLFに正規化されています。
Brett Ryan、

3
ティモシークレムのすばらしい記事へのリンクを追加する必要があります。マインドザエンドオブユアラインをすべてお読みください。
JJD 2012

1
シナリオ:私はLinux / Windowsの開発者です。私は両方のタイプの行末(IE。vim、eclipse)を認識できるテキストエディターのみを使用しています。末尾がLFのファイルを処理する必要がある(必要な)だけです。現在、グローバルgit構成でcore.autocrlf = inputを設定しています。私は行ってもいいですか?紛争は発生しますか?
クリス

回答:


128

動作の最良の説明はcore.autocrlfgitattributesの 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設定は、gitによるEOL文字の処理方法を明確にするのに役立ちました。


3
autocrlf = trueの場合、次のようにすべきではありませんか?リポジトリにCRLF EOL文字のみが含まれるテキストファイルは、リポジトリにコミットされるときにCRLFからLFに正規化されます。リポジトリにLFを含むファイルは、そのままコミットされます。
Piotr Lewandowski

2
私にとって、autocrlf = falseの場合でも、gitはEOLをCRLFに変換していました。この回答を読んだ後、私の.gitattributeファイルにtext = autoが設定されていることがわかりました。
irsis 2016年

1
の場合core.autocrlf = falsegitattributesファイルがない場合、正規化は行われません。それとも、デフォルトの正規化を使用するという意味ですか?
Chin

.gitattributesファイルはcore.autocrlf設定よりも優先されるべきではありませんか?
Qwerty

63

混合プラットフォームプロジェクトでのEOLの問題は、長い間私の人生を悲惨なものにしてきました。すでに別および混合たEOLを持つファイルがある場合の問題は通常発生し、すでにレポインチ この意味は:

  1. リポジトリには、異なるEOLの異なるファイルが含まれている可能性があります
  2. リポジトリ内の一部のファイルは、EOLが混在している場合があります。たとえば、同じファイルCRLFとの組み合わせLFです。

これがどのように発生するかは、ここでは問題ではありませんが、発生します。

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

                 | |の場合の結果の変換 結果として生じる変換
                 | さまざまなファイルのコミット| FROMリポジトリをチェックアウト-
                 | EOLs INTO repo and | その中に混合ファイルがあり、
                 | core.autocrlf値:| core.autocrlf値:           
-------------------------------------------------- ------------------------------
ファイル| 真| 入力| 誤り| 真| 入力| 偽
-------------------------------------------------- ------------------------------
Windows-CRLF | CRLF-> LF | CRLF-> LF | 現状のまま| 現状のまま| 現状のまま| そのまま
Unix -LF | 現状のまま| 現状のまま| 現状のまま| LF-> CRLF | 現状のまま| そのまま
Mac -CR | 現状のまま| 現状のまま| 現状のまま| 現状のまま| 現状のまま| そのまま
混合CRLF + LF | 現状のまま| 現状のまま| 現状のまま| 現状のまま| 現状のまま| そのまま
混合CRLF + LF + CR | 現状のまま| 現状のまま| 現状のまま| 現状のまま| 現状のまま| そのまま

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

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

  1. core.autocrlfでありtrue
  2. リポジトリ内のファイルにはLFEOL があります。

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

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

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


4
すばらしい答えですが、私が同意できない1つの文はWindowscore.autocrlf trueです。おそらくで作業を再開してください。私は個人的にはそれinputを常に使うべきだと信じています。
G.デメッキ2017年

39

次のGit 1.7.2で、「eol変換」の面で状況が変わります。

新しい構成設定core.eolが追加/展開されています:

これは、core.eol現在追加されている「追加 " "構成変数」コミットpu(私のシリーズの最後のコミット)に代わるものです。
代わりに「ことを意味しているの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です。


他の進化が考慮されています:

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


git 2.8(2016年3月)はcore.autocrlf、eol への影響を改善します。

参照817a0c7コミット、(2016年2月23日)を6e336a5コミットdf747b8コミットdf747b8コミット、(2016年2月10日)をdf747b8コミットdf747b8コミット(2016年2月10日に)、そして4b4024fコミットbb211b4コミット92cce13コミット320d39cコミット4b4024fコミットcommit bb211b4commit 92cce13commit 320d39c(2016年2月5日)、TorstenBögershausen(tboegi
(合併によりJunio C浜野- gitster-c6b94ebコミット、2016年2月26日)

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

の決定と使用法をリファクタリングしcrlf_actionます。
今日、crlfファイルに" "属性が設定されていない場合、crlf_actionはに設定され CRLF_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=またはからのEOL変換autocrlf、および " clean"フィルター)は、ファイルが作業ツリーからインデックス移動するときに、つまり、時間git addではなく実行中に実行されますgit commit
(ただし、そのときにインデックスにファイルを追加するgit commit -aか、--onlyまたは--include追加します。)

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


18
残念ながら、これは私には明快さを追加しません。現在の実装に問題があると彼らは言っているようで(それらの問題が何であるかは明らかではありません)、彼らはそれらの不特定の問題を解決するために複雑さを増しています。私の意見では、core.autocrlf設定はすでに過度に複雑で文書化されておらず、その状況は悪化しているようです。頭を上げてくれてありがとう。
マイケル・マドックス2010

1
これは満足できる解決策ではないようで、core.autocrlfと同じ問題があるようです。私の好みは、gitが自動的に何も変更しないことですが、間違った行末を追加またはコミットしたいユーザーに警告します。したがって、「git add」で「間違った」行末を追加できるようにするコマンドラインオプションが必要になります。(おそらくgit addはgit commitよりもこれを確認するのに適しています)
donquixote

これにより、それぞれのユーザーがエディター設定を変更し、実際に問題に対処することが強制されます。サードパーティからのファイル、またはすでにリポジトリにチェックインされているファイルの「間違った」行末を残すことができますが。
ドンキホーテ2014

@donquixote再び、同意します。しかしcore.eol、「自動的に変更」するのは、.gitattributesファイルで明示的に宣言したものだけです。これは異なっているcore.autocrlfに適用される任意のレポ内のファイル。これは宣言的なプロセスです。
VonC、2014

1
@donquixote:これはかなり古いと思いますが、今あなたのコメントを読んだだけです。実際、これらのすべての変換(eol =またはautocrlf設定からのEOL変換、および「クリーン」フィルター)は、ファイルが作業ツリーからインデックスに移動するときに、つまり時間git addではなく実行中に実行されますgit commit。(なお、git commit -aまたは--onlyあるいは--includeその時点でインデックスに追加ファイルを行う、しかしが。)それは何の価値については、あなたと私とLinus Torvalds氏は、すべてのVCSのアイデアを嫌い、これまでコミットされているものの変更します。しかし、これらすべてのWindowsユーザーがいます... :-)
torek

34

core.autocrlf値はOSタイプに依存しませんが、Windowsのデフォルト値はtrueLinuxの場合です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 ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝

5
短い要約:CR単独のファイルは変更されません。false行末に触れないでください。true常にコミットしLF、チェックアウトしCRLFます。そして、input常にコミットしてそのままLFチェックアウトします。
Furkan Kambay

7

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

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の行末が使用されているファイルを作成した使用例をカバーするためであるため、使用しません。代わりに、テキストエディターが常にプラットフォームの行末デフォルトで新しいファイルを保存するようにします。


3

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

の場合Checkin (git add, git commit)

  1. textプロパティがの場合Set, Set value to 'auto'、ファイルが 'CRLF'でコミットされたときに変換が行われます
  2. 場合textプロパティがあるUnset:何も起こりません、ためenenCheckout
  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. なし、何も起こりません。core.eolは、textプロパティがUnspecified

デフォルトの動作

だから、デフォルトの動作はありtext財産であるUnspecifiedcore.autocrlf = false

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

結論

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

2

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  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.