gitignore sem arquivos binários

141

Como os arquivos binários podem ser ignorados ao gitusar o .gitignorearquivo?

Exemplo:

$ g++ hello.c -o hello

O arquivo "Olá" é um arquivo binário. Pode gitignorar este arquivo?

Juan Pablo
fonte
2
Estou muito surpreso que uma pergunta tão antiga e importante não tenha resposta adequada. Estou ainda mais surpreso que a resposta seja direta [^\.]*.
TamaMcGlinn 3/10
isso não funciona
timotheecour 23/04

Respostas:

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
VenomVendor
fonte
1
Esta solução funciona como um encanto! Não entendo por que, ao desconsiderar todos os diretórios "! * /", Ele também pode desconsiderar os arquivos do subdir com uma extensão? (por exemplo, aaa / bbb.c), mas ainda assim ignora o arquivo do subdir sem extensões. (por exemplo aaa / ccc)
dragonxlwang 14/11
4
Parece que este método não funciona como esperado depois que eu descobri que quando há várias camadas de diretório ...
dragonxlwang
@dragonxlwang Estou curioso para saber onde isso não funcionaria? A solução aceita aqui stackoverflow.com/a/19023985/1426932 é um pouco diferente e usa em !/**/vez de !*/; qual está correto? / cc @VonC
timotheecour 25/01/19
É bastante comum na cultura Unix nomear scripts de shell e executáveis ​​binários sem extensões. Nesse caso, essa solução fará com que os scripts sejam ignorados. Uma idéia melhor é adicionar apenas executáveis ​​binários ao .gitignore manualmente sempre que forem adicionados ao projeto - normalmente isso não acontece com tanta frequência. Se isso for muito complicado, a solução makefile sugerida pelo vedantk é melhor.
Peter Helfer
Isso irá ignorar makefile
VMatrix1900
42

Adicione algo como

*.o

no arquivo .gitignore e coloque-o na raiz do seu repositório (ou você pode colocar em qualquer subdiretório que desejar - ele será aplicado a partir desse nível em diante) e faça o check-in.

Editar:

Para binários sem extensão, é melhor colocá-los em bin/ou em alguma outra pasta. Afinal, não há ignorar com base no tipo de conteúdo.

Podes tentar

*
!*.*

mas isso não é infalível.

manojlds
fonte
1
Edição adicionada. Existe alguma razão que você não quer que seu binário para ter uma extensão
manojlds
10
Os executáveis ​​geralmente não têm extensões. Estou tentando fazer a mesma coisa aqui para arquivos criados por gccpassagem -o $@.
21713 Nathan Lilienthal
29

Para anexar todos os executáveis ​​ao seu .gitignore(o que você provavelmente quer dizer com "arquivo binário" a julgar pela sua pergunta), você pode usar

find . -executable -type f >>.gitignore

Se você não se importa com o pedido de linhas no seu .gitignore, também pode atualizá-lo .gitignorecom o seguinte comando, que também remove duplicatas e mantém intacta a ordem alfabética.

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

Observe que você não pode canalizar a saída diretamente para .gitignore, porque isso truncaria o arquivo antes de catabri-lo para leitura. Além disso, você pode adicionar \! -regex '.*/.*/.*'como uma opção para descobrir se não deseja incluir arquivos executáveis ​​em subdiretórios.

icks
fonte
23

Sua melhor aposta com binários é fornecer uma extensão que você possa filtrar facilmente com um padrão padrão ou colocá-las em diretórios que você pode filtrar no nível do diretório.

A sugestão de extensão é mais aplicável no Windows, porque as extensões são padrão e basicamente necessárias, mas no Unix, você pode ou não usar extensões em seus binários executáveis. Nesse caso, você pode colocá-los em uma lixeira / pasta e adicioná bin/-los ao seu .gitignore.

No seu exemplo de escopo pequeno e muito específico, você pode simplesmente colocar hellono seu .gitignore.

Andy White
fonte
15

Você pode tentar em seu .gitignore:

*
!*.c

Essa abordagem tem muitas desvantagens, mas é aceitável para pequenos projetos.

Andrei Beliankou
fonte
3
Seria bom se você menos lista das grandes desvantagens
pjvds
A desvantagem óbvia é a ordem das regras de permissão de negação, a maneira correta é ignorar apenas arquivos indesejados, não proibir tudo e incluir apenas os arquivos desejados.
Andrei Beliankou
13

Se você estiver usando um makefile, tente modificar as regras do make para anexar os nomes dos novos binários ao seu arquivo .gitignore.

Aqui está um exemplo de Makefile para um pequeno projeto Haskell;

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

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

Este makefile define uma regra para criar executáveis ​​a partir do código Haskell. Depois que o ghc é chamado, verificamos o .gitignore para ver se o binário já está nele. Caso contrário, anexamos o nome do binário ao arquivo.

vedantk
fonte
Agora, esse é um tipo de abordagem diferente.
René Nyffenegger 18/01/19
5

Aqui está outra solução usando o arquivo. Dessa forma, os scripts executáveis ​​não terminarão no gitignore. Pode ser necessário alterar como a saída do arquivo é interpretada para corresponder ao seu sistema. Pode-se então configurar um gancho de pré-confirmação para chamar esse script toda vez que você confirmar.

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)
Tyler Earnest
fonte
Criei um script semelhante e postei em uma pergunta duplicada: stackoverflow.com/a/28258619/218294 Seu código é mais agradável :) o meu provavelmente roda mais rápido, pois executa o "arquivo" apenas uma vez ou algumas vezes (usando xargs).
Sam Watkins
4

Uma maneira de também ignorar em alguns subdiretórios, não apenas em uma raiz:

# 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/**/*.*

Ou, se você deseja incluir apenas alguns tipos específicos de arquivos:

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

Parece que também pode funcionar como para cada novo subdiretório, se você quiser!

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

As barras principais são importantes apenas nas duas primeiras linhas e opcionais nas outras. Tailing barra em !/*/e !/subdir/também é opcional, mas somente nesta linha.

shaman.sir
fonte
3

Se você seguir estes comandos no arquivo .gitignore e os arquivos ainda parecerem exibidos, convém tentar:

git rm --cached FILENAME

Depois disso, adicione seu .gitignore, commit e push. Levei 40 minutos para entender isso, espero que isso ajude novatos como eu

Shaun Peretz
fonte
2

Segmento antigo, mas ainda relevante. Eu mudei o makefile para que o arquivo binário resultante após a vinculação tenha o nome [nome do arquivo]. bin em vez de apenas [nome do arquivo]. Então eu adicionei arquivos * .bin no gitignore.
Essa rotina atende às minhas necessidades.

Nalle Haddock
fonte
1

Não conheço nenhuma outra solução, mas adicioná-las uma a uma .gitignore.

Uma maneira grosseira de testar é grep a saída do comando file:

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

EDITAR

Por que você simplesmente não nomeia seu executável hello.bin?

muhuk
fonte
Como nomear executáveis ​​com a extensão do arquivo .biné uma prática recomendada.
MD XF
1

Basta adicionar helloou /helloao seu .gitignore. Qualquer um funciona.

Travis Reeder
fonte
Isso também ignorará uma pasta chamada hello.
Patrick D'appollonio
0

Criei um arquivo .gitignore com duas entradas no diretório GOPATH.

/bin
/pkg

Ignora todos os desenvolvimentos compilados atualmente.

gszecsenyi
fonte
0

.gitignore usa programação glob para filtrar arquivos, pelo menos no Linux.

Estou prestes a dar uma palestra sobre codificação em um Meetup e, em preparação, criei um diretório com vários subdiretórios nomeados de acordo com a ordem em que quero apresentá-los: 01_subject1, 02_subject2, 03_subject3. Cada subdiretório contém um arquivo de origem com uma extensão dependente do idioma que é compilada em um arquivo executável cujo nome corresponde ao nome do arquivo de origem sem a extensão, de acordo com a prática comum.

Excluo os arquivos compilados nos diretórios prefixados com números com a seguinte linha .gitignore:

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

De acordo com meu entendimento da documentação, ela não deve funcionar. O asterisco à direita deve falhar porque deve corresponder a qualquer número de caracteres não especificados, incluindo o '.' + extensão. A omissão do asterisco à direita deve falhar (e falha) porque [!\.]corresponde apenas a um caractere que não seja ponto final. No entanto, adicionei o asterisco à direita, como faria com uma expressão regular, e ele funciona. Por trabalho, quero dizer que o git percebe alterações no arquivo de origem, mas não a existência ou alterações nos arquivos compilados.

chuckj
fonte
0

Com base na resposta VenomVendors

# Ignore all
*

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

# Unignore Makefiles recursively
!**/Makefile

# other .gitignore rules...
Eero Aaltonen
fonte
0

Adicione o seguinte ao seu arquivo .gitignore:

[^\.]*

Explicação:

[] 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"
TamaMcGlinn
fonte
0

O .gitignoremecanismo funciona apenas com base nos nomes dos arquivos , não no conteúdo do arquivo . Ser um arquivo binário é uma propriedade do conteúdo; portanto, você não pode pedir ao git ignore os arquivos binários diretamente, mas apenas ignorá-los por nome (e como sugerido, você pode adicionar todos os nomes de arquivos binários ao seu .gitignorecomputador ou usar um método apropriado. convenção de nomes).

O fato de .gitignorefuncionar com nomes de arquivo é uma propriedade importante em termos de desempenho: o Git só precisa listar arquivos, mas não abri-los e lê-los para saber quais arquivos ignorar. Em outras palavras, o Git seria terrivelmente lento se você pedisse para ignorar arquivos com base no conteúdo deles.

Matthieu Moy
fonte