Question .gitignore Syntaxe: bin vs bin / vs. bin / * vs bin / **


Quelle est la différence entre l'ajout bin, bin/, bin/* et bin/** dans mon fichier .gitignore? J'ai utilisé bin/, mais en regardant autre  Fichiers .gitignore (dans le fichier éclipse les doubles et simples étoiles sont même utilisées ensemble comme ceci: tmp/**/* Qu'est-ce qui se passe avec ça?) Je vois que les deux premiers modèles sont également largement utilisés. Quelqu'un peut-il s'il vous plaît expliquer les différences entre les trois?


72
2018-01-09 01:42


origine


Réponses:


bin correspond à tous les fichiers ou répertoires nommés 'bin'.

bin/ correspond à tout les répertoires nommée "bin", ce qui signifie en fait tout son contenu, car Git ne suit pas les répertoires seuls.

bin/* fait correspondre tous les fichiers et répertoires directement bin/. Cela empêche Git de trouver automatiquement tous les fichiers dans ses sous-répertoires, mais si, disons un bin/foo sous-répertoire est créé, cette règle va ne pas rencontre foocontenu de

bin/** correspond à tous les fichiers et répertoires de tout bin/ répertoire et tous ses sous-répertoires.

Le mot "any" est essentiel car les règles ne sont pas relatives à la racine du référentiel et s'appliquent nulle part dans l'arborescence du système de fichiers. Vous devez commencer les règles avec un / (ou !/ dés-ignorer) qui signifie la racine du référentiel, pas la racine du système, afin de correspondre uniquement à ce qui était prévu.

ATTENTION: Vous devriez jamais utiliser des règles comme dir/*, /dir/**, etc. seul à moins que vous ignoriez également quelque chose qui existe dans ce répertoire. Omettre l'astérisque ou vous pourriez perdre définitivement beaucoup de données de certaines invocations de git gc, git stash et plus.

Je ne sais pas trop quoi tmp/**/* est destiné à faire. J'ai d'abord pensé qu'il pourrait être utilisé pour faire correspondre les fichiers dans les sous-répertoires de tmp/ mais pas les fichiers directement présents dans tmp/ lui-même Mais un simple test semble suggérer que cela ignore tous les fichiers dans tmp/.


71
2018-01-09 03:40



bin et bin/ ne diffèrent que par le fait que ce dernier ne correspond qu’à un répertoire.

bin/**/* est le même que bin/** (apparemment depuis 1.8.2, selon la réponse de @VonC).

Le plus difficile, que je viens de passer une heure ou plus à me déchirer les cheveux, est-ce que bin/ et bin/** ne sont pas assez le même! Comme le plus ancien ignore le répertoire dans son ensemble, et que le dernier ignore chacun des fichiers qu'il contient, et que dans presque tous les cas, git ne s'intéresse pas aux répertoires, il n'y a normalement aucune différence. Cependant, si vous essayez d'utiliser ! pour ignorer un sous-chemin, alors vous trouverez ce git (ahem) ne tient pas compte si vous avez ignoré le répertoire parent! (encore une fois, plutôt que le contenu du répertoire)

Ceci est plus clair par exemple, donc pour un référentiel nouvellement initié mis en place pour:

$ cat .gitignore
ignored-file
or-dir
dir-only/
!dir-only/cant-reinclude
dir-contents/**
!dir-contents/can-reinclude

$ mkdir or-dir dir-only dir-contents

$ touch file ignored-file or-dir/ignored-file dir-only/cant-reinclude dir-contents/can-reinclude

Les fichiers non suivis suivants existent:

$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file

Mais vous pouvez voir que les fichiers suivants ne sont pas ignorés:

$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file

Et si vous essayez d'ajouter, vous obtenez:

$ git add dir-only/cant-reinclude
The following paths are ignored by one of your .gitignore files:
dir-only/cant-reinclude
Use -f if you really want to add them.
fatal: no files added

Je considère ce comportement comme un bug. (Tout est sur git version 1.8.4.msysgit.0)


40
2017-12-05 05:04



Notez que, à proprement parler, git ne suit pas les répertoires, mais uniquement les fichiers. Il n’est donc pas possible d’ajouter un répertoire, seulement son Contenu.

Dans le contexte de .gitignore Cependant, git prétend comprendre les répertoires pour la seule raison que

Il n'est pas possible de ré-inclure un fichier si un répertoire parent de ce fichier est exclu.
https://git-scm.com/docs/gitignore#_pattern_format

Qu'est-ce que cela signifie pour les modèles d'exclusion? Traitons-les en détail:

bin

Cela ignore

  • fichiers nommés bin.
  • le contenu des dossiers nommés bin

Vous pouvez ignorer la liste blanche bin fichiers et dossiers en ajoutant ultérieurement ! entrées, mais vous ne pouvez pas inclure la liste blanche Contenu des dossiers nommés bin

bin

!bin/file_in_bin # has no effect, since bin/ is blacklisted!
!bin/* # has no effect, since bin/ is blacklisted!
!file_in_bin # has no effect, since bin/ is blacklisted!

!bin # this works

bin/

Comme ci-dessus, sauf que cela ne correspond pas des dossiers nommé bin. Ajout d'un suivi / indique à git de faire correspondre les répertoires uniquement.

bin/*

Cela ignore

  • des dossiers contenu dans un dossier nommé bin
  • contenu des sous-dossiers directs des dossiers nommés bin
bin/*  # blacklists bin/file_in_bin and bin/subfolder/

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted!
!bin # whitelists files named bin/bin, since bin/ itself is not blacklisted
!bin/ # has no effect, since bin/ itself is not blacklisted


!bin/file_in_bin # works since bin/ itself is not blacklisted
!file_in_bin # works too
!bin/subfolder # works (so implicitly whitelists bin/subfolder/file_in_sub)
!bin/subfolder/ # works just as well
!bin/* # works for file_in_bin and subfolder/

bin/**

Cela ignore

  • contenu de bin
  • contenu des sous-dossiers (n'importe quel niveau d'imbrication) dans bin
bin/**  # blacklists bin/file_in_bin and
        # bin/subfolder/ and bin/subfolder/file_in_sub and
        # bin/subfolder/2/ and bin/subfolder/2/file_in_sub_2

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/ # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/file_in_sub_2 # has no effect, since bin/subfolder is blacklisted

!bin/subfolder # works only in combinations with other whitelist entries,
               # since all contents of subfolder are blacklisted (1)

!bin/file_in_bin # works since bin itself is not blacklisted
!bin/* # works for file_in_bin and subfolder; see (1)

16
2018-02-23 05:00



Je viens de faire un nouveau repo et j'ai essayé certaines choses. Voici mes résultats:

NOUVEAUX RÉSULTATS

git version 2.10.1.windows.1

  1. Initialiser un dépôt presque vide. Seul le fichier README
  2. Remplir le bin répertoire plusieurs couches en profondeur
    • bin.txt
    • Test.txt
    • bin/a/b/bin.txt
    • bin/a/b/Test.txt
    • bin/a/bin/bin.txt
    • bin/a/bin/Test.txt
    • bin/a/bin.txt
    • bin/a/Test.txt
    • bin/bin.txt
    • bin/Test.txt
  3. Ajouter bin to gitignore: Résultats
    • Tout sous le bin répertoire (et plus profond) est maintenant ignoré
    • Le niveau racine n'est pas ignoré (/bin.txt et /Test.txt continuent d'afficher)
  4. modifier bin à bin/ dans le gitignore: résultats
    • Pas de changement
  5. modifier bin/ à bin/*
    • Pas de changement
  6. modifier bin/* à bin/**
    • Pas de changement
  7. modifier bin/** à bin/**/
    • bin/bin.txt et bin/Test.txt ne sont plus ignorés
  8. modifier bin/**/ à bin/**/*
    • bin/bin.txt et bin/Test.txt reviennent à être ignorés

Vieux résultats

version git: 2.7.0.windows.1

  1. Initialiser un dépôt presque vide. Seul le fichier README
  2. Remplir le bin répertoire plusieurs couches en profondeur
    • bin/a/b/Test.txt
    • bin/a/bin/Test.txt
    • bin/a/Test.txt
    • bin/Test.txt
  3. Ajouter bin to gitignore: Résultats
    • Tout sous le bin répertoire (et plus profond) est maintenant ignoré
  4. modifier bin à bin/ dans le gitignore: résultats
    • Tout sous le bin répertoire (et plus profond) est toujours ignoré (pas de changement)
  5. modifier bin/ à bin/*
    • Tout sous le bin répertoire (et plus profond) est toujours ignoré (pas de changement)
  6. modifier bin/* à bin/**
    • Tout sous le bin répertoire (et plus profond) est toujours ignoré (pas de changement)
  7. modifier bin/** à bin/**/
    • bin/Test.txt n'est plus ignoré
  8. modifier bin/**/ à bin/**/*
    • Tout sous le bin répertoire (et plus profond) est à nouveau ignoré

7
2018-02-23 05:22



Notez que le '**', lorsqu'il est combiné avec un sous-répertoire (**/bar), doit avoir changé depuis son comportement par défaut, puisque le note de version pour git1.8.2 mentionne maintenant:

Les motifs dans .gitignore et .gitattributes les fichiers peuvent avoir **/, comme modèle correspondant à 0 ou plusieurs niveaux de sous-répertoire.

Par exemple. "foo/**/bar" allumettes "bar" dans "foo"lui-même ou dans un sous-répertoire de"foo".


La règle à retenir (et qui aide à comprendre la différence d'intention derrière ces syntaxes) est la suivante:

Il n'est pas possible de ré-inclure un fichier si un répertoire parent de ce fichier est exclu.


En règle générale, si vous souhaitez exclure des fichiers d'un sous-dossier d'un dossier ignore f, vous devez:

f/**
!f/**/
!f/a/sub/folder/someFile.txt

C'est:

  • Si la première règle était f/, le dossier f/ serait ignoré et les règles ci-dessous concernant f n'aurait pas d'importance.
  • f/** atteindre le même que f/, mais ignorer tous les sous-éléments (fichiers et sous-dossiers).
    Cela vous donne la possibilité de mettre en liste blanche (exclure de gitignore) les sous-dossiers: !f/**/.
  • Puisque toutes f les sous-dossiers sont ne pas ignoré, vous pouvez ajouter une règle pour exclure un fichier (!f/a/sub/folder/someFile.txt)

7
2018-02-18 07:14



Il y a une autre différence entre bin/* et bin/.

bin/allumettes foo/bin/test.txt (comme prévu), mais bin/* pas, ce qui semble étrange, mais il est documenté: https://git-scm.com/docs/gitignore 

"Documentation / *. Html" correspond à "Documentation / git.html" mais pas   "Documentation / ppc / ppc.html" ou "tools / perf / Documentation / perf.html".

La raison de ceci semble être ces règles:

  • Si le motif se termine par une barre oblique, il est supprimé pour les besoins de la description suivante ...

  • Si le modèle ne contient pas de barre oblique /, Git le traite comme un modèle de glob et vérifie s'il y a une correspondance avec le chemin d'accès par rapport à l'emplacement du fichier .gitignore ...

  • Sinon, Git traite le motif comme un glob shell pouvant être consommé par fnmatch (3) avec le drapeau FNM_PATHNAME ...

Donc, si le motif se termine par une barre oblique, la barre oblique est supprimée et traitée comme un motif de globes de shell, auquel cas binallumettes foo/bin/test.txt. Si ça finit avec /*, la barre oblique n'est pas supprimée et transmise à fnmatch, qui ne correspond pas aux sous-répertoires.

Cependant, le même n'est pas vrai pour foo/bin/ et foo/bin/*, car même après avoir supprimé la barre oblique foo/bin/, il contient toujours une barre oblique, donc il est traité comme un motif fnmatch, pas un glob. C'est à dire. ça ne correspondra pas bar/foo/bin/test.txt


0
2017-11-16 15:07