如何确定Git是否将文件处理为二进制文件或文本?

我知道GIT以某种方式自动检测文件是二进制文件还是文本文件,如果需要,可以使用gitattributes手动设置。 但是,还有一种方法可以问GIT如何处理文件?

假设我有一个包含两个文件的GIT仓库:一个包含纯文本的ascii.dat文件和一个包含随机二进制文件的binary.dat文件。 Git将第一个dat文件作为文本处理,将第二个文件处理成二进制文件。 现在我想写一个GIT webfrontend,它有一个文本文件查看器和一个特殊的二进制文件查看器(例如显示一个hex转储文件)。 当然,我可以实现自己的文本/二进制检查,但如果查看器依赖GIT处理这些文件的信息,这将更有用。

那么我怎么能问GIT如果它把文件当作文本或者二进制文件?

builtin_diff() 1调用diff_filespec_is_binary() ,它调用buffer_is_binary() ,检查前8000个字节(或者更短的整个长度buffer_is_binary()中是否出现零字节(NUL“字符”)。

我没有看到这个“是二进制的?”testing是明确暴露在任何命令,但。

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开头,所以我们只是testing一下。


1 builtin_diff()具有像Binary files %s and %s differstring应该是熟悉的。

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

将返回git解释为文本文件的文件的名称。

你可以使用通配符

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

我不喜欢这个答案,但是你可以parsinggit-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特意知道这个魔法)。

为了降低代码质量的风险,我列出了一个C实用程序,is_binary,围绕Git源代码中的原始buffer_is_binary()例程构build。 请参阅关于如何构build和运行的内部注释。 轻松修改:

 /*********************************************************** * 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: https://stackoverflow.com/questions/14002954/c-programming-how-to-read-the-whole-file-contents-into-a-buffer */ /* From: https://stackoverflow.com/questions/1563882/reading-a-file-name-from-piped-command */ /* From: https://stackoverflow.com/questions/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中获取文件的编码