gitignore没有二进制文件


141

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

例:

$ g++ hello.c -o hello

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



2
我很惊讶如此古老而重要的问题没有适当的答案。答案是直截了当的,我更感到惊讶[^\.]*
TamaMcGlinn

这行不通
timotheecour

Answers:


136
# 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

1
这个解决方案就像一个魅力!我不明白为什么通过忽略所有目录“!* /”,它也可以忽略扩展名为subdir的文件?(例如aaa / bbb.c),但仍会忽略不带扩展名的subdir文件。(例如aaa / ccc)
dragonxlwang 2015年

4
我发现有多层目录时,似乎此方法无法按预期工作...
dragonxlwang 2015年

@dragonxlwang我很好奇这在哪里不起作用?这里的stackoverflow.com/a/19023985/1426932可接受的解决方案 略有不同,使用!/**/代替!*/;哪一个是正确的?/ cc @VonC
timotheecour

在Unix文化中,命名外壳程序脚本以及不带扩展名的二进制可执行文件是相当普遍的,在这种情况下,此解决方案将导致脚本被忽略。一个更好的主意是,只要将二进制可执行文件添加到项目中,就手动将它们添加到.gitignore中-通常不会经常发生这种情况。如果那太麻烦了,那么vedantk建议的makefile解决方案更好。
彼得·海弗

这将忽略makefile
VMatrix1900

42

添加类似

*.o

在.gitignore文件中,并将其放置在仓库的根目录中(或者您可以将其放置在所需的任何子目录中-从该级别开始应用),然后将其检入。

编辑:

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

你可以试试

*
!*.*

但这不是万无一失的。


1
添加了编辑。有什么理由不希望您的二进制文件具有扩展名
manojlds 2011年

10
可执行文件通常没有扩展名。我正在尝试对gcc通过创建的文件做同样的事情-o $@
内森·利连塔尔

29

要将所有可执行文件附加到您的.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 '.*/.*/.*'一个选项来查找是否不想在子目录中包括可执行文件。


23

使用二进制文件最好的选择是给它们一个扩展名,您可以使用标准模式轻松地将其过滤掉,或者将它们放入可以在目录级别过滤掉的目录中。

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

在非常具体的小范围示例中,您只需hello输入.gitignore。



13

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

这是一个小的Haskell项目的示例Makefile。

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

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

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


现在,这是一种不同的方法。
勒内Nyffenegger


5

这是另一个使用文件的解决方案。这样,可执行脚本将不会以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)

我做了一个类似的脚本,并发布了一个重复的问题: stackoverflow.com/a/28258619/218294 您的代码更好:)我的代码运行得更快,因为它只运行一次或多次“文件”(使用xargs)。
山姆·沃特金斯

4

一种在某些子目录中也不仅在根目录中也忽略的方法:

# 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/也是可选的,但仅限于此行。


3

如果对.gitignore文件执行以下命令,但文件似乎仍然出现,则可能需要尝试:

git rm --cached FILENAME

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


2

旧线程,但仍然相关。我更改了makefile,因此链接后生成的二进制文件的名称为[filname]。bin,而不只是[filname]。然后我在gitignore中添加了* .bin文件。
这个例行程序满足了我的需求。


1

我没有其他解决方案,只能将它们一个接一个地添加到中.gitignore

一种简单的测试方法是grep file命令的输出:

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

编辑

为什么不简单地命名可执行文件hello.bin


因为用文件扩展名命名可执行文件.bin是不好的做法。
MD XF


0

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

/bin
/pkg

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


0

.gitignore使用Glob编程至少在Linux上来过滤文件。

我将在一次Meetup上进行编码讨论,并且在准备过程中,我创建了一个目录,其中包含几个子目录,这些子目录根据我想要显示的顺序命名:01_subject1、02_subject2、03_subject3。每个子目录都包含一个源文件,该文件具有与语言相关的扩展名,根据常规惯例,该文件会编译为名称与源文件名匹配且没有扩展名的可执行文件。

我使用以下.gitignore行将编译后的文件排除在数字前缀目录中:

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

根据我对文档的理解,它不起作用。星号结尾应失败,因为它应与任意数量的未指定字符匹配,包括“。”。+扩展名。省略结尾的星号应该会失败(并且确实会失败),因为[!\.]仅匹配一个非句点字符。但是,我像在正则表达式中一样添加了结尾的星号,并且可以使用。通过工作,我的意思是git注意到对源文件的更改,但没有注意到已编译文件的存在或更改。



0

将以下内容添加到您的.gitignore文件中:

[^\.]*

说明:

[] 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"

0

.gitignore机制仅基于文件而不是文件内容起作用。作为二进制文件是内容的属性,因此您不能要求git直接忽略二进制文件,而只能按名称忽略它们(如其他建议,您可以将所有二进制文件名添加到您的文件中,也可以.gitignore使用适当的名称命名约定)。

.gitignore在文件名上起作用的事实是性能方面重要的属性:Git仅需要列出文件,而无需打开和读取文件即可知道要忽略的文件。换句话说,如果您可以要求Git根据文件的内容忽略文件,它的运行速度将非常慢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.