Gitignore二进制文件,没有扩展名

如何使用.gitignore文件在git中忽略二进制文件?

例子:

$ g++ hello.c -o hello

“hello”文件是二进制文件。git可以忽略这个文件吗?

103075 次浏览

添加如下内容

*.o

在.gitignore文件中,把它放在你的repo的根目录下(或者你可以把它放在你想要的任何子目录中——它将从那个级别应用),然后签入。

编辑:

对于没有扩展名的二进制文件,最好将它们放在bin/或其他文件夹中。毕竟没有基于内容类型的忽略。

你可以试试

*
!*.*

但这并非万无一失。

对于二进制文件,最好的办法是为它们提供一个可以用标准模式轻松过滤掉的扩展名,或者将它们放入可以在目录级别过滤掉的目录中。

扩展建议在Windows中更适用,因为扩展是标准的,并且基本上是必需的,但在Unix中,您可以对可执行二进制文件使用扩展,也可以不使用扩展。在这种情况下,你可以把它们放在bin/文件夹中,并将bin/添加到你的.gitignore中。

在您非常具体的小范围示例中,您可以将hello放在.gitignore中。

我不知道任何其他解决方案,但将它们一个接一个地添加到.gitignore

一个粗略的测试方法是grep文件命令的输出:

find . \( ! -regex '.*/\..*' \) -type f | xargs -n 1 file | egrep "ASCII|text"

编辑

为什么不直接将可执行文件命名为hello.bin呢?

要将所有可执行文件附加到.gitignore(从你的问题判断,你可能指的是“二进制文件”),你可以使用

find . -executable -type f >>.gitignore

如果你不关心.gitignore中的行顺序,你也可以用下面的命令更新你的.gitignore,它也会删除重复项并保持字母顺序不变。

T=$(mktemp); (cat .gitignore; find . -executable -type f | sed -e 's%^\./%%') | sort | uniq >$T; mv $T .gitignore

注意,不能将输出直接输送到.gitignore,因为这会在cat打开文件以供读取之前截断文件。此外,如果你不想在子目录中包含可执行文件,你可能想添加\! -regex '.*/.*/.*'作为一个选项来查找。

你可以在你的.gitignore中尝试:

*
!*.c

这种方法有很多缺点,但对于小型项目是可以接受的。

如果您正在使用makefile,可以尝试修改make规则,将新二进制文件的名称附加到.gitignore文件中。

下面是一个小型Haskell项目的Makefile示例;

all: $(patsubst %.hs, %, $(wildcard *.hs))


%: %.hs
ghc $^
grep -xq "$@" .gitignore || echo $@ >> .gitignore

这个makefile定义了一个用Haskell代码创建可执行文件的规则。在ghc被调用之后,我们检查.gitignore,看看二进制文件是否已经在其中。如果不是,我们将二进制文件的名称附加到文件中。

这是另一个使用文件的解决方案。这样,可执行脚本就不会在gitignore中结束。您可能需要更改文件输出的解释方式,以匹配您的系统。然后可以设置一个预提交钩子,以便在每次提交时调用此脚本。

import subprocess, os


git_root = subprocess.check_output(['git', 'root']).decode("UTF-8").strip()
exes = []
cut = len(git_root)


for root, dirnames, filenames in os.walk(git_root+"/src/"):
for fname in filenames:
f = os.path.join(root,fname)
if not os.access(f,os.X_OK):
continue


ft = subprocess.check_output(['file', f]).decode("UTF-8")


if 'ELF' in ft and 'executable' in ft:
exes.append(f[cut:])


gifiles = [ str.strip(a) for a in open(git_root + "/.gitignore").readlines() ]
gitignore=frozenset(exes+gifiles)


with open(git_root+"/.gitignore", "w") as g:
for a in sorted(gitignore):
print(a, file=g)

在某些子目录中也可以忽略,而不仅仅是在根目录中:

# Ignore everything in a root
/*
# But not files with extension located in a root
!/*.*
# And not my subdir (by name)
!/subdir/
# Ignore everything inside my subdir on any level below
/subdir/**/*
# A bit of magic, removing last slash or changing combination with previous line
# fails everything. Though very possibly it just says not to ignore sub-sub-dirs.
!/subdir/**/
# ...Also excluding (grand-)children files having extension on any level
# below subdir
!/subdir/**/*.*

或者,如果你只想包含一些特定类型的文件:

/*
!/*.c
!/*.h
!/subdir/
/subdir/**/*
!/subdir/**/
!/subdir/**/*.c
!/subdir/**/*.h

如果你想的话,它甚至可以像每个新子目录一样工作!:

/*
!/*.c
!/*.h
!/*/
/*/**/*
!/*/**/
!/*/**/*.c
!/*/**/*.h

前导斜杠只在前两行中重要,在其他行中是可选的。!/*/!/subdir/中的尾斜杠也是可选的,但仅在这一行中。

# Ignore all
*


# Unignore all with extensions
!*.*


# Unignore all dirs
!*/


### Above combination will ignore all files without extension ###


# Ignore files with extension `.class` & `.sm`
*.class
*.sm


# Ignore `bin` dir
bin/
# or
*/bin/*


# Unignore all `.jar` in `bin` dir
!*/bin/*.jar


# Ignore all `library.jar` in `bin` dir
*/bin/library.jar


# Ignore a file with extension
relative/path/to/dir/filename.extension


# Ignore a file without extension
relative/path/to/dir/anotherfile

只要在.gitignore中添加hello/hello即可。要么工作。

我在GOPATH目录中创建了一个包含两个条目的.gitignore文件。

/bin
/pkg

目前,它忽略所有已编译的开发。

.gitignore使用水珠编程来过滤文件,至少在Linux上是这样。

我准备在一个Meetup上做一个编码演讲,在准备过程中,我创建了一个包含几个子目录的目录,这些子目录根据我想要呈现它们的顺序命名:01_subject1, 02_subject2, 03_subject3。每个子目录都包含一个源文件,其扩展名与语言相关,可编译为一个可执行文件,根据惯例,该文件的名称与不带扩展名的源文件名匹配。

我排除了以下.gitignore行以数字为前缀的目录中的编译文件:

[0-9][0-9]_*/[!\.]*

根据我对文档的理解,它不应该工作。后面有星号应该会失败,因为它应该匹配任意数量的未指定字符,包括'。' +扩展名。省略后面的星号应该会失败(而且确实会),因为[!\.]只匹配一个非句点字符。然而,我添加了尾随星号,就像我对正则表达式所做的那样,它可以工作。工作,我的意思是git注意到源文件的变化,但不注意编译文件的存在或变化。

VenomVendors回答上构建

# Ignore all
*


# Unignore all files with extensions recursively
!**/*.*


# Unignore Makefiles recursively
!**/Makefile


# other .gitignore rules...

最具体的gitignore行通常是最好的,这样您就不会意外地对git隐藏文件,从而在其他人检查您的提交时导致难以诊断的问题。因此,我特别建议只对目录根目录中名为hello的文件进行命名。要做到这一点,添加:

/hello

到存储库根目录下的.gitignore文件。(也可以在存储库的其他地方有.gitignore文件,当你的git存储库包含多个项目时,这是有意义的,你可能想稍后移动这些项目,或者有一天将它们分离到自己的存储库中。)

然而,如果你真的想忽略所有没有扩展名的文件,你可以使用:

/[^\.]*

或者更不具体:

[^\.]*

解释:

/  starting with / means "only in the root of the repository"
[] encloses a character class, e.g. [a-zA-Z] means "any letter".
^  means "not"
\. means a literal dot - without the backslash . means "any character"
*  means "any number of these characters"

.gitignore机制仅基于文件的名字工作,而不是文件内容。二进制文件是内容的属性,因此你不能要求git直接忽略二进制文件,而只能通过名称忽略它们(正如其他人建议的那样,你可以将所有二进制文件名添加到.gitignore或使用适当的命名约定)。

.gitignore作用于文件名的事实是一个重要的性能属性:Git只需要列出文件,而不需要打开和读取它们来知道要忽略哪些文件。换句话说,如果您要求Git根据文件的内容忽略文件,那么Git会非常慢。

二进制文件通常没有扩展名。如果这是你的情况,试试这个:

*
!/**/
!*.*

裁判:https://stackoverflow.com/a/19023985/1060487

旧线程,但仍然相关。 我改变了makefile,因此链接后的结果二进制文件具有名称[filname]。箱子而不是[filname]。然后我在gitignore中添加了*.bin文件

如果你在你的.gitignore文件上执行这些命令,文件仍然出现,你可能想尝试:

git rm --cached FILENAME

之后,添加你的.gitignore,提交并推送。 我花了40分钟才明白,希望这对像我这样的新手有帮助