Como os arquivos binários podem ser ignorados ao git
usar o .gitignore
arquivo?
Exemplo:
$ g++ hello.c -o hello
O arquivo "Olá" é um arquivo binário. Pode git
ignorar este arquivo?
[^\.]*
.
Como os arquivos binários podem ser ignorados ao git
usar o .gitignore
arquivo?
Exemplo:
$ g++ hello.c -o hello
O arquivo "Olá" é um arquivo binário. Pode git
ignorar este arquivo?
[^\.]*
.
Respostas:
# 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
!/**/
vez de !*/
; qual está correto? / cc @VonC
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.
gcc
passagem -o $@
.
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 .gitignore
com 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 cat
abri-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.
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 hello
no seu .gitignore.
Você pode tentar em seu .gitignore
:
*
!*.c
Essa abordagem tem muitas desvantagens, mas é aceitável para pequenos projetos.
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.
Arquivos binários geralmente não possuem extensões. Se este for o seu caso, tente o seguinte:
*
!/**/
!*.*
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)
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.
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
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.
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
?
.bin
é uma prática recomendada.
Basta adicionar hello
ou /hello
ao seu .gitignore. Qualquer um funciona.
hello
.
Criei um arquivo .gitignore com duas entradas no diretório GOPATH.
/bin
/pkg
Ignora todos os desenvolvimentos compilados atualmente.
.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.
Com base na resposta VenomVendors
# Ignore all
*
# Unignore all files with extensions recursively
!**/*.*
# Unignore Makefiles recursively
!**/Makefile
# other .gitignore rules...
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"
O .gitignore
mecanismo 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 .gitignore
computador ou usar um método apropriado. convenção de nomes).
O fato de .gitignore
funcionar 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.