web-dev-qa-db-fra.com

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

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

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

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

De toute évidence, un "statut git -u" indique:

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

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

Si je crée un .gitignore ainsi:

c/

Ensuite, un 'statut git -u' indique que foo et bar sont ignorés:

# Untracked files:
...
#       .gitignore

C'est ce que j'attends.

Maintenant, si j'ajoute une règle d'exclusion pour foo, voici ce qui suit:

c/
!foo

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

# Untracked files:
...
#       .gitignore

Cela ne marche 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 n'est pas ignoré non plus.

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

Cela ne fait pas non plus ce à quoi je m'attendais:

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

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

Une situation qui fonctionne est que si je crée le fichier a/b/c/.gitignore et le mienne:

*
!foo

Mais le problème, c’est qu’il y aura éventuellement d’autres sous-répertoires sous a/b/c et que je ne veux pas avoir à mettre un .gitignore séparé dans chacun d’entre eux; j’espérais créer un .gitignore 'basé sur projet' les fichiers pouvant figurer dans le répertoire principal de chaque projet et couvrant toute la structure de sous-répertoires "standard".

Cela semble aussi être équivalent:

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

Cela pourrait être la chose la plus proche de "travailler" que je puisse réaliser, mais les chemins relatifs complets et les exceptions explicites doivent être définis, ce qui sera pénible si j'ai beaucoup de fichiers de nom 'foo' à différents niveaux de l'arbre de sous-répertoire.

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

Quelqu'un peut-il s'il vous plaît nous éclairer un peu?

Existe-t-il un moyen de faire en sorte que gitignore utilise quelque chose de raisonnable, comme des expressions régulières, au lieu de cette syntaxe maladroite basée sur Shell?

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

139
davidA
/a/b/c/*
!foo

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

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

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

c'est-à-dire que le fichier doit déjà avoir été exclu pour être inclus à nouveau. Espérons que cela nous éclaire un peu.

141
Chris

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

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

Cela devrait fonctionner pour un nombre arbitraire de répertoires intermédiaires si je lis ** correctement.

24
medge799

Voici une autre option:

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

Cela ignorerait tous les fichiers et répertoires, à l’exception des fichiers/répertoires à trois niveaux situés au plus profond d’un.

6
Peter Petrik

Sur une note plus générale, git1.8.2 inclura le patch (aussi dans sa v4 , suite à une question sur le dépassement de capacité ) de Adam Spiers pour déterminer quelle règle gitignore ignore en réalité votre fichier.

Voir notes de version de git1.8.2 et la SO question " quelle règle de gitignore ignore mon fichier ":
Ce sera la commande git check-ignore .

4
VonC

cela n’est certainement pas clair dans la page de manuel de .gitignore. Cela marche:

*
!/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 pouvoir ignorer * mais certains fichiers, vous devez créer le chemin d'accès à ces fichiers comme ci-dessus. Pour moi, cela est pratique, car je veux effectuer une révision du code sur un fichier d’une bibliothèque et si je veux en faire un autre plus tard, je l’ajoute, et tout le reste est ignoré.

4
user1115652