Come si possono ignorare i file binari git
usando il .gitignore
file?
Esempio:
$ g++ hello.c -o hello
Il file "ciao" è un file binario. Puoi git
ignorare questo file?
[^\.]*
.
Come si possono ignorare i file binari git
usando il .gitignore
file?
Esempio:
$ g++ hello.c -o hello
Il file "ciao" è un file binario. Puoi git
ignorare questo file?
[^\.]*
.
Risposte:
# 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
!/**/
invece di !*/
; quale è corretto? / cc @VonC
Aggiungi qualcosa di simile
*.o
nel file .gitignore e posizionalo nella radice del tuo repository (oppure puoi inserirlo in qualsiasi sottodirectory che desideri - si applicherà da quel livello in poi) e archiviarlo.
Modificare:
Per i binari senza estensione, è meglio posizionarli in bin/
un'altra cartella. Dopotutto non è possibile ignorare in base al tipo di contenuto.
Puoi provare
*
!*.*
ma questo non è infallibile.
gcc
passando -o $@
.
Per aggiungere tutti i file eseguibili al tuo .gitignore
(che probabilmente intendi per "file binario" a giudicare dalla tua domanda), puoi usare
find . -executable -type f >>.gitignore
Se non ti interessa ordinare le linee nel tuo .gitignore
, potresti anche aggiornare il tuo .gitignore
con il seguente comando che rimuove anche i duplicati e mantiene intatto l'ordine alfabetico.
T=$(mktemp); (cat .gitignore; find . -executable -type f | sed -e 's%^\./%%') | sort | uniq >$T; mv $T .gitignore
Si noti che non è possibile reindirizzare direttamente l'output .gitignore
, poiché ciò troncerebbe il file prima di cat
aprirlo per la lettura. Inoltre, potresti voler aggiungere \! -regex '.*/.*/.*'
un'opzione per trovare se non vuoi includere file eseguibili nelle sottodirectory.
La tua scommessa migliore con i binari è quella di dare loro un'estensione che puoi facilmente filtrare con uno schema standard, o metterli in directory che puoi filtrare a livello di directory.
Il suggerimento di estensione è più applicabile in Windows, poiché le estensioni sono standard e fondamentalmente richieste, ma in Unix è possibile o meno utilizzare estensioni nei file binari eseguibili. In questo caso, puoi metterli in un bin / cartella e aggiungerli bin/
al tuo .gitignore.
Nel tuo esempio molto specifico, di portata ridotta, puoi semplicemente inserire il hello
tuo .gitignore.
Puoi provare nel tuo .gitignore
:
*
!*.c
Questo approccio presenta molti svantaggi, ma è accettabile per piccoli progetti.
Se stai usando un makefile, potresti provare a modificare le tue regole di make per aggiungere i nomi di nuovi binari al tuo file .gitignore.
Ecco un Makefile di esempio per un piccolo progetto Haskell;
all: $(patsubst %.hs, %, $(wildcard *.hs))
%: %.hs
ghc $^
grep -xq "$@" .gitignore || echo $@ >> .gitignore
Questo makefile definisce una regola per la creazione di eseguibili dal codice Haskell. Dopo aver richiamato ghc, controlliamo il file .gitignore per vedere se il binario è già in esso. In caso contrario, aggiungiamo il nome del file binario al file.
I file binari sono spesso senza estensioni. Se questo è il tuo caso, prova questo:
*
!/**/
!*.*
Ecco un'altra soluzione che utilizza il file. In questo modo gli script eseguibili non finiranno in gitignore. Potrebbe essere necessario modificare il modo in cui l'output del file viene interpretato in base al sistema in uso. Si potrebbe quindi impostare un hook pre-commit per chiamare questo script ogni volta che si commette.
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)
Un modo per ignorare anche in alcuni sottodir, non solo in una radice:
# 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/**/*.*
Oppure, se si desidera includere solo alcuni tipi specifici di file:
/*
!/*.c
!/*.h
!/subdir/
/subdir/**/*
!/subdir/**/
!/subdir/**/*.c
!/subdir/**/*.h
Sembra che potrebbe anche funzionare come per ogni nuova sottodirectory, se vuoi !:
/*
!/*.c
!/*.h
!/*/
/*/**/*
!/*/**/
!/*/**/*.c
!/*/**/*.h
Le barre iniziali sono importanti solo nelle prime due righe e facoltative nelle altre. Tailing barra in !/*/
ed !/subdir/
è opzionale, ma solo in questa linea.
Se segui questi comandi sul tuo file .gitignore e i file sembrano ancora apparire, potresti provare:
git rm --cached FILENAME
Successivamente, aggiungi il tuo .gitignore, esegui il commit e il push. Mi ci sono voluti 40 minuti per capirlo, spero che questo aiuti ai neofiti come me
Vecchio thread, ma ancora rilevante. Ho modificato il makefile in modo che il file binario risultante dopo il collegamento abbia il nome [nomefile]. bin anziché solo [nome file]. Quindi ho aggiunto i file * .bin in gitignore.
Questa routine soddisfa i miei bisogni.
Non conosco altre soluzioni, ma aggiungendole una ad una a .gitignore
.
Un modo grezzo per testare è grep l'output del comando file:
find . \( ! -regex '.*/\..*' \) -type f | xargs -n 1 file | egrep "ASCII|text"
MODIFICARE
Perché non ti chiami semplicemente eseguibile hello.bin
?
.bin
è una cattiva pratica.
Basta aggiungere hello
o /hello
al vostro .gitignore. Funziona entrambi.
hello
.
Ho creato un file .gitignore con due voci nella directory GOPATH.
/bin
/pkg
Attualmente ignora tutti gli sviluppi compilati.
.gitignore utilizza la programmazione glob per filtrare i file, almeno su Linux.
Sto per tenere un discorso di programmazione in un Meetup e, in preparazione, ho creato una directory con diverse sottodirectory che sono nominate in base all'ordine che voglio presentarle: 01_subject1, 02_subject2, 03_subject3. Ogni sottodirectory contiene un file di origine con un'estensione dipendente dalla lingua che viene compilata in un file eseguibile il cui nome corrisponde al nome del file di origine senza l'estensione secondo la prassi comune.
Escludo i file compilati nelle directory con prefisso numerale con la seguente riga .gitignore:
[0-9][0-9]_*/[!\.]*
Secondo la mia comprensione della documentazione, non dovrebbe funzionare. Avere l'asterisco finale dovrebbe fallire perché dovrebbe corrispondere a qualsiasi numero di caratteri non specificati, incluso il '.' + estensione. L'omissione dell'asterisco finale dovrebbe fallire (e lo fa) perché [!\.]
corrisponde a un solo carattere non punto. Tuttavia, ho aggiunto l'asterisco finale, come farei per un'espressione regolare, e funziona. Per lavoro, intendo che git nota le modifiche al file sorgente, ma non l'esistenza o le modifiche ai file compilati.
Basandosi sulla risposta di VenomVendors
# Ignore all
*
# Unignore all files with extensions recursively
!**/*.*
# Unignore Makefiles recursively
!**/Makefile
# other .gitignore rules...
Aggiungi quanto segue al tuo file .gitignore:
[^\.]*
Spiegazione:
[] 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"
Il .gitignore
meccanismo funziona solo in base ai nomi dei file , non al contenuto dei file . Essere un file binario è una proprietà del contenuto, quindi non puoi chiedere a git di ignorare direttamente i file binari, ma solo di ignorarli per nome (e come altri hanno suggerito, puoi aggiungere tutti i nomi di file binari al tuo .gitignore
o usare un appropriato convenzione di denominazione).
Il fatto che .gitignore
funzioni sui nomi dei file è un'importante proprietà dal punto di vista delle prestazioni: Git deve solo elencare i file, ma non aprirli e leggerli per sapere quali file ignorare. In altre parole, Git sarebbe terribilmente lento se potessi chiedergli di ignorare i file in base al loro contenuto.