[git] Git이 파일을 바이너리 또는 텍스트로 처리하는지 확인하는 방법은 무엇입니까?

Git은 파일이 바이너리인지 텍스트인지 자동으로 감지하고 .gitattributes필요한 경우 수동으로 설정하는 데 사용할 수 있다는 것을 알고 있습니다. 그러나 Git이 파일을 어떻게 처리하는지 물어 보는 방법도 있습니까?

그래서 두 개의 파일이있는 Git 저장소가 있다고 가정 해 봅시다 : ascii.dat일반 텍스트를 binary.dat포함 하는 파일 과 임의의 바이너리를 포함 하는 파일. Git은 첫 번째 .dat파일을 텍스트로, 보조 파일을 바이너리로 처리합니다. 이제 텍스트 파일 용 뷰어와 바이너리 파일 용 특수 뷰어 (예 : 16 진수 덤프 표시)가있는 Git 웹 프런트 엔드를 작성하고 싶습니다. 물론 내 자신의 텍스트 / 이진 검사를 구현할 수 있지만 뷰어가 Git이 이러한 파일을 처리하는 방법에 대한 정보에 의존하는 경우 더 유용 할 것입니다.

그렇다면 파일을 텍스트로 처리하는지 바이너리로 처리하는지 Git에게 어떻게 물어볼 수 있습니까?



답변

builtin_diff()1 은 처음 8000 바이트 (또는 더 짧은 경우 전체 길이)에서 0 바이트 (NUL “문자”)가 발생하는지 확인 diff_filespec_is_binary()하는 호출 을 호출 buffer_is_binary()합니다.

나는 이것이 “이진법인가?”라는 것을 알지 못한다. 테스트는 모든 명령에서 명시 적으로 노출됩니다.

git merge-file직접 사용 buffer_is_binary()하므로 사용할 수 있습니다.

git merge-file /dev/null /dev/null file-to-test

error: Cannot merge binary files: file-to-test바이너리 파일이 주어지면 다음과 같은 오류 메시지가 생성되고 종료 상태가 255 인 것으로 보입니다 . 그래도이 동작에 의존하고 싶지는 않습니다.

아마도 git diff --numstat더 신뢰할 수 있습니다.

isBinary() {
    p=$(printf '%s\t-\t' -)
    t=$(git diff --no-index --numstat /dev/null "$1")
    case "$t" in "$p"*) return 0 ;; esac
    return 1
}
isBinary file-to-test && echo binary || echo not binary

바이너리 파일의 경우 --numstat출력은 -TAB -TAB으로 시작해야 하므로 테스트 만합니다.


1
builtin_diff() 에는 Binary files %s and %s differ익숙한 문자열 이 있습니다.


답변

git grep -I --name-only --untracked -e . -- ascii.dat binary.dat ...

git이 텍스트 파일로 해석하는 파일의 이름을 반환합니다.

예를 들어 와일드 카드를 사용할 수 있습니다.

git grep -I --name-only --untracked -e . -- *.ps1


답변

이 답변이 마음에 들지 않지만 git-diff-tree의 출력을 구문 분석하여 바이너리인지 확인할 수 있습니다. 예를 들면 :

git diff-tree -p 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD -- MegaCli
diff --git a/megaraid/MegaCli b/megaraid/MegaCli
new file mode 100755
index 0000000..7f0e997
Binary files /dev/null and b/megaraid/MegaCli differ

반대로 :

git diff-tree -p 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD -- megamgr
diff --git a/megaraid/megamgr b/megaraid/megamgr
new file mode 100755
index 0000000..50fd8a1
--- /dev/null
+++ b/megaraid/megamgr
@@ -0,0 +1,78 @@
+#!/bin/sh
[…]

아, 그리고 BTW, 4b825d는 … 빈 트리 (가 나타내는 마법의 SHA는 이다 빈 나무에 대한 SHA하지만 자식이 마법의 특별 알고있다).


답변

열악한 코드 품질로 인해 충돌 할 위험이 있으므로 Git 소스의 원래 buffer_is_binary () 루틴을 기반으로 빌드 된 C 유틸리티 is_binary를 나열합니다. 빌드 및 실행 방법은 내부 의견을 참조하십시오. 쉽게 수정 가능 :

/***********************************************************
 * is_binary.c
 *
 * Usage: is_binary <pathname>
 *   Returns a 1 if a binary; return a 0 if non-binary
 *
 * Thanks to Git and Stackoverflow developers for helping with these routines:
 * - the buffer_is_binary() routine from the xdiff-interface.c module
 *   in git source code.
 * - the read-a-filename-from-stdin route
 * - the read-a-file-into-memory (fill_buffer()) routine
 *
 * To build:
 *    % gcc is_binary.c -o is_binary
 *
 * To build debuggable (to push a few messages to stdout):
 *    % gcc -DDEBUG=1 ./is_binary.c -o is_binary
 *
 * BUGS:
 *  Doesn't work with piped input, like
 *    % cat foo.tar | is_binary
 *  Claims that zero input is binary. Actually,
 *  what should it be?
 *
 * Revision 1.4
 *
 * Tue Sep 12 09:01:33 EDT 2017
***********************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_PATH_LENGTH 200
#define FIRST_FEW_BYTES 8000

/* global, unfortunately */
char *source_blob_buffer;

/* From: /programming/14002954/c-programming-how-to-read-the-whole-file-contents-into-a-buffer */

/* From: /programming/1563882/reading-a-file-name-from-piped-command */

/* From: /programming/6119956/how-to-determine-if-git-handles-a-file-as-binary-or-as-text
*/

/* The key routine in this function is from libc: void *memchr(const void *s, int c, size_t n); */
/* Checks for any occurrence of a zero byte (NUL character) in the first 8000 bytes (or the entire length if shorter). */

int buffer_is_binary(const char *ptr, unsigned long size)
{
  if (FIRST_FEW_BYTES < size)
    size = FIRST_FEW_BYTES;
    /* printf("buff = %s.\n", ptr); */
  return !!memchr(ptr, 0, size);
}
int fill_buffer(FILE * file_object_pointer) {
  fseek(file_object_pointer, 0, SEEK_END);
  long fsize = ftell(file_object_pointer);
  fseek(file_object_pointer, 0, SEEK_SET);  //same as rewind(f);
  source_blob_buffer = malloc(fsize + 1);
  fread(source_blob_buffer, fsize, 1, file_object_pointer);
  fclose(file_object_pointer);
  source_blob_buffer[fsize] = 0;
  return (fsize + 1);
}
int main(int argc, char *argv[]) {

  char pathname[MAX_PATH_LENGTH];
  FILE *file_object_pointer;

  if (argc == 1) {
    file_object_pointer = stdin;
  } else {
    strcpy(pathname,argv[1]);
#ifdef DEBUG
    printf("pathname=%s.\n", pathname);
#endif
    file_object_pointer = fopen (pathname, "rb");
    if (file_object_pointer == NULL) {
      printf ("I'm sorry, Dave, I can't do that--");
      printf ("open the file '%s', that is.\n", pathname);
      exit(3);
    }
  }
  if (!file_object_pointer) {
    printf("Not a file nor a pipe--sorry.\n");
    exit (4);
  }
  int fsize = fill_buffer(file_object_pointer);
  int result = buffer_is_binary(source_blob_buffer, fsize - 2);

#ifdef DEBUG
  if (result == 1) {
    printf ("%s %d\n", pathname, fsize - 1);
  }
  else {
    printf ("File '%s' is NON-BINARY; size is %d bytes.\n", pathname, fsize - 1);
  }
#endif
  exit(result);
  /* easy check -- 'echo $?' after running */
}


답변

명령 줄 도구 ‘파일’유틸리티를 사용할 수 있습니다. Windows에서는 git 설치에 포함되어 있으며 일반적으로 C : \ Program Files \ git \ usr \ bin 폴더에 있습니다.

file --mime-encoding *

Windows에서 파일 인코딩 가져 오기 에서 자세히보기


답변