Gitignore ohne Binärdateien

141

Wie können Binärdateien bei der gitVerwendung der .gitignoreDatei ignoriert werden ?

Beispiel:

$ g++ hello.c -o hello

Die "Hallo" -Datei ist eine Binärdatei. Kann gitdiese Datei ignorieren?

Juan Pablo
quelle
2
Ich bin sehr überrascht, dass eine so alte und wichtige Frage keine richtige Antwort hat. Ich bin noch mehr überrascht, dass die Antwort einfach ist [^\.]*.
TamaMcGlinn
das funktioniert nicht
timotheecour

Antworten:

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
quelle
1
Diese Lösung funktioniert wie ein Zauber! Ich verstehe nicht, warum durch Aufheben der Registrierung aller Verzeichnisse "! * /" Auch die Dateien des Unterverzeichnisses mit einer Erweiterung aufgehoben werden können. (zB aaa / bbb.c), ignorieren Sie jedoch die Datei des Unterverzeichnisses ohne Erweiterungen. (zB aaa / ccc)
Dragonxlwang
4
Scheint, dass diese Methode nicht wie erwartet funktioniert, nachdem ich festgestellt habe, dass es mehrere Ebenen des Verzeichnisses gibt ...
dragonxlwang
@dragonxlwang Ich bin neugierig, wo würde das nicht funktionieren? Die hier akzeptierte Lösung stackoverflow.com/a/19023985/1426932 unterscheidet sich geringfügig und wird !/**/anstelle von verwendet !*/. Welches ist korrekt? / cc @VonC
timotheecour
In der Unix-Kultur ist es ziemlich üblich, Shell-Skripte sowie ausführbare Binärdateien ohne Erweiterungen zu benennen. In diesem Fall werden bei dieser Lösung Skripte ignoriert. Eine bessere Idee ist es, binäre ausführbare Dateien einfach manuell zu .gitignore hinzuzufügen, wenn sie dem Projekt hinzugefügt werden - dies kommt normalerweise nicht allzu oft vor. Wenn das zu umständlich ist, ist die von vedantk vorgeschlagene Makefile-Lösung besser.
Peter Helfer
Dies ignoriert Makefile
VMatrix1900
42

Fügen Sie so etwas hinzu

*.o

in der .gitignore-Datei und platzieren Sie es im Stammverzeichnis Ihres Repos (oder Sie können es in einem beliebigen Unterverzeichnis ablegen - es gilt ab dieser Ebene) und checken Sie es ein.

Bearbeiten:

Bei Binärdateien ohne Erweiterung sollten Sie sie besser in bin/einem anderen Ordner ablegen. Immerhin gibt es kein Ignorieren basierend auf dem Inhaltstyp.

Du kannst es versuchen

*
!*.*

aber das ist nicht kinderleicht.

manojlds
quelle
1
Bearbeiten hinzugefügt. Gibt es einen Grund, warum Sie nicht möchten, dass Ihre Binärdatei eine Erweiterung hat
manojlds
10
Ausführbare Dateien haben häufig keine Erweiterungen. Ich versuche hier dasselbe für Dateien zu tun, die durch gccÜbergeben erstellt wurden -o $@.
Nathan Lilienthal
29

Um alle ausführbaren Dateien an Ihre anzuhängen .gitignore(was Sie wahrscheinlich mit "Binärdatei" meinen, gemessen an Ihrer Frage), können Sie verwenden

find . -executable -type f >>.gitignore

Wenn Sie sich nicht für die Reihenfolge der Zeilen in Ihrem interessieren .gitignore, können Sie Ihre auch .gitignoremit dem folgenden Befehl aktualisieren, der auch Duplikate entfernt und die alphabetische Reihenfolge beibehält.

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

Beachten Sie, dass Sie die Ausgabe nicht direkt an weiterleiten können .gitignore, da dadurch die Datei abgeschnitten wird, bevor catsie zum Lesen geöffnet wird. Möglicherweise möchten Sie \! -regex '.*/.*/.*'auch eine Option hinzufügen, um festzustellen, ob Sie keine ausführbaren Dateien in Unterverzeichnisse aufnehmen möchten.

icks
quelle
23

Bei Binärdateien ist es am besten, ihnen entweder eine Erweiterung zu geben, die Sie einfach mit einem Standardmuster herausfiltern können, oder sie in Verzeichnisse zu legen, die Sie auf Verzeichnisebene herausfiltern können.

Der Erweiterungsvorschlag ist in Windows besser anwendbar, da Erweiterungen Standard sind und grundsätzlich erforderlich sind. Unter Unix können Sie jedoch Erweiterungen für Ihre ausführbaren Binärdateien verwenden oder nicht. In diesem Fall können Sie sie in einen Bin / Ordner legen und bin/Ihrem .gitignore hinzufügen .

In Ihrem sehr spezifischen Beispiel mit kleinem Umfang können Sie einfach helloIhren .gitignore eingeben.

Andy White
quelle
15

Sie können versuchen in Ihrem .gitignore:

*
!*.c

Dieser Ansatz hat viele Nachteile, ist jedoch für kleine Projekte akzeptabel.

Andrei Beliankou
quelle
3
Es wäre schön, wenn Sie am wenigsten die Hauptnachteile
auflisten würden
Der offensichtliche Nachteil ist die Reihenfolge der Zulassungsverweigerungsregeln. Der richtige Weg besteht darin, nur unerwünschte Dateien zu ignorieren, nicht alle zu verbieten und dann nur die gewünschten Dateien einzuschließen.
Andrei Beliankou
13

Wenn Sie ein Makefile verwenden, können Sie versuchen, Ihre Make-Regeln zu ändern, um die Namen neuer Binärdateien an Ihre Gitignore-Datei anzuhängen.

Hier ist ein Beispiel für ein Makefile für ein kleines Haskell-Projekt.

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

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

Dieses Makefile definiert eine Regel zum Erstellen ausführbarer Dateien aus Haskell-Code. Nachdem ghc aufgerufen wurde, überprüfen wir den .gitignore, um festzustellen, ob die Binärdatei bereits darin enthalten ist. Ist dies nicht der Fall, hängen wir den Namen der Binärdatei an die Datei an.

vedantk
quelle
Dies ist ein anderer Ansatz.
René Nyffenegger
5

Hier ist eine andere Lösung mit Datei. Auf diese Weise landen ausführbare Skripte nicht in gitignore. Möglicherweise müssen Sie die Interpretation der Dateiausgabe an Ihr System anpassen. Sie können dann einen Pre-Commit-Hook einrichten, um dieses Skript bei jedem Commit aufzurufen.

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
quelle
Ich habe ein ähnliches Skript erstellt und eine doppelte Frage gestellt: stackoverflow.com/a/28258619/218294 Ihr Code ist besser :) Mein Code wird wahrscheinlich schneller ausgeführt, da "Datei" nur einmal oder einige Male (mit xargs) ausgeführt wird.
Sam Watkins
4

Eine Möglichkeit, auch in einigen Unterverzeichnissen zu ignorieren, nicht nur in einer Wurzel:

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

Oder wenn Sie nur bestimmte Dateitypen einschließen möchten:

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

Scheint, als könnte es sogar für jedes neue Unterverzeichnis funktionieren, wenn Sie wollen!:

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

Führende Schrägstriche sind nur in den ersten beiden Zeilen wichtig und in anderen optional. Tailing Slash In !/*/und !/subdir/ist ebenfalls optional, jedoch nur in dieser Zeile.

shaman.sir
quelle
3

Wenn Sie diese Befehle in Ihrer .gitignore-Datei befolgen und die Dateien weiterhin angezeigt werden, möchten Sie möglicherweise Folgendes versuchen:

git rm --cached FILENAME

Fügen Sie danach Ihren .gitignore hinzu, legen Sie fest und drücken Sie. Ich habe 40 Minuten gebraucht, um das zu verstehen. Ich hoffe, das hilft Neulingen wie mir

Shaun Peretz
quelle
2

Alter Thread, aber immer noch relevant. Ich habe das Makefile so geändert, dass die resultierende Binärdatei nach dem Verknüpfen den Namen [Dateiname] hat. bin statt nur [filname]. Dann habe ich * .bin-Dateien im Gitignore hinzugefügt.
Diese Routine erfüllt meine Bedürfnisse.

Nalle Haddock
quelle
1

Ich kenne keine andere Lösung, als sie einzeln hinzuzufügen .gitignore.

Eine grobe Methode zum Testen besteht darin, die Ausgabe des Dateibefehls zu überprüfen:

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

BEARBEITEN

Warum benennst du dich nicht einfach ausführbar hello.bin?

Muhuk
quelle
Weil das Benennen von ausführbaren Dateien mit der Dateierweiterung .bineine schlechte Praxis ist.
MD XF
1

Fügen Sie einfach hellooder /hellozu Ihrem .gitignore. Entweder funktioniert.

Travis Reeder
quelle
Dadurch wird auch ein Ordner namens ignoriert hello.
Patrick D'appollonio
0

Ich habe eine Gitignore-Datei mit zwei Einträgen im GOPATH-Verzeichnis erstellt.

/bin
/pkg

Derzeit werden alle kompilierten Entwicklungen ignoriert.

gszecsenyi
quelle
0

.gitignore verwendet Glob-Programmierung , um Dateien zu filtern, zumindest unter Linux.

Ich bin dabei, bei einem Meetup einen Codierungsvortrag zu halten, und habe in Vorbereitung ein Verzeichnis mit mehreren Unterverzeichnissen erstellt, die in der Reihenfolge benannt sind, in der ich sie präsentieren möchte: 01_subject1, 02_subject2, 03_subject3. Jedes Unterverzeichnis enthält eine Quelldatei mit einer sprachabhängigen Erweiterung, die zu einer ausführbaren Datei kompiliert wird, deren Name mit dem Namen der Quelldatei ohne die Erweiterung gemäß der gängigen Praxis übereinstimmt.

Ich schließe die kompilierten Dateien in den Verzeichnissen mit vorangestellten Ziffern mit der folgenden .gitignore-Zeile aus:

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

Nach meinem Verständnis der Dokumentation sollte es nicht funktionieren. Das nachfolgende Sternchen sollte fehlschlagen, da es mit einer beliebigen Anzahl nicht angegebener Zeichen übereinstimmen sollte, einschließlich des '.' + Erweiterung. Das Weglassen des nachfolgenden Sterns sollte fehlschlagen (und tut dies auch), da [!\.]nur ein einzelnes Zeichen ohne Punkt übereinstimmt. Ich habe jedoch das abschließende Sternchen hinzugefügt, wie ich es für einen regulären Ausdruck tun würde, und es funktioniert. Mit Arbeit meine ich, dass Git Änderungen an der Quelldatei bemerkt, aber nicht die Existenz oder Änderungen an den kompilierten Dateien.

chuckj
quelle
0

Aufbauend auf der Antwort von VenomVendors

# Ignore all
*

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

# Unignore Makefiles recursively
!**/Makefile

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

Fügen Sie Ihrer .gitignore-Datei Folgendes hinzu:

[^\.]*

Erläuterung:

[] 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
quelle
0

Der .gitignoreMechanismus funktioniert auf Datei nur anhand Namen , nicht auf Dateiinhalte . Eine Binärdatei zu sein ist eine Eigenschaft des Inhalts, daher können Sie git nicht bitten, Binärdateien direkt zu ignorieren, sondern sie nur nach Namen zu ignorieren (und wie andere vorgeschlagen, können Sie entweder alle Binärdateinamen zu Ihren hinzufügen.gitignore oder eine geeignete verwenden Namenskonvention).

Die Tatsache, dass .gitignoremit Dateinamen gearbeitet wird, ist eine wichtige Eigenschaft in Bezug auf die Leistung: Git muss nur Dateien auflisten, aber nicht öffnen und lesen, um zu wissen, welche Dateien ignoriert werden sollen. Mit anderen Worten, Git wäre furchtbar langsam, wenn Sie ihn bitten könnten, Dateien aufgrund ihres Inhalts zu ignorieren.

Matthieu Moy
quelle