J'ai utilisé git mais j'ai toujours de la confusion à propos des chemins de fichier . Gitignore.
Alors, quelle est la différence entre les deux chemins suivants dans le fichier . Gitignore?
tmp /* public/documents /**/*
Je peux comprendre cela tmp/*
ignorera tous les fichiers et dossiers qu'il contient. Ai-je raison? Mais que signifie ce deuxième chemin de ligne?
Cela dépend du comportement de votre Shell. Git ne fait aucun travail pour déterminer comment les développer. En général, *
correspond à n'importe quel fichier ou dossier:
/a/*/z
matches /a/b/z
matches /a/c/z
doesn't match /a/b/c/z
**
correspond à n'importe quelle chaîne de dossiers:
/a/**/z
matches /a/b/z
matches /a/b/c/z
matches /a/b/c/d/e/f/g/h/i/z
doesn't match /a/b/c/z/d.pr0n
Combiner **
avec *
pour faire correspondre les fichiers dans une arborescence de dossiers entière:
/a/**/z/*.pr0n
matches /a/b/c/z/d.pr0n
matches /a/b/z/foo.pr0n
doesn't match /a/b/z/bar.txt
Aujourd'hui, je n'arrive pas à trouver une machine où **
Ne fonctionne pas comme indiqué. Cela inclut OSX-10.11.3 (El Capitan) et Ubuntu-14.04.1 (Trusty). Peut-être que git-ignore a été mis à jour, ou peut-être que récemment fnmatch gère **
Comme prévu. La réponse acceptée semble donc désormais correcte dans la pratique.
Le **
N'a pas de signification particulière dans git . C'est une fonctionnalité de bash> = 4.0, via
shopt -s globstar
Mais git n'utilise pas bash . Pour voir ce que git fait réellement, vous pouvez expérimenter avec git add -nv
Et des fichiers dans plusieurs niveaux de sous-répertoires.
Pour l'OP, j'ai essayé toutes les combinaisons auxquelles je peux penser pour le fichier .gitignore
, Et rien ne fonctionne mieux que cela:
public/documents/
Ce qui suit ne fait pas ce que tout le monde semble penser:
public/documents/**/*.obj
Je ne peux pas faire fonctionner cela, peu importe ce que j'essaie, mais au moins cela est cohérent avec les documents git . Je soupçonne que lorsque les gens ajoutent cela à .gitignore
, Cela fonctionne par accident, uniquement parce que leurs fichiers .obj
Ont précisément un sous-répertoire en profondeur. Ils ont probablement copié le double astérisque d'un script bash. Mais peut-être existe-t-il des systèmes où fnmatch(3)
peut gérer le double astérisque comme bash le peut.
Si vous utilisez un shell tel que Bash 4, alors ** est essentiellement une version récursive de *, qui correspondra à n'importe quel nombre de sous-répertoires.
Cela a plus de sens si vous ajoutez une extension de fichier à vos exemples. Pour faire correspondre les fichiers journaux immédiatement à l'intérieur de tmp, vous devez taper:
/tmp/*.log
Pour faire correspondre les fichiers journaux n'importe où dans n'importe quel sous-répertoire de tmp, vous devez taper:
/tmp/**/*.log
Mais en testant la version 1.6.0.4 de git et la version 3.2.17 (1) de bash, il semble que git ne supporte pas du tout ** globs. La page de manuel la plus récente pour gitignore ne mentionne pas ** non plus, donc c'est soit (1) très nouveau, (2) non pris en charge, ou (3) en quelque sorte dépendant de l'implémentation de globbing de votre système .
De plus, quelque chose de subtil se passe dans vos exemples. Cette expression:
tmp/*
... signifie en fait "ignorer tout fichier à l'intérieur d'un répertoire tmp, n'importe où dans l'arborescence source, mais ne pas ignorer les répertoires tmp eux-mêmes". Dans des circonstances normales, vous écririez probablement simplement:
/tmp
... qui ignorerait un seul répertoire tmp de niveau supérieur. Si vous devez conserver les répertoires tmp, tout en ignorant leur contenu, vous devez placer un fichier .gitignore vide dans chaque répertoire tmp pour vous assurer que git crée réellement le répertoire.
Notez que le '**
', lorsqu'il est combiné avec un sous-répertoire (**/bar
), doit avoir changé par rapport à son comportement par défaut, puisque la note de publication pour git1.8.2 mentionne maintenant:
Les motifs dans
.gitignore
et.gitattributes
les fichiers peuvent avoir**/
, comme un modèle qui correspond à 0 ou plusieurs niveaux de sous-répertoire.Par exemple. "
foo/**/bar
"correspond à"bar
"dans"foo
"lui-même ou dans un sous-répertoire de"foo
".
Voir commit 4c251e5cb5c245ee3bb98c7cedbe944df93e45f4 :
"
foo/**/bar
" allumettes "foo/x/bar
","foo/x/y/bar
"... mais non "foo/bar
".
Nous faisons un cas spécial, lorsquefoo/**/
est détecté (et "foo/
"partie est déjà mise en correspondance), essayez de faire correspondre"bar
"avec le reste de la chaîne.La sémantique "Faire correspondre un ou plusieurs répertoires" peut être facilement réalisée en utilisant "
foo/*/**/bar
".Cela fait également "
**/foo
"match"foo
"en plus de"x/foo
","x/y/foo
"..Signé par: Nguyễn Thái Ngọc Duy
<[email protected]>
Simon Buchan aussi commenté :
documents actuels (
.gitignore
page de manuel ) sont assez clairs qu'aucun sous-répertoire n'est nécessaire,x/**
correspond à tous les fichiers sous (éventuellement vide)x
Le .gitignore
la page de manuel mentionne:
Un tiret "
/**
"correspond à tout ce qu'il contient. Par exemple,"abc/**
"correspond à tous les fichiers du répertoire"abc
", par rapport à l'emplacement du.gitignore
fichier, avec une profondeur infinie.Une barre oblique suivie de deux astérisques consécutifs, puis une barre oblique correspond à zéro ou plusieurs répertoires. Par exemple, "
a/**/b
" allumettes "a/b
","a/x/b
","a/x/y/b
" etc.
Lorsque ** n'est pas pris en charge, le "/" est essentiellement un caractère de fin pour le caractère générique, donc lorsque vous avez quelque chose comme:
public/documents/**/*
il recherche essentiellement deux éléments génériques entre les barres obliques et ne récupère pas les barres obliques elles-mêmes. Par conséquent, cela reviendrait à:
public/documents/*/*
Cela ne fonctionne pas pour moi, mais vous pouvez créer un nouveau .gitignore
dans ce sous-répertoire:
tmp/**/*.log
peut être remplacé par un .gitignore
dans tmp
:
*.log