gitignore sans fichiers binaires


141

Comment les fichiers binaires peuvent-ils être ignorés lors de l' gitutilisation du .gitignorefichier?

Exemple:

$ g++ hello.c -o hello

Le fichier "bonjour" est un fichier binaire. Peut gitignorer ce fichier?



2
Je suis très surpris qu'une question aussi ancienne et importante n'ait pas de réponse appropriée. Je suis encore plus surpris que la réponse soit simple [^\.]*.
TamaMcGlinn

ça ne marche pas
timotheecour

Réponses:


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
Cette solution fonctionne comme un charme! Je ne comprends pas pourquoi en annulant tous les répertoires "! * /", Il peut également annuler les fichiers de sous-répertoire avec une extension? (par exemple aaa / bbb.c) mais ignore toujours le fichier de sous-répertoire sans extensions. (par exemple aaa / ccc)
dragonxlwang

4
Il semble que cette méthode ne fonctionne pas comme prévu après avoir constaté que lorsqu'il y a plusieurs couches de répertoire ...
dragonxlwang

@dragonxlwang Je suis curieux de savoir où cela ne fonctionnerait pas? La solution acceptée ici stackoverflow.com/a/19023985/1426932 est légèrement différente et utilise à la !/**/place de !*/; laquelle est correcte? / cc @VonC
timotheecour

Il est assez courant dans la culture Unix de nommer des scripts shell ainsi que des exécutables binaires sans extensions, auquel cas cette solution entraînera l'ignorance des scripts. Une meilleure idée est d'ajouter simplement des exécutables binaires à .gitignore manuellement chaque fois qu'ils sont ajoutés au projet - cela ne se produit généralement pas si souvent. Si cela est trop compliqué, alors la solution makefile suggérée par vedantk est meilleure.
Peter Helfer

Cela ignorera makefile
VMatrix1900

42

Ajoutez quelque chose comme

*.o

dans le fichier .gitignore et placez-le à la racine de votre dépôt (ou vous pouvez le placer dans n'importe quel sous-répertoire de votre choix - il s'appliquera à partir de ce niveau) et archivez-le.

Éditer:

Pour les binaires sans extension, il vaut mieux les placer dans bin/ou dans un autre dossier. Après tout, il n'y a pas d'ignorer basé sur le type de contenu.

Tu peux essayer

*
!*.*

mais ce n'est pas infaillible.


1
Modification ajoutée. Y a-t-il une raison pour laquelle vous ne voulez pas que votre binaire ait une extension
manojlds

10
Les exécutables n'ont souvent pas d'extensions. J'essaye de faire la même chose ici pour les fichiers créés en gccpassant -o $@.
Nathan Lilienthal

29

Pour ajouter tous les exécutables à votre .gitignore(ce que vous entendez probablement par «fichier binaire» d'après votre question), vous pouvez utiliser

find . -executable -type f >>.gitignore

Si vous ne vous souciez pas de l'ordre des lignes dans votre .gitignore, vous pouvez également mettre à jour votre .gitignoreavec la commande suivante qui supprime également les doublons et maintient l'ordre alphabétique intact.

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

Notez que vous ne pouvez pas diriger la sortie directement vers .gitignore, car cela tronquerait le fichier avant de l' catouvrir pour la lecture. En outre, vous souhaiterez peut-être ajouter \! -regex '.*/.*/.*'une option pour rechercher si vous ne souhaitez pas inclure de fichiers exécutables dans les sous-répertoires.


23

Votre meilleur pari avec les binaires est de leur donner une extension que vous pouvez facilement filtrer avec un modèle standard, ou de les placer dans des répertoires que vous pouvez filtrer au niveau du répertoire.

La suggestion d'extension est plus applicable dans Windows, car les extensions sont standard et fondamentalement requises, mais sous Unix, vous pouvez ou non utiliser des extensions sur vos binaires exécutables. Dans ce cas, vous pouvez les mettre dans un dossier bin / et les ajouter bin/à votre .gitignore.

Dans votre exemple très spécifique, à petite portée, vous pouvez simplement mettre hellovotre .gitignore.


15

Vous pouvez essayer dans votre .gitignore:

*
!*.c

Cette approche présente de nombreux inconvénients, mais elle est acceptable pour les petits projets.


3
Ce serait bien si vous
énumérez au

L'inconvénient évident est l'ordre des règles autoriser-refuser, la bonne façon est d'ignorer uniquement les fichiers indésirables, de ne pas tout interdire et ensuite d'inclure uniquement les fichiers souhaités.
Andrei Beliankou

13

Si vous utilisez un makefile, vous pouvez essayer de modifier vos règles de make pour ajouter les noms des nouveaux binaires à votre fichier .gitignore.

Voici un exemple de Makefile pour un petit projet Haskell;

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

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

Ce makefile définit une règle pour créer des exécutables à partir de code Haskell. Une fois que ghc est appelé, nous vérifions le .gitignore pour voir si le binaire y est déjà. Si ce n'est pas le cas, nous ajoutons le nom du binaire au fichier.


Maintenant, c'est une sorte d'approche différente.
René Nyffenegger


5

Voici une autre solution utilisant file. De cette façon, les scripts exécutables ne finiront pas dans gitignore. Vous devrez peut-être modifier la façon dont la sortie du fichier est interprétée pour correspondre à votre système. On pourrait alors configurer un hook pré-commit pour appeler ce script à chaque fois que vous vous engagez.

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)

J'ai fait un script similaire, et posté sur une question en double: stackoverflow.com/a/28258619/218294 Votre code est plus agréable :) le mien tourne probablement plus vite car il exécute "file" une seule fois, ou plusieurs fois (en utilisant xargs).
Sam Watkins

4

Un moyen d'ignorer également dans certains sous-répertoires, pas seulement dans une racine:

# 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, si vous souhaitez inclure uniquement certains types de fichiers spécifiques:

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

Il semble que cela puisse même fonctionner comme pour chaque nouveau sous-répertoire si vous le souhaitez!:

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

Les barres obliques de début ne sont importantes que dans les deux premières lignes et facultatives dans les autres. Tailing slash in !/*/et !/subdir/est également facultatif, mais uniquement dans cette ligne.


3

Si vous suivez ces commandes sur votre fichier .gitignore et que les fichiers semblent toujours apparaître, vous pouvez essayer:

git rm --cached FILENAME

Après cela, ajoutez votre .gitignore, validez et poussez. Il m'a fallu 40 minutes pour comprendre cela, j'espère que cela aidera les débutants comme moi


2

Vieux fil, mais toujours d'actualité. J'ai changé le makefile pour que le fichier binaire résultant après la liaison porte le nom [filname]. bin au lieu de seulement [filname]. Ensuite, j'ai ajouté des fichiers * .bin dans le gitignore.
Cette routine répond à mes besoins.


1

Je ne connais pas d'autre solution que de les ajouter une par une à .gitignore.

Une manière rudimentaire de tester est de grep la sortie de la commande de fichier:

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

ÉDITER

Pourquoi ne vous nommez-vous pas simplement exécutable hello.bin?


Parce que nommer les exécutables avec l'extension de fichier .binest une mauvaise pratique.
MD XF


0

J'ai créé un fichier .gitignore avec deux entrées dans le répertoire GOPATH.

/bin
/pkg

Il ignore tous les développements compilés, actuellement.


0

.gitignore utilise la programmation glob pour filtrer les fichiers, au moins sous Linux.

Je suis sur le point de donner une conférence sur le codage lors d'un Meetup et, en préparation, j'ai créé un répertoire avec plusieurs sous-répertoires qui sont nommés selon l'ordre dans lequel je veux les présenter: 01_subject1, 02_subject2, 03_subject3. Chaque sous-répertoire contient un fichier source avec une extension dépendante de la langue qui se compile en un fichier exécutable dont le nom correspond au nom du fichier source sans l'extension selon la pratique courante.

J'exclus les fichiers compilés dans les répertoires à préfixe numérique avec la ligne .gitignore suivante:

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

D'après ma compréhension de la documentation, cela ne devrait pas fonctionner. L'astérisque de fin doit échouer car il doit correspondre à n'importe quel nombre de caractères non spécifiés, y compris le «.» + extension. Omettre l'astérisque de fin doit échouer (et le fait) car il [!\.]ne correspond qu'à un seul caractère non point. Cependant, j'ai ajouté l'astérisque de fin, comme je le ferais pour une expression régulière, et cela fonctionne. Par travail, je veux dire que git remarque les modifications apportées au fichier source, mais pas l'existence ou les modifications des fichiers compilés.



0

Ajoutez ce qui suit à votre fichier .gitignore:

[^\.]*

Explication:

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

Le .gitignoremécanisme fonctionne uniquement sur la base des noms de fichiers , pas sur le contenu des fichiers . Être un fichier binaire est une propriété du contenu, par conséquent vous ne pouvez pas demander directement à git d'ignorer les fichiers binaires, mais uniquement de les ignorer par leur nom (et comme cela est suggéré, vous pouvez soit ajouter tous les noms de fichiers binaires à votre, .gitignoresoit utiliser un convention de dénomination).

Le fait que cela .gitignorefonctionne sur les noms de fichiers est une propriété importante en termes de performances: Git n'a besoin que de lister les fichiers, mais pas de les ouvrir et de les lire pour savoir quels fichiers ignorer. En d'autres termes, Git serait terriblement lent si vous pouviez lui demander d'ignorer les fichiers en fonction de leur contenu.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.