^ M을 무시하는 git-diff


474

파일의 일부가 개행 구분자로 ^ M을 포함하는 프로젝트에서. git-diff는 전체 파일이 한 줄이므로 파일을 비교하는 것은 불가능합니다.

이전 버전과 다른 점은 무엇입니까?

"확산시 ^ 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
힘내 2.16 (Q1 2018), 당신은해야합니다 git diff --ignore-cr-at-eol. 아래 내 답변을 참조하십시오 .
VonC

7
@JasonPyeron 및 향후 Google 직원 :와 git diff -b동일한 내용을 찾아야했습니다 git diff --ignore-space-change.
Gogowitsch

답변:


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는 매뉴얼 페이지 에 설명되어 있습니다.


1
물론, 설정이 끝나면 커밋시 자동으로 변환됩니다. 모든이다 나는 그것이 수행의 사고 방식, ... 작동하는 경우
nes1983

1
문제는 이미 저장소에 CRLF 엔딩이있는 파일과 그렇지 않은 파일이 있다는 것입니다. Mac 버전을 사용하고 있는데도 Adobe Flash가 CRLF를 추가한다고 생각합니다. 이 파일의 이전 버전과 비교해야합니다. 지금부터 시작하는 줄 끝을 변환해도 이전 개정판의 문제를 해결하지 못합니다 :-/
neoneye

65
적어도 당신이 게시 한 예제가 아닌 CRLF 파일로 작업하고 있지 않습니다. 구식 Mac 파일입니다 (EOL에는 \ r 만 사용). 그것이 diff가 한 줄에 표시되는 이유입니다. 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

5
@ trusktr, 그것은 나에게 동일하게 일어났다. 리눅스에서 실수로 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

370

Windows에서 개발할 때을 사용할 때이 문제가 발생했습니다 git tfs. 나는 이것을 이렇게 해결했다.

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

이것은 기본적으로 줄 끝 CR이 오류가 아니라고 Git에 알려줍니다. 그 결과, 그 성가신 ^M문자는 더 이상의 행의 끝 부분에 표시되지 않습니다 git diff, git show

다른 설정은 그대로 둡니다. 예를 들어, 줄 끝의 추가 공백은 여전히 ​​diff에서 오류로 표시됩니다 (빨간색으로 강조 표시됨).

(다른 답변이 언급하지만, 위의 설정을 설정하는 방법을 정확하게있다. 하나 개의 프로젝트에 대한 설정을 설정하려면 생략 --global.)

편집 :

많은 줄 끝 난통 후 .NET 팀에서 다음 설정으로 작업 할 때 가장 운이 좋았습니다.

  • 코어가 없습니다.
  • 코어 없음 공백 설정
  • 코어 없음 자동 crlf 설정
  • Windows 용 Git 설치 프로그램을 실행하면 다음 세 가지 옵션이 제공됩니다.
    • Windows 스타일 체크 아웃, 유닉스 스타일 줄 바꿈 <-이 중 하나를 선택하십시오
    • 그대로 체크 아웃, 유닉스 스타일의 결말 커밋
    • 있는 그대로 체크 아웃하고있는 그대로 커밋

공백 설정을 사용해야하는 경우 TFS와 상호 작용해야하는 경우 프로젝트별로 설정해야합니다. 그냥 생략하십시오 --global:

git config core.whitespace cr-at-eol

일부 core. * 설정을 제거해야하는 경우 가장 쉬운 방법은 다음 명령을 실행하는 것입니다.

git config --global -e

텍스트 편집기에서 전역 .gitconfig 파일이 열리고 제거하려는 행을 쉽게 삭제할 수 있습니다. 또는 주석 앞에 '#'을 넣을 수도 있습니다.


30
지금 이것을 찾는 사람들에게는 Checkout Windows 스타일, Unix 스타일 라인 엔딩 자동 설정 core.autocrlftrue
K. Carpenter

14
이 줄 git config --global core.whitespace cr-at-eol은 기본 설정 인 다른 설정을 해제합니다. 기본값은 blank-at-eol, blank-at-eof 및 space-before-tab입니다. 따라서 cr-at-eol을 활성화하고 다른 것을 유지하려면을 사용해야 git config --global core.whitespace blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol합니다.
Zitrax

2
내 프로젝트를 위해 (이것은 윈도우에 밖으로 체크 아웃하고 있었고, 난 리눅스에 그것을 볼 수 있어요), cr-at-eol지웠어 ^M에서 라인의 끝 부분에 git diff라인 결말이 유일한 차이는 있었지만, 좋아하지만, GIT는 여전히 다른 같은 그 선을 보였다.
Jānis Elmeris

SourceInsight는 ^ M 문자를 계속 누르고 있으며 git은 여전히 ​​줄 끝의 차이를 보여줍니다. @Zitrax의 명령은 제 경우에 대한 정답입니다 .git diff는 훌륭하고 깨끗한 출력을 보여줍니다.
Lê 꽝 두이

3
git은 좀 더 복잡하고 줄 끝 부분에 충돌하는 설정이 더 필요하다고 생각합니다. git은 공백에 관심을 가져야한다고 생각합니다 . 예를 들어 Windows (Linux는 아님) 컴퓨터에서 Mac 줄 끝이 발생하면 관련없는 치명적 오류가 발생하고 리포지토리가 손상된 상태로 유지됩니다. 나는 왜 비즈니스에 신경 쓰이는 VCS를 사용하고 원하는 라인 엔딩을 사용할 수 있습니까? 나는 그들이 노력하고있는 것을 보았지만 존재하지 않는 문제를 해결하기 위해 열 여섯 줄을 더 끝내야합니다. 거의 다 왔습니다! 유지하십시오.
Rolf

125

git diff --ignore-space-at-eol, 또는 git diff --ignore-space-change, 또는을 사용해보십시오 git diff --ignore-all-space.


22
그중 어느 것도 개행을 식별하는 문자에 실제로 영향을 미치지 않습니다.
nes1983

4
나는 또한 "-w"로 시도했지만 운이 없어도 여전히 한 줄로 취급합니다. 다음 프로젝트는 CR을 소스 코드에 넣지 마십시오.
neoneye

3
git config --global core.autocrlf true를 기억하거나 git 사람들이 기본값이 될 때까지 버그를 수정하십시오 :)
nes1983

10
이렇게하면 autocrlf설정 을 변경하지 않고도 문제가 해결되었습니다 . 감사!
nneonneo

11
이 플래그는 나에게 아무런 영향을 미치지 않습니다 ... 여전히 ^ M을 diffs로 표시
Magnus

103

참조 :

core.whitespace = cr-at-eol

또는 동등하게

[core]
    whitespace = cr-at-eol

여기서 문자 whitespace가 앞에옵니다 .


4
그래, 이것은 git diff 도구 (에서 사용됨 git show) ^M가 변경된 줄 의 s에 대해 나를 괴롭히는 것을 멈추게했습니다 ! :)
Rijk

2
어떤 이유로 든 이것이 효과가 없었습니다. =와 no = 부호로 시도했습니다. git diff여전히 ^ M 문자를 표시합니다.
Dennis

6
이를 수행하는 두 가지 방법 : 하나는 .git / config 또는 ~ / .gitconfig에서 .gitconfig에 축 위의 행을 추가합니다. 2, git config --global core.whitespace cr-at-eol(여기서 --repo에서 원하는 경우 --global은 선택 사항입니다)
K. Carpenter

이것은 Windows 7에서 저에게 효과적이었습니다.하지만 접두사를 TAB 문자로 [core]바꿀 수 있습니다 core..
Rufflewind

이 질문에 어떻게 숨길 수 위였다 ^M에서 git diff하지 처음에 M ^에 넣지하는 방법에 대해. 즉, core.autocrlf사용자의 확인없이 파일을 자동으로 변경하기 때문에 승인 된 변경 답변이 가장 좋지 않습니다.
deddebme

45

왜 이것들 ^M을 당신의 안에 넣 git diff습니까?

필자의 경우 Windows에서 개발 된 프로젝트를 진행 중이며 OS X를 사용했습니다. 코드를 변경했을 때 ^M추가 한 줄의 끝을 보았습니다 git diff. 나는 ^M그들이 파일의 나머지 부분과 다른 줄 끝 때문에 나타나고 있다고 생각 합니다. 파일의 나머지 부분은 Windows에서 개발되었으므로 CR줄 끝을 사용 했고 OS X에서는 LF줄 끝을 사용했습니다 .

분명히 Windows 개발자는 Git을 설치하는 동안 " Checkout Windows-style, commit Unix-style line ending " 옵션을 사용하지 않았습니다 .

그래서 우리는 이것에 대해 어떻게해야합니까?

당신은 Windows 사용자는 "자식을 다시 설치하고 사용할 수 있습니다 , 유닉스 스타일의 라인 엔딩을 커밋 체크 아웃 윈도우 스타일 옵션을". 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. .gitattributes" Windows 스타일 체크 아웃, Unix 스타일 행 끝 커밋 "옵션 을 사용하지 않으려는 완고한 Windows 사용자가 없으면 파일을 제거 할 수 있습니다.

  5. 커밋하고 모두 밀어 넣으십시오.

  6. 사용 된 모든 시스템에서 해당 파일을 제거하고 체크 아웃하십시오. Windows 시스템에서 이제 " Checkout Windows 스타일, commit 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문자는 다시 나타나지 않습니다. :).

다른 옵션은 창 스타일 줄 끝을 적용하는 것입니다. .gitattributes이 파일을 사용할 수도 있습니다 .

자세한 정보 : https://help.github.com/articles/dealing-with-line-endings/#platform-all


4
Sublime Text를 사용하는 경우 특정 파일의 모든 줄 끝을 수정하려면 View-> 로 이동하여를 Line Endings클릭하십시오 Unix.
Topher Hunt

이것이 정확히 무엇을 ^M의미합니까? Windows 또는 Linux 줄 바꿈입니까? 아니면 파일의 다른 개행과 비교하여 "다른"개행입니까?
buhtz 2016 년

좋은 것, 나는 그것이 단지 "다른"개행이라고 생각합니다 (대부분의 다른 것보다 다릅니다)
gitaarik

-1을 달성하기 위해 git을 다시 설치하는 git config --global core.autocrlf true것은 과잉이며, 안티 Windows / 안티 CR캠페인은 문제의 핵심입니다.
RJFalconer

41

"확산시 ^ M을 줄 바꿈으로 처리"와 같은 옵션이 있습니까?

" diff"명령 군이 줄 끝에서 캐리지 리턴의 차이를 무시하는 법을 배웠기 때문에 Git 2.16 (2018 년 1 분기)이있는 것이있을 것 입니다.

참조 e9282f0 커밋 에 의해 (2017년 10월 26일)를 Junio C 하마노 ( gitster) .
도움 : Johannes Schindelin ( dscho) .
( Junio ​​C gitsterHamano 에 의해 병합 -- 커밋 10f65c2 , 2017 년 11 월 27 일)

차이점 : --ignore-cr-at-eol

새로운 옵션 --ignore-cr-at-eol은 diff 기계 장치가 캐리지 리턴을 (완료된) 줄 끝에 존재하지 않는 것처럼 처리하도록 지시합니다.

--ignore-*다양한 종류의 공백 차이를 무시하는 다른 " "옵션 과 마찬가지로 CRLF<->LF편집기 프로그램에서 생성 된 스퓨리어스 변환에 방해가되지 않고 실제 변경 사항을 검토하는 데 도움이됩니다 .


@kaartic 답변을 수정하고 올바른 커밋을 참조 해 주셔서 감사합니다!
VonC

3
일반적으로 git config --global core.autocrlf true허용되는 답변과 같이 설정하는 것이 좋은 방법이지만 OP의 질문에보다 직접적으로 대답합니다. " '확산시 ^ M을 줄 바꿈으로 처리"와 같은 옵션이 있습니까?'
drkvogel 5

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 pager 옵션 인으로 여기에 이미지 설명을 입력하십시오 인해 발생합니다 less -R. (git의 기본 호출기는 less -REX)

가장 먼저 알아 두어야 할 것은 git diff -b공백의 변화를 보여주지 않는다는 것입니다 (예 : \ r \ n vs \ n)

설정:

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

유닉스 파일을 만들고 줄 끝을 변경하는 빠른 테스트는 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

파이프를 줄이면 강제로 ^ 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 파일을 직접 편집하려면 다음을 업데이트 / 추가해야합니다.

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

파일의 일부에 \r\n줄 끝이 있고 일부는 \n줄 끝 이있는 리포지토리 에서이 문제가 있었습니다 (관련이 있는지 모르겠습니다). 전자의 diff는 ^M수정 된 라인 (즉, +라인)을 보여 주었다 . core.autocrlf로 설정되었습니다 true. 달리는 git config core.pager "tr -d '\r' | less -REX"성가신을 제거했습니다 ^M. 감사!
labreuer

5
고마워 이것은 리포지토리에서 다른 줄 끝으로 작업 해야하는 경우 유일한 대답입니다. 예를 들어 체크 아웃을 그대로 사용하고 그대로 커밋하십시오.
Mike

git diff -b내가 찾던 것이지만 철저한 설명에 감사합니다.
마틴 버치

이것이 답입니다! 감사합니다. -b 플래그가 작동하지 않았습니다.
Chris

예! 이 질문에 대한 모든 답변 중 git "config"파일 [core]섹션을 추가하여 수정 하는 pager = tr -d '\\r' | less -REX것이 저에게 효과적이었습니다. 감사합니다!
Rashiki

13

나는이 문제로 오랫동안 고생했다. 지금까지 가장 쉬운 해결책은 ^ M 문자에 대해 걱정하지 않고 문자를 처리 할 수있는 시각적 diff 도구를 사용하는 것입니다.

입력하는 대신 :

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.