^ Mを無視するgit-diff


474

一部のファイルが改行区切り文字として^ Mを含むプロジェクト。git-diffはファイル全体が1行であると認識しているため、これらのファイルの比較は明らかに不可能です。

以前のバージョンとどのように違いますか?

「比較時に^ Mを改行として扱う」のようなオプションはありますか?

prompt> git-diff "HEAD^" -- MyFile.as 
diff --git a/myproject/MyFile.as b/myproject/MyFile.as
index be78321..a393ba3 100644
--- a/myproject/MyFile.cpp
+++ b/myproject/MyFile.cpp
@@ -1 +1 @@
-<U+FEFF>import flash.events.MouseEvent;^Mimport mx.controls.*;^Mimport mx.utils.Delegate
\ No newline at end of file
+<U+FEFF>import flash.events.MouseEvent;^Mimport mx.controls.*;^Mimport mx.utils.Delegate
\ No newline at end of file
prompt>

更新:

現在、最新の10のリビジョンをチェックアウトし、CRをLFに変換するRubyスクリプトを記述しています。

require 'fileutils'

if ARGV.size != 3
  puts "a git-path must be provided"
  puts "a filename must be provided"
  puts "a result-dir must be provided"
  puts "example:"
  puts "ruby gitcrdiff.rb project/dir1/dir2/dir3/ SomeFile.cpp tmp_somefile"
  exit(1)
end

gitpath = ARGV[0]
filename = ARGV[1]
resultdir = ARGV[2]

unless FileTest.exist?(".git")
  puts "this command must be run in the same dir as where .git resides"
  exit(1)
end

if FileTest.exist?(resultdir)
  puts "the result dir must not exist"
  exit(1)
end
FileUtils.mkdir(resultdir)

10.times do |i|
  revision = "^" * i
  cmd = "git show HEAD#{revision}:#{gitpath}#{filename} | tr '\\r' '\\n' > #{resultdir}/#{filename}_rev#{i}"
  puts cmd 
  system cmd
end

7
あなたがしたかったかもしれないgit diff -b-私はこれをstackoverflow.com/a/46265081/58794で
Jason Pyeron

6
Gitの2.16(Q1 2018年)で、あなたは持っていますgit diff --ignore-cr-at-eol以下の私の答えを参照しください。
VonC 2017年

7
@JasonPyeronと将来のGoogle社員向け:git diff -bと同じものを探す必要がありましたgit diff --ignore-space-change
Gogowitsch 2018

回答:


392

GitHubは、git-handled reposで改行文字として\ nのみを使用することを確認することを推奨しています。自動変換するオプションがあります:

$ git config --global core.autocrlf true

もちろん、これはcrlfをlfに変換すると言われていますが、crをlfに変換する必要があります。これがうまくいくことを願っています…

次に、ファイルを変換します。

# Remove everything from the index
$ git rm --cached -r .

# Re-add all the deleted files to the index
# You should get lots of messages like: "warning: CRLF will be replaced by LF in <file>."
$ git diff --cached --name-only -z | xargs -0 git add

# Commit
$ git commit -m "Fix CRLF"

core.autocrlfについては、manページで説明しています


1
いいえ、もちろん違います。いったん設定が行われると、コミット時に黙って変換されます。すべてが私が思う
とおりに

1
問題は、リポジトリにCRLFで終わるファイルがすでにあり、それ以外のファイルがあることです。Mac版を使っていても、Adobe FlashがCRLFを追加しているのではないかと思います。これらのファイルの古いリビジョンと比較する必要があります。これから始まる行末を変換しても、古いリビジョンの問題は解決されません:-/
neoneye 2009

65
ここでは、少なくとも投稿した例ではCRLFファイルを操作していません。これは古いスタイルのMacファイルです(EOLには\ rを使用するだけです)。そのため、差分が1行で表示されます。dos EOLを使用するファイルは、各行を個別に示し、末尾に^ Mを付けますgit config core.whitespace cr-at-eol
jamessan

12
私はこれを試していwarning: LF will be replaced by CRLFますがwarning: CRLF will be replaced by LF、の代わりに取得し続けており、Linuxを使用しています。なぜか?CRLFではなくLFで終わらせたい!
trusktr 2014

5
@trusktr、それは私にも同じことが起こりました。Linuxでは、誤ってCRLFを使用git config --global core.autocrlf inputして、を使用し、この回答の手順(rm、add、commit)を実行すると、が得られwarning: CRLF will be replaced by LF. The file will have its original line endings in your working directory.ます。ファイルを削除し(元のCRLFが間違っているため)、最後の「Fix CRLF」コミットから再度チェックアウトします。
jmmut 2015年

370

Windowsで開発しているときに、を使用しているときにこの問題に遭遇しましたgit tfs。私はこのようにそれを解決しました:

git config --global core.whitespace cr-at-eol

これは基本的に、行末CRがエラーではないことをGitに伝えます。その結果、これらの迷惑な^M文字git diffgit show、などの行末に表示されなくなりました。

他の設定はそのままにしているようです。たとえば、行の最後の余分なスペースは、diffでエラー(赤で強調表示)として表示されます。

(他の回答でもこれを暗示していますが、上記は設定の設定方法です。1つのプロジェクトのみに設定を設定するには、を省略し--globalます。)

編集

多くの行末の悲劇の後、私は.NETチームで作業するときに、次の設定で最高の幸運を手に入れました。

  • core.eol設定なし
  • core.whitespace設定なし
  • core.autocrlf設定なし
  • Windows用のGitインストーラーを実行すると、次の3つのオプションが表示されます。
    • Windowsスタイルのチェックアウト、Unixスタイルの行末のコミット <-これを選択
    • そのままチェックアウトし、Unixスタイルの行末をコミットする
    • そのままチェックアウト、そのままコミット

空白設定を使用する必要がある場合、TFSと対話する必要がある場合は、プロジェクトごとにのみ有効にする必要があります。省略してください--global

git config core.whitespace cr-at-eol

一部のcore。*設定を削除する必要がある場合、最も簡単な方法は次のコマンドを実行することです。

git config --global -e

これにより、グローバル.gitconfigファイルがテキストエディターで開き、削除する行を簡単に削除できます。(または、コメントの前に「#」を付けることができます。)


30
これを今見つけた人にとって、Windowsスタイルのチェックアウト、自動スタイル設定のUnixスタイルの行末core.autocrlftrue
K.カーペンター

14
この行git config --global core.whitespace cr-at-eolは、デフォルトである他の設定をオフにすることに注意してください。デフォルトには、blank-at-eol、blank-at-eof、space-before-tabの3つがあります。したがって、使用する必要がある他のものを維持しながらcr-at-eolを有効にするにはgit config --global core.whitespace blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol
Zitrax 2016

2
私のプロジェクトのために(これは、Windows上でチェックアウトして、私は、Linux上でそれを見てる)、cr-at-eol処分した^Mの行の末尾にgit diff行末が唯一の違いはあったが、すべての権利が、GITはまだ異なるとしてこれらの行を示しました。
ジャニスElmeris

SourceInsightは^ M文字をプッシュし続けますが、gitは依然として行末で違いを示しています。@Zitraxのコマンドは私のケースに対する正しい答えです。gitdiffは素晴らしいクリーンな出力を表示します。
LêクアンDuyと

3
gitにはもう少し複雑さが必要で、行末の設定がいくつか競合しています。私はgitが私の空白についてもっと心配すべきだと思います。たとえば、Windows(Linuxではない)マシンでMacの行末を検出した場合、無関係な致命的なエラーをスローし、リポジトリを破損した状態のままにします。私はそれがビジネスであることに気がつくVCSを使う理由を私が意味し、私が欲しい行末を使用させてくれるのですか?私は彼らが試みているのを見ますが、存在しない問題を解決するために、行末の動作をさらに6ダース投入する必要があります。彼らはほとんどそこにいます!がんばり続ける。
Rolf

125

試してみてくださいgit diff --ignore-space-at-eol、またはgit diff --ignore-space-change、またはgit diff --ignore-all-space


22
改行を識別する文字には実際には影響しません。
nes1983

4
「-w」も試してみましたが、運が悪く、それでも1行として扱います。次のプロジェクトでは、ソースコードにCRを決して入れないことを覚えておく必要があります。
neoneye 2009

3
git config --global core.autocrlf trueを覚えているか、デフォルトになるまでgitユーザーにバグを報告してください:)
nes1983

10
これにより、autocrlf設定を変更せずに問題が解決しました。ありがとう!
nneonneo 2013

11
これらのフラグは私には効果がありません... ^ Mを差分として表示します
Magnus

103

こちらもご覧ください:

core.whitespace = cr-at-eol

または同等に、

[core]
    whitespace = cr-at-eol

ここでwhitespaceタブ文字が前に付きます


4
うん、これによりgit diffツール(でも使用されますgit show^Mが変更された行のsに関するバグを解消しました!:)
ライク

2
何らかの理由で、これは私にとってうまくいきませんでした。=と=記号なしの両方で試してみました。 git diff^ M文字は引き続き表示されます。
デニス

6
これを行うには2つの方法があります。1つ目は、.git / configまたは〜/ .gitconfigのいずれかで、.gitconfigにそのままの行を追加します。2つgit config --global core.whitespace cr-at-eol(ここで--globalは、自分がいるリポジトリでそれを必要とする場合はオプションです)
K. Carpenter

これは私がWindows 7で機能しました[core]が、core.プレフィックスをTAB文字に置き換えることができるようにしただけです。
Rufflewind、2015

この質問は、最初に^ Mを入れない方法^Mgit diffはなく、に隠す方法の上にありました。これは、core.autocrlfユーザーの確認なしにファイルを静かに変更するため、受け入れられた変更の回答が最適ではないことを意味します。
deddebme

45

なぜあなたはこれら^Mをあなたの中に持っているのgit diffですか?

私の場合、私はWindowsで開発されたプロジェクトで作業していて、OS Xを使用していました。コードを変更する^Mと、で追加した行の最後に表示されましたgit diff^Mファイルの残りの部分とは行末が異なっていたため、が表示されていたと思います。ファイルの残りの部分はWindowsで開発されたため、CR行末を使用し、OS XではLF行末を使用しました。

どうやら、Windows開発者は、Gitのインストール中に「Windowsスタイルのチェックアウト、Unixスタイルの行末コミット」オプションを使用しなかったようです。

では、これについて何をすべきでしょうか?

Windowsユーザーにgitを再インストールして、「Windowsスタイルでチェックアウトし、Unixスタイルで行末をコミットする」オプションを使用させることができます。私はWindowsを行末文字の例外と見なしており、Windowsはこの方法で独自の問題を修正しているため、これが私が好むものです。

ただし、このオプションを使用する場合は、現在のファイルを修正する必要があります(ファイルがまだCR行末を使用しているため)。私は次の手順に従ってこれを行いました:

  1. ファイルシステムからではなく、リポジトリからすべてのファイルを削除します。

    git rm --cached -r .
    
  2. .gitattributes特定のファイルを強制的にLF行末として使用するファイルを追加します。これをファイルに入れます:

    *.ext text eol=crlf
    

    .ext一致させたいファイル拡張子に置き換えます。

  3. すべてのファイルを再度追加します。

    git add .
    

    次のようなメッセージが表示されます。

    warning: CRLF will be replaced by LF in <filename>.
    The file will have its original line endings in your working directory.
    
  4. .gitattributesWindowsスタイルのチェックアウト、Unixスタイルの行末コミット」オプションを使用したくない頑固なWindowsユーザーがいない限り、ファイルを削除できます。

  5. すべてをコミットしてプッシュします。

  6. それらが使用されているすべてのシステムで、該当するファイルを削除してチェックアウトします。Windowsシステムでは、「チェックアウトWindowsスタイル、コミットUnixスタイルの行末」オプションを使用していることを確認してください。ファイルを追加したときにgitが言ったので、これらのタスクを実行したシステムでもこれを行う必要があります。

    The file will have its original line endings in your working directory.
    

    次のようにしてファイルを削除できます。

    git ls | grep ".ext$" | xargs rm -f
    

    そして、これは正しい行末でそれらを戻すために:

    git ls | grep ".ext$" | xargs git checkout
    

    もちろん.ext、必要な拡張子に置き換えます。

これで、プロジェクトLFは行末に文字のみを使用し、厄介なCR文字が二度と戻らないようになりました:)。

もう1つのオプションは、ウィンドウスタイルの行末を強制することです。.gitattributesこのファイルを使用することもできます。

詳細:https : //help.github.com/articles/dealing-with-line-endings/#platform-all


4
特定のファイルのすべての行末を修正するには、Sublime Textを使用している場合、View-> Line Endingsに移動してをクリックしUnixます。
トファーハント2015

これ^Mはどういう意味ですか?それはwindowsまたはlinuxの改行ですか?それとも、ファイル内の他の改行と比較して単なる「異なる」改行ですか?
buhtz

いいですね、それは単なる "異なる"改行(他のほとんどの
文書

-1はgitを再インストールして達成するのgit config --global core.autocrlf trueはやり過ぎであり、アンチWindows /アンチCRキャンペーンは問題の正接のようです。
RJFalconer

41

「比較時に^ Mを改行として扱う」のようなオプションはありますか?

diffコマンドの「」ファミリーが行末の改行の違いを無視することを学習したため、Git 2.16(2018年第1四半期)のバージョンが1つあります。

Junio C Hamano()によるcommit e9282f0(2017年10月26日)を参照してください。 協力者:ヨハネスシンデリン(gitster
dscho
(合併によりJunio C浜野- gitster-10f65c2コミットし、2017年11月27日)を

差分: --ignore-cr-at-eol

新しいオプション--ignore-cr-at-eolは、(完全な)行末の改行を存在しないかのように扱うようにdiff機構に指示します。

--ignore-*さまざまな種類の空白の違いを無視する他の「」オプションと同様に、これはCRLF<->LF、エディタープログラムによる誤った変換に気を取られることなく、実際の変更を確認するのに役立ちます。


@kaartic回答を編集して正しいコミットを参照していただきありがとうございます!
VonC、2018年

3
git config --global core.autocrlf true受け入れられた回答のように設定することは一般的には良い習慣ですが、これはOPの質問に直接答えます。
drkvogel

1
Git 2.20以降、^ Mは非表示になりません
user1944491

@ user1944491 Git 2.26でこのオプションを比較するときに、eolが無視されることはありません。
VonC

@VonC git diffコマンドでこの引数を使用しても機能しませんでした。また、core.whitespaceの値をオンに設定しませんでしたgit version 2.20.1 (Apple Git-117)が、Jason Pyeronのcore.pagerの回答を追加することで修正されました。明らかにYMMV。
user1944491

26

TL; DR

変更core.pager"tr -d '\r' | less -REX"ソースコードではありません、

これが理由です

示されている厄介な^ Mは、カラー化とページャのアーティファクトです。デフォルトのgitページャーオプションであるここに画像の説明を入力してください が原因less -Rです。(gitのデフォルトのポケットベルはless -REX

最初に注意することは git diff -b空白の変更が表示されない(たとえば、\ r \ nと\ n)。

セットアップ:

git clone https://github.com/CipherShed/CipherShed
cd CipherShed

UNIXファイルを作成して行末を変更する簡単なテストでは、次のような変更は表示されませんgit diff -b

echo -e 'The quick brown fox\njumped over the lazy\ndogs.' > test.txt
git add test.txt
unix2dos.exe test.txt
git diff -b test.txt

パイプをlessに強制しても^ Mは表示されませんが、色が有効になり、次のようになりless -Rます。

git diff origin/v0.7.4.0 origin/v0.7.4.1 | less
git -c color.ui=always diff origin/v0.7.4.0 origin/v0.7.4.1 | less -R

修正は、パイプを使用して出力から\ r(^ M)を取り除くことによって示されます。

git diff origin/v0.7.4.0 origin/v0.7.4.1
git -c core.pager="tr -d '\r' | less -REX"  diff origin/v0.7.4.0 origin/v0.7.4.1

less -r色コードだけでなく、すべての制御コードを通過するため、賢明な代替手段はを使用することです。

git configファイルを直接編集するだけの場合、これはupdate / addのエントリです。

[core]
        pager = tr -d '\\r' | less -REX

一部のファイルに\r\n行末があり、一部に行末があったリポジトリでこの問題が発生しました\n(それが関連するかどうかはわかりません)。前者の差分は、^M変更された行(つまり+行)にを示しました。core.autocrlfに設定されましたtrue。実行するgit config core.pager "tr -d '\r' | less -REX"と、厄介な^Ms が取り除かれました。ありがとう!
ラベルワー

5
これをありがとう。これは、リポジトリの異なる行末で作業する必要がある場合の唯一の回答です。たとえば、意図的にチェックアウトをそのまま使用する、そのままコミットするなどです。
マイク

git diff -b私が探していたものですが、完全な説明に感謝します。
マーティンバーチ2018

これが答えです!ありがとうございました。-bフラグは機能しませんでした。
クリス、

はい!この質問に対するすべての回答の中で、git "config"ファイルの[core]セクションを追加して変更することpager = tr -d '\\r' | less -REXが、私にとって有効な唯一の回答でした。ありがとうございました!
ラシキ

13

私は長い間この問題に苦しんでいました。はるかに簡単な解決策は、^ M文字を気にせず、それらを処理できる視覚的な差分ツールを使用することです。

入力する代わりに:

git diff <commitHash> <filename>

試してください:

git difftool <commitHash> <filename>

1
ありがとう!また、私は「git difftool」を実行しただけで、基本的には変更されたすべてのファイルをループで比較しました
Bhanuprakash D


2

VonCによって指摘されているように、これはすでにgit 2.16+に含まれています。残念ながら、オプションの名前(--ignore-cr-at-eol)は、私が慣れているGNU diffで使用されているものとは異なります(--strip-trailing-cr)。

この問題に直面したとき、私の解決策はgitの組み込みdiffではなくGNU diffを呼び出すことでした。私のgitは2.16より古いためです。私はこのコマンドラインを使用してそれをしました:

GIT_EXTERNAL_DIFF='diff -u --strip-trailing-cr "$2" "$5";true;#' git diff --ext-diff

これにより、--strip-trailing-crおよびその他のGNU diffオプションを使用できます。

この他の方法もあります:

git difftool -y -x 'diff -u --strip-trailing-cr'

しかし、それは構成されたポケットベル設定を使用しないので、私は前者を好みます。


私の答えの興味深い代替案。賛成。
VonC、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.