157 votes

Comment les règles d'exclusion .gitignore fonctionnent-elles réellement ?

J'essaie de résoudre un problème de gitignore sur une grande structure de répertoires, mais pour simplifier ma question, je l'ai réduite à ce qui suit.

J'ai la structure de répertoire suivante de deux fichiers (foo, bar) dans un tout nouveau dépôt git (pas de commits jusqu'à présent) :

a/b/c/foo
a/b/c/bar

Évidemment, un "git status -u" montre :

# Untracked files:
...
#       a/b/c/bar
#       a/b/c/foo

Ce que je veux faire est de créer un fichier .gitignore qui ignore tout ce qui se trouve à l'intérieur de a/b/c mais qui n'ignore pas le fichier 'foo'.

Si je crée un .gitignore ainsi :

c/

Puis un 'git status -u' montre que foo et bar sont ignorés :

# Untracked files:
...
#       .gitignore

C'est ce à quoi je m'attendais.

Maintenant si j'ajoute une règle d'exclusion pour foo, donc :

c/
!foo

Selon la page de manuel de gitignore, je m'attendrais à ce que cela fonctionne. Mais ce n'est pas le cas - il ignore toujours foo :

# Untracked files:
...
#       .gitignore

Cela ne fonctionne pas non plus :

c/
!a/b/c/foo

Ceci non plus :

c/*
!foo

Donne :

# Untracked files:
...
#       .gitignore
#       a/b/c/bar
#       a/b/c/foo

Dans ce cas, bien que foo ne soit plus ignoré, bar ne l'est pas non plus.

L'ordre des règles dans .gitignore ne semble pas non plus avoir d'importance.

Cela ne fait pas non plus ce que j'attendais :

a/b/c/
!a/b/c/foo

Celui-là ignore à la fois foo et bar.

Une situation qui fonctionne est celle où je crée le fichier a/b/c/.gitignore et où je le mets dedans :

*
!foo

Mais le problème avec ceci est qu'il y aura éventuellement d'autres sous-répertoires sous a/b/c et je ne veux pas avoir à mettre un .gitignore séparé dans chacun d'entre eux - j'espérais créer des fichiers .gitignore 'basés sur le projet' qui pourraient se trouver dans le répertoire supérieur de chaque projet, et couvrir toute la structure 'standard' des sous-répertoires.

Cela semble également être équivalent :

a/b/c/*
!a/b/c/foo

C'est peut-être ce qui se rapproche le plus d'un "fonctionnement", mais les chemins relatifs complets et les exceptions explicites doivent être indiqués, ce qui va être pénible si j'ai beaucoup de fichiers du nom "foo" à différents niveaux de l'arborescence des sous-répertoires.

Quoi qu'il en soit, soit je ne comprends pas bien le fonctionnement des règles d'exclusion, soit elles ne fonctionnent pas du tout lorsque des répertoires (plutôt que des caractères génériques) sont ignorés - par une règle se terminant par un /

Quelqu'un peut-il m'éclairer à ce sujet ?

Y a-t-il un moyen de faire en sorte que gitignore utilise quelque chose de sensé comme des expressions régulières au lieu de cette syntaxe maladroite basée sur le shell ?

J'utilise et observe ceci avec git-1.6.6.1 sur Cygwin/bash3 et git-1.7.1 sur Ubuntu/bash3.

0 votes

5 votes

Question très bien rédigée ! La quantité de cas que vous avez essayés m'a vraiment aidé à comprendre ce que je faisais mal dans mon cas similaire. Dieu merci, j'ai cherché pendant longtemps aujourd'hui.

165voto

Chris Smith Points 6643
/a/b/c/\*
!foo

Cela semble fonctionner pour moi (git 1.7.0.4 sur Linux). Le site * est important car sinon vous ignorez le répertoire lui-même (donc git ne regardera pas à l'intérieur) au lieu des fichiers dans le répertoire (ce qui permet l'exclusion).

Considérez les exclusions comme disant "mais pas celui-ci" plutôt que "mais incluez ceci" - "ignorez ce répertoire ( /a/b/c/ ) mais pas celui-ci ( foo )" n'a pas beaucoup de sens ; "ignorer tous les fichiers de ce répertoire ( /a/b/c/* ) mais pas celui-ci ( foo )". Pour citer la page de manuel :

Un préfixe facultatif ! qui annule le motif ; tout fichier correspondant exclu par un motif précédent sera à nouveau inclus.

c'est-à-dire le fichier doit avoir déjà été exclu pour être à nouveau inclus. J'espère que cela vous éclairera.

0 votes

Oui, l'exemple que vous donnez fonctionne bien pour moi aussi. Le problème est que /a/b/* ne fonctionne pas si foo est dans c, ce qui signifie que si j'ai plusieurs fichiers foo dans différents sous-répertoires sous c (par exemple d/, e/, f/g/h/, i/j/, etc.), la règle de négation "!foo" ne les rattrapera pas.

1 votes

@meowsqueak En effet, il ne le fera pas. Si vous ignorez /a/b/*, alors il n'y a pas de répertoire où se trouve foo ! Si vous essayez d'ignorer toute l'arborescence des répertoires sous /a/b mais d'inclure tout fichier nommé "foo" qui peut se trouver n'importe où dans l'arborescence, je ne pense pas que ce soit faisable avec les motifs .gitignore :-)

0 votes

En fait, cela pourrait expliquer pourquoi cela ne fonctionne pas pour moi - les règles suivantes ne fonctionnent pas : "/a/b/*", "!c/foo". Si cela fonctionnait, il n'y aurait peut-être pas de problème.

25voto

medge799 Points 71

J'ai une situation similaire, ma solution a été d'utiliser :

/a/**/*
!/a/**/foo

Cela devrait fonctionner pour un nombre arbitraire de répertoires intermédiaires si j'ai lu ** correctement.

7voto

Peter Petrik Points 41

Voici une autre option :

*
!/a*
!/a/*
!/a/*/*
!/a/*/*/*

Cela ignorerait tous les fichiers et répertoires, à l'exception des fichiers/répertoires situés à trois niveaux de profondeur dans un fichier.

6voto

nus Points 1613

La page de manuel .gitignore ne le dit pas clairement. Cela fonctionne :

*
!/a
!/a/b
!/a/b/c
!/a/b/c/foo

# don't forget this one
!.gitignore

Comme mentionné par Chris, un répertoire n'est même pas ouvert s'il est exclu. Donc, si vous voulez être en mesure d'ignorer * mais certains fichiers, vous devez construire le chemin vers ces fichiers comme ci-dessus. Pour moi, c'est pratique, car je veux faire une revue de code sur un fichier d'une bibliothèque et si je veux en faire une autre plus tard, je l'ajoute simplement, et tout le reste est ignoré.

5voto

VonC Points 414372

Sur une note plus générale, git1.8.2 comprendra le patch (également dans sa v4 , suite à une question sur Stack Overflow ) de Adam Spiers sur la détermination des gitignore ignore en fait votre fichier.

Voir Notes de publication de git1.8.2 et la question du SO " quelle règle gitignore ignore mon fichier " :
ce sera la commande git check-ignore .

1 votes

Merci de diffuser cette information. check-ignore vous indiquera également quelle règle est prévenir votre fichier ne sera pas ignoré, si c'est le cas.

0 votes

@AdamSpiers, ça a l'air génial. Je vais certainement devoir jouer avec.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X