我知道Git会以某种方式自动检测文件是二进制文件还是文本文件,如果需要,可以使用gitattributes手动设置。但是有没有办法向GIT询问它如何处理文件?
所以假设我有一个包含两个文件的Git存储库:包含纯文本的 ascii.dat 文件和包含随机二进制文件的 binary.dat 文件。 Git将第一个dat文件作为文本处理,将辅助文件作为二进制文件处理。现在我想写一个Git webfrontend,它有一个文本文件查看器和二进制文件的特殊查看器(例如,显示十六进制转储)。当然,我可以实现自己的文本/二进制检查,但如果查看器依赖于Git如何处理这些文件的信息,它会更有用。
那么我怎么能问Git它是否将文件视为文本或二进制文件?
答案 0 :(得分:33)
builtin_diff()
1 调用diff_filespec_is_binary()
调用buffer_is_binary()
,它检查前8000字节中是否出现零字节(NUL“字符”)(或者整个长度如果更短)。
我没有看到这个“它是二进制吗?”测试是在任何命令中明确公开的。
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
之类的字符串,应该很熟悉。
答案 1 :(得分:24)
git grep -I --name-only --untracked -e . -- ascii.dat binary.dat ...
将返回git解释为文本文件的文件名。
您可以使用通配符,例如
git grep -I --name-only --untracked -e . -- *.ps1
答案 2 :(得分:18)
我不喜欢这个答案,但你可以解析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特别注意这个魔法)。
答案 3 :(得分:1)
# considered binary (or with bare CR) file
git ls-files --eol | grep -E '^(i/-text)'
# files that do not have any line-ending characters (including empty files) - unlikely that this is a true binary file ?
git ls-files --eol | grep -E '^(i/none)'
# via experimentation
# ------------------------
# "-text" binary (or with bare CR) file : not auto-normalized
# "none" text file without any EOL : not auto-normalized
# "lf" text file with LF : is auto-normalized when gitattributes text=auto
# "crlf" text file with CRLF : is auto-normalized when gitattributes text=auto
# "mixed" text file with mixed line endings : is auto-normalized when gitattributes text=auto
# (LF or CRLF, but not bare CR)
来源:https://git-scm.com/docs/git-ls-files#Documentation/git-ls-files.txt---eol https://github.com/git/git/commit/a7630bd4274a0dff7cff8b92de3d3f064e321359
顺便说一句:设置 .gitattributes
文本属性时要小心,例如*.abc text
。因为在这种情况下,所有 带有 *.abc
的文件都将被规范化,即使它们是二进制文件(在二进制文件中找到的内部 CRLF 将被规范化为 LF)。这与自动行为不同。
答案 4 :(得分:0)
冒着因为代码质量差而受到打击的风险,我列出了一个C实用程序is_binary,它围绕Git源中的原始buffer_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: 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 */
}
答案 5 :(得分:0)
@bonh 在评论中给出了有效的答案
<块引用>git diff --numstat 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD -- | grep "^-" |切 -f 3
它显示了 git 解释为二进制文件的所有文件。
答案 6 :(得分:0)
使用git check-attr --all
。
无论文件是否已暂存/提交,这都有效。
在 git 版本 2.30.2 上测试。
假设您在 .gitattributes
中有这个。
package-lock.json binary
有这个输出。
git check-attr --all package-lock.json
package-lock.json: binary: set
package-lock.json: diff: unset
package-lock.json: merge: unset
package-lock.json: text: unset
对于普通文件,没有输出。
git check-attr --all package.json
答案 7 :(得分:-7)
您可以使用命令行工具&#39; file&#39;效用。在Windows上,它包含在git安装中,通常位于C:\ Program Files \ git \ usr \ bin文件夹中
file --mime-encoding *
中查看详情