Git은 왜이 텍스트 파일을 이진 파일로 취급합니까?


150

왜 git이 나에게 이것을 말하는지 궁금합니다.

$ git diff MyFile.txt
diff --git a/MyFile.txt b/MyFile.txt
index d41a4f3..15dcfa2 100644
Binary files a/MyFile.txt and b/MyFile.txt differ

텍스트 파일이 아닙니까?

.gitattributes를 확인했는데 비어 있습니다. 이 메시지가 나타나는 이유는 무엇입니까? 더 이상 사용할 때 diffs를 얻을 수 없습니다

추가 :

@파일 권한 이 있음을 알았습니다 . 이것이 이유가 될 수 있습니까?

$ls -all
drwxr-xr-x   5 nacho4d  staff    170 28 Jul 17:07 .
drwxr-xr-x  16 nacho4d  staff    544 28 Jul 16:39 ..
-rw-r--r--@  1 nacho4d  staff   6148 28 Jul 16:15 .DS_Store
-rw-r--r--@  1 nacho4d  staff    746 28 Jul 17:07 MyFile.txt
-rw-r--r--   1 nacho4d  staff  22538  5 Apr 16:18 OtherFile.txt

4
UTF-8로 인코딩 된 파일 일 수 있습니다.
Marnix van Valen

UTF16 리틀 엔디 언 LF 인 것으로 예상됩니다
nacho4d

1
lsMac OS X 의 맨 페이지에서 : 파일 또는 디렉토리에 확장 된 속성이있는 경우, -l옵션으로 인쇄 된 권한 필드 뒤에 @문자가 있습니다. -@이러한 확장 된 속성을 보려면 옵션 을 사용하십시오 .
adl

나는 이것이 git의 버그 일 수 있다고 생각한다. 확장 된 속성을 삭제했으며 이제 모든 것이 정상입니다.
nacho4d

4
@ nacho4d : git은 확장 된 속성이 있다는 것을 알지 못하기 때문에 이상합니다. 그것을 재현 할 수 있다면, git 메일 링리스트를 불러오는 것이 좋습니다. vger.kernel.org목록 에 대한 좋은 사용자 정의와 마찬가지로 게시물을 구독 할 필요가 없으며 (사람들이 CC를 답변으로 유지하도록 할 것입니다) 다소 많은 양의 git@vger.kernel.org목록 을 제공하지 않아야 합니다.
Jan Hudec

답변:


76

그것은 단순히 git이 파일의 실제 내용을 검사 할 때 주어진 확장자가 이진 파일 이 아니라는 것을 알지 못합니다 -속성 파일을 명시 적으로 말하고 싶다면 매뉴얼 페이지를 참조하십시오.

파일의 내용을 검사 한 결과 기본 ASCII 문자가 아닌 것을 발견했습니다. UTF16이기 때문에 '재미있는'문자를 가질 것으로 예상되므로 바이너리라고 생각합니다.

파일에 국제화 (i18n) 또는 확장 문자 형식이있는 경우 git에 알리는 방법이 있습니다. 나는 그것을 설정하는 정확한 방법에 충분히 익숙하지 않다-RT [Full] M ;-)해야 할 수도있다

편집 : SO에 대한 빠른 검색을 통해 can-i-make-git-recognize-a-utf-16-file-as-text 를 찾을 수 있습니다.


10
당신은 거의 완벽하지는 않습니다. 힘내 실제 파일을 검사하고 거기에 '재미있는'문자를 보았다. 그러나 UTF-16이 이진 인 "생각"하지 않습니다. 그것은 이다 텍스트가 ASCII 기반 (유일한 내장에 사용할 수에 대한 결과를 줄 것이다 DIFF)와 UTF-16를하지으로 정의되어 있기 때문에, 진. 예, 패턴 정의 파일에 특수 diff를 사용하도록 git에 지시하는 방법이 있습니다 (사용 .gitattributes).
Jan Hudec

2
'재미있는 문자'는 실제로 0 바이트를 의미한다고 덧붙여 야합니다.
Jan Hudec

4
우리는 둘 다 옳지 만 다른 관점에서 봅니다. "Git은 내용을 검사하여 유형을 결정합니다." 우리는 git이 UTF16으로 취급해야한다는 것을 알리기 위해 사용자가 git .gitattributes등을 통해 알려 주어야한다고 말합니다 .
Philip Oakley

7
@ JanHudec :보기에 모든 파일은 이진입니다.
stolsvik

2
@stolosvik, (및 JanH) UTF-8은 기본 0-127 ASCII 문자와 다른 모든 유니 코드 문자를 포함하고 nul char 이외의 다른 것에 대해서는 null (00h) 바이트가 필요하지 않기 때문에 더 미묘한 중간 근거입니다. ( 'C'문자열 종결 자). 따라서 Git의 텍스트 정의는 utf-8로 인코딩 할 때 내용 (첫 번째 1k 바이트)에 null 바이트가 없어야한다는 것입니다. 재미있게 읽으려면 stackoverflow.com/questions/2241348/… 를 시도하십시오 . 필자의 원래 의견은 UTF-16으로 인코딩 된 데이터가 바이트 쌍으로 표시되는 경우를 나타내므로 ASCII 코드 포인트의 상위 바이트는 00이됩니다.
Philip Oakley

41

파일 유형을 설정하지 않은 경우 Git은 자동으로 파일을 결정하려고 시도하고 실제로 긴 줄을 가진 파일과 일부 넓은 문자 (예 : 유니 코드)는 이진으로 처리됩니다. .gitattributes 파일을 사용하면 Git이 파일을 해석하는 방법을 정의 할 수 있습니다. diff 속성을 수동으로 설정 하면 Git은 파일 내용을 텍스트로 해석하여 일반적인 diff를 수행합니다.

저장소 루트 폴더에 .gitattributes 를 추가 하고 diff 속성을 경로 또는 파일로 설정하십시오. 예를 들면 다음과 같습니다.

src/Acme/DemoBundle/Resources/public/js/i18n/* diff
doc/Help/NothingToSay.yml                      diff
*.css                                          diff

파일에 속성이 설정되어 있는지 확인하려면 git check-attr 의 도움으로 할 수 있습니다

git check-attr --all -- src/my_file.txt

Git 속성에 대한 또 다른 좋은 참고 자료는 여기 에서 찾을 수 있습니다 .


1
이것은 도움이되었지만 실제로는 올바르지 diff않습니다 text. 올바른 속성은 입니다. 이 text속성은 텍스트를 사용하여 git에게 diff를 지시하지 않지만 대신 줄 끝을 처리하는 방법을 제어합니다 (LF로 표준화). 자세한 내용은 .gitattributes에 대한 링크를 참조하십시오.
ErikE

감사합니다 @ErikE. 귀하의 의견과 Git 설명서에 따라 게시물을 업데이트했습니다.
naitsirch

4
또한 어떤 종류의 diff를 수행해야하는지 설정할 수 있습니다. 예를 들어 xml 파일 인 경우 diff=xmljust 대신 사용할 수 있습니다 diff.
Sandy Chapman

1
체크 공격의 반대는 무엇입니까-세트 공격이 있습니까? 원래 실수로 파일을 UTF-16으로 저장 한 다음 커밋하고 푸시했으며 이제 BitBucket은 파일을 UTF-8로 다시 저장하고 커밋하고 다시 푸시 한 후에도 UTF-16으로 인식합니다. 기본적으로 검토자는 검토 주석을 추가하기 위해 각 개별 주석을 클릭해야하기 때문에 풀 요청을 읽을 수 없습니다.
John Zabroski

21

Git GUI와 SourceTree가 Java / JS 파일을 바이너리로 취급하여 차이를 볼 수없는이 문제가 발생했습니다.

다음 내용으로 .git \ info 폴더에 "attributes"라는 파일을 생성하면 문제가 해결되었습니다.

*.java diff
*.js diff
*.pl diff
*.txt diff
*.ts diff
*.html diff

모든 저장소에 대해이 변경을 수행하려는 경우 $ HOME / .config / git / attributes 위치에 속성 파일을 추가 할 수 있습니다.


1
또한 <project-root>/.gitattributes파일을 참고하여 모든 기고자 및 관련 프로젝트에 대해서만 변경 사항을 적용하십시오.
jpaugh

추가 * diff는 저에게 도움이되었습니다. 모든 파일 형식의 차이점을 보여줍니다. 그러나 큰 이진 파일에서 불필요한 diff를 표시하지 않기 때문에 솔루션이 더 좋습니다.
부울 _ 유형

네! 도움이됩니다!
WildCat

19

Git은 텍스트 파일에 하나의 긴 줄이 있으면 바이너리인지 확인합니다. 나는 긴 문자열을 끊어 여러 소스 코드 줄로 바꾸었고 갑자기 파일이 '이진'에서 (SmartGit에서 볼 수있는) 텍스트 파일로 바뀌 었습니다.

따라서 편집기에서 'Enter'를 누르지 않고 오른쪽으로 너무 멀리 입력하지 마십시오. 그렇지 않으면 나중에 Git에서 바이너리 파일을 생성했다고 생각합니다.


1
이것은 올바른 정보입니다. 매우 큰 MySQL 덤프 (.sql 파일)에 대한 diff를 제어하려고했지만 git은 ASCII / UTF8 데이터 만 있어도 바이너리 파일로 취급합니다. 그 이유는 줄이 매우 길기 때문입니다 (삽입 값 (1), (2), (3), (...), (3 백만 ...) ;. 모든 커밋마다 git 저장소는 이상합니다. 1.7GB 증가하지 않고 ~ 350mb 만 증가 git 파일을 저장하기 전에 "이진"파일을 압축하는 중일 수 있습니다.
Alexandre T.

@AlexandreT. Git은 실제로 파일 블롭을 압축합니다 (GZip, IIRC 사용).
jpaugh

11

새 편집기에서 파일 중 하나를 편집 한 후에도 동일한 문제가 발생했습니다. 새 편집기에서 기존 편집기 (UTF-8)와 다른 인코딩 (유니 코드)을 사용했습니다. 따라서 새 편집기에서 UTF-8로 파일을 저장하도록 지시 한 다음 git에서 변경 사항을 다시 올바르게 표시하고 이진 파일로 보지 않았습니다.

문제는 단순히 git이 다른 인코딩 유형의 파일을 비교하는 방법을 모른다는 것입니다. 따라서 사용하는 인코딩 유형은 일관성이 유지되는 한 중요하지 않습니다.

테스트하지는 않았지만 새 유니 코드 인코딩으로 파일을 커밋 한 경우 다음에 해당 파일을 변경하면 변경 사항이 올바르게 표시되고 바이너리로 감지되지 않았을 것입니다. 그런 다음 UTF-8 파일이 아닌 두 개의 유니 코드 인코딩 파일을 유니 코드 파일과 비교했을 것입니다.

메모장 ++ 과 같은 앱을 사용하여 텍스트 파일의 인코딩 유형을 쉽게보고 변경할 수 있습니다. 메모장 ++에서 파일을 열고 툴바의 인코딩 메뉴를 사용하십시오.


1
유니 코드는 인코딩이 아닙니다. 문자셋이고 UTF-8은 인코딩 중 하나입니다. 즉, 유니 코드 코드 포인트를 인코딩하는 방법입니다.
phuclv

1
이렇게해도 문제가 해결되지 않고 피할 수 있습니다. 문제는 git 또는 diff 도구가 텍스트 파일을 올바르게 인식하지 못하거나 사용자가 쉽게 동작을 무시할 수 없다는 것입니다.
Preza8

6

나는 같은 문제가 있었다. Google에서 솔루션을 검색 할 때 스레드를 찾았지만 여전히 실마리를 찾지 못했습니다. 그러나 나는 공부 후 이유를 발견했다고 생각합니다. 아래 예는 내 단서를 명확하게 설명합니다.

    echo "new text" > new.txt
    git add new.txt
    git commit -m "dummy"

현재는 new.txt 파일이 텍스트 파일로 간주됩니다.

    echo -e "newer text\000" > new.txt
    git diff

이 결과를 얻을 것입니다

diff --git a/new.txt b/new.txt
index fa49b07..410428c 100644
Binary files a/new.txt and b/new.txt differ

그리고 이것을 시도하십시오

git diff -a

당신은 아래에 얻을 것이다

    diff --git a/new.txt b/new.txt
    index fa49b07..9664e3f 100644
    --- a/new.txt
    +++ b/new.txt
    @@ -1 +1 @@
    -new file
    +newer text^@

5

.html 파일을 변경하려고 할 때마다 .html 파일이 이진으로 표시되는 경우가있었습니다. diff를 보지 않으면 매우 불편합니다. 솔직히 말해서, 여기에있는 모든 솔루션을 확인하지는 않았지만 우리에게 도움이 된 것은 다음과 같습니다.

  1. 파일을 제거하고 (실제로 내 데스크탑으로 옮겼습니다) git deletion. 힘내 말한다Deleted file with mode 100644 (Regular) Binary file differs
  2. 파일을 다시 추가했습니다 (실제로 내 데스크탑에서 프로젝트로 파일을 옮겼습니다). 힘내 말한다 New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletions파일이 이제 일반 텍스트 파일로 추가되었습니다

이제부터 파일에서 변경 한 내용은 일반 텍스트 차이로 표시됩니다. 이 커밋을 스쿼시 할 수도 있습니다 (1, 2 및 3은 실제 변경 사항입니다).하지만 나중에 내가 한 일을 볼 수 있기를 바랍니다. 스 쿼싱 1과 2는 이진 변화를 보여줍니다.


VS에서 푸시 된 하나 또는 두 개 (성공적으로 컴파일 된) cpp 파일과 유사합니다. 우스꽝스러운 비교를 위해 Github GUI를 렌더링합니다 . 하나는 그런 딩동 인터체인지에서 종소리를 원하지 않습니다 .- 한쪽은 Github라고 말하고 다른 쪽은 Github는 VS라고 말합니다. :(
Laurie Stearn

4

이 도움이 대답 , 당신은 특정 방법으로 파일을 취급 직접 왜 망할 놈을 요청할 수 있습니다 :

cd directory/of/interest
file *

다음과 같은 유용한 출력을 생성합니다.

$ file *
CR6Series_stats resaved.dat: ASCII text, with very long lines, with CRLF line terminators
CR6Series_stats utf8.dat:    UTF-8 Unicode (with BOM) text, with very long lines, with CRLF line terminators
CR6Series_stats.dat:         ASCII text, with very long lines, with CRLF line terminators
readme.md:                   ASCII text, with CRLF line terminators

6
filegit 명령이 아닙니다. Windows에서 git으로 패키지 된 완전히 별도의 도구입니다. 이것이 git이 바이너리 파일 탐지에 사용한다는 것을 보여주는 문서가 있습니까?
Max

4

이것은 BOM 인코딩을 사용하는 UTF-8 이있는 텍스트 파일에 의해서도 발생합니다 (적어도 Windows에서는) . 인코딩을 일반 UTF-8로 즉시 변경하면 Git은 파일을 type = text로 볼 수 있습니다.


1

목적에 .gitignore따라 이중 \r(캐리지 리턴) 시퀀스가 포함 된 인스턴스가 있었습니다 .

이 파일은 git에 의해 바이너리로 식별되었습니다. .gitattributes파일 추가가 도움이되었습니다.

# .gitattributes file
.gitignore diff

1
일했다. 또한 일부 OS "Icon \ r \ r"파일을 무시하기 위해 이중 \ r이있었습니다. 수정 사항뿐만 아니라 원인을 아는 것이 좋습니다.
hsandt

1

경우 git check-attr --all -- src/my_file.txt파일이 바이너리로 플래그가, 당신은 바이너리로 설정되지 않았 음을 나타냅니다 .gitattributes에 대한 체크를 /.git/info/attributes.


0

Aux.js를 Sig.js와 같은 다른 이름으로 변경하십시오.

소스 트리는 여전히 이진 파일로 표시하지만이를 준비 (추가)하고 커밋 할 수 있습니다.


0

바이너리 Kafka 메시지의 일부 텍스트를 붙여 넣을 때 비슷한 문제가 발생하여 보이지 않는 문자를 삽입하고 git이 파일을 바이너리라고 생각하게했습니다.

regex 사용하여 파일을 검색하여 문제가되는 문자를 찾았습니다 [^ -~\n\r\t]+.

  • [ 이 세트의 문자와 일치
  • ^ 이 세트에없는 문자 일치
  • -~ ''(공백)에서 '~'까지의 모든 문자와 일치
  • \n 개행
  • \r 캐리지 리턴
  • \t
  • ] 가까운 세트
  • + 이 문자들 중 하나 이상과 일치

-2

방금 솔루션의 테스트 프로젝트 중 하나가 탐색기에 테스트를 추가하지 않은 이유를 해결하기 위해이 목록의 모든 것을 검토하는 데 몇 시간을 보냈습니다.

내 경우에는 VS가 어쨌든 프로젝트의 참조를 잃어 버린 어딘가 (어쩌면 어딘가 git merge가 어딘가에 기인 한) 것으로 나타났습니다. 그것은 여전히 ​​건물 이었지만 의존성 만 만들었습니다.

그런 다음 종속성 목록 자체에 표시되지 않는 것으로 나타 났으므로 테스트 프로젝트를 제거하고 다시 추가했습니다. 모든 테스트가 마침내 나타났습니다.


2
Visual Studio는 실제로 관련이 없습니다.
jpaugh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.