Expliquez quelle règle gitignore ignore mon fichier

310

Existe-t-il un moyen de voir pourquoi certains fichiers sont ignorés par git (c'est-à-dire quelle règle dans un .gitignorefichier entraîne l'ignorance du fichier)?

Imaginez que j'ai ceci (ou un scénario beaucoup plus complexe, avec des centaines de dossiers et des dizaines de .gitignorefichiers:

/
-.gitignore
-folder/
    -.gitignore
    -subfolder/
              -.gitignore
              -file.txt

Si je lance git add folder/subfolder/file.txtgit, je peux me plaindre qu'il soit ignoré:

The following paths are ignored by one of your .gitignore files:
folder/subfolder/file.txt
Use -f if you really want to add them.

Existe-t-il un moyen de savoir lequel de tous les possibles .gitignorea une règle pour ignorer ce fichier et afficher également la règle? Comme:

The following paths are ignored by your folder/.gitignore file (line 12: *.txt)
folder/subfolder/file.txt
Use -f if you really want to add them.

Ou juste:

$ git why-is-ignored folder/subfolder/file.txt
folder/.gitignore:12:*.txt
Carlos Campderrós
la source
4
Remarque: git check-ignoreaura bientôt (git1.8.5 / 1.9) une --no-indexoption. Voir ma réponse ci
VonC
Remarque: GIT_TRACE_EXCLUDE=1 git statussera bientôt un moyen supplémentaire de déboguer les .gitignorerègles. Voir ma réponse modifiée ci
VonC
Article de blog pertinent: danielcompton.net/2016/04/21/… .
krlmlr

Réponses:

643
git check-ignore -v filename

Voir la page de manuel pour plus de détails.

La réponse originale suit:

git ne fournit actuellement rien de tel. Mais après avoir vu votre question, j'ai fait une recherche sur Google et j'ai découvert qu'en 2009, cette fonctionnalité avait été demandée et partiellement mise en œuvre . Après avoir lu le fil, je me suis rendu compte que ce ne serait pas trop de travail pour le faire correctement, j'ai donc commencé à travailler sur un patch et j'espère que ce sera fini le lendemain ou deux. Je mettrai à jour cette réponse lorsqu'elle sera prête.

MISE À JOUR: Wow, c'était beaucoup plus difficile que ce à quoi je m'attendais. Les entrailles de gitla gestion des exclusions sont assez énigmatiques. Quoi qu'il en soit, voici une série de validations presque terminées qui s'appliquent à la masterbranche en amont d'aujourd'hui . La suite de tests est terminée à 99%, mais je n'ai pas encore fini de gérer l' --stdinoption. J'espère que je gérerai cela ce week-end, puis soumettrai mes correctifs à la liste de diffusion git.

En attendant, j'accueillerais certainement les tests de toute personne en mesure de le faire - il suffit de cloner à partir de ma gitfourchette , de vérifier la check-ignorebranche et de la compiler comme d'habitude.

MISE À JOUR 2: C'est fait! La dernière version est sur github comme ci-dessus, et j'ai soumis la série de correctifs à la liste de diffusion git pour examen par les pairs. Voyons ce qu'ils en pensent ...

MISE À JOUR 3: Après plusieurs mois de piratage / révisions de correctifs / discussions / attente, je suis ravi de pouvoir dire que cette fonctionnalité a maintenant atteint la masterbranche de git et sera disponible dans la prochaine version (1.8.2, prévue le 8 Mars 2013). Voici la check-ignorepage de manuel . Ouf, c'était bien plus de travail que ce à quoi je m'attendais!

MISE À JOUR 4: Si vous êtes intéressé par l'histoire complète de l'évolution de cette réponse et de la mise en œuvre de la fonctionnalité, consultez l' épisode # 32 du podcast GitMinutes .

Adam Spires
la source
2
J'utilise 1.8.2 et git check-ignorene fait rien.
zakdances
3
@yourfriendzak Sans l'ombre d'un doute, git check-ignoreest présent et fonctionne en 1.8.2. Si le comportement n'est pas celui que vous attendez, je vous suggère de (relire) la page de manuel, et si ce n'est toujours pas le cas, veuillez soumettre un rapport de bogue approprié sur la liste de diffusion git. Dire simplement qu'il ne fait rien n'est pas très utile. Je suppose que vous l'avez probablement exécuté sur un fichier non ignoré et que vous attendez à tort une sortie (bien que j'ajouterai probablement la prise en charge --show-unmatcheddu --verbosemode de sortie à l'avenir).
Adam Spires
1
@AdamSpiers vous avez raison. J'aurais dû spécifier que lorsque j'exécute la commande, rien n'est imprimé. Pas de message d'erreur, pas de message de réussite, pas d'information. Juste la prochaine invite vide apparaissant. Ai-je donc raison de supposer que "aucune sortie" n'est un comportement attendu dans certaines circonstances?
zakdances
1
@AdamSpiers merci beaucoup pour cela! Après 3 jours d'enquête, vous venez de m'aider à retrouver la cause d'une rupture de build due à un fichier globalement ignoré dans .gitignore_global! Je ne savais même pas que c'était une chose!
BenBtg
3
Ce n'est pas tous les jours que l'on voit un développeur Stack Overflow apporter autant de changements pour implémenter une fonctionnalité développeur. Wow et respect.
user3613932
18

Mise à jour git 2.8 (mars 2016):

GIT_TRACE_EXCLUDE=1 git status

Voir " Un moyen de valider le .gitignorefichier "

C'est complémentaire à ce qui est git check-ignore -vdécrit ci-dessous.


Réponse originale: septembre 2013 (git 1.8.2, puis 1.8.5+):

git check-ignores'améliore à nouveau dans git 1.8.5 / 1.9 (T4 2013) :

" git check-ignore" suit la même règle que " git add" et " git status" en ce que le mécanisme ignorer / exclure ne prend pas effet sur les chemins déjà suivis.
Avec l' --no-indexoption " ", il peut être utilisé pour diagnostiquer les chemins qui auraient dû être ignorés qui ont été ajoutés par erreur à l'index .

Voir commit 8231fa6 sur https://github.com/flashydave :

check-ignoremontre actuellement comment les .gitignorerègles traiteraient les chemins non suivis. Les chemins suivis ne génèrent pas de sortie utile.
Cela empêche le débogage des raisons pour lesquelles un chemin a été suivi de manière inattendue, sauf si ce chemin est d'abord supprimé de l'index avec git rm --cached <path>.

L'option --no-indexindique à la commande de contourner la vérification du chemin se trouvant dans l'index et permet donc de vérifier également les chemins suivis.

Alors que ce comportement dévie des caractéristiques git addet git statusson cas d'utilisation est peu susceptible de causer une confusion chez l'utilisateur.

Les scripts de test sont augmentés pour vérifier cette option par rapport aux ignorés standard pour garantir un comportement correct.


--no-index::

Ne regardez pas dans l'index lors des vérifications.
Cela peut être utilisé:

  • pour déboguer pourquoi un chemin a été suivi par exemple git add .et n'a pas été ignoré par les règles comme prévu par l'utilisateur ou
  • lors du développement de modèles comprenant la négation pour correspondre à un chemin précédemment ajouté avec git add -f.
VonC
la source
4

Je ne trouve rien dans la page de manuel mais voici un script rapide et sale qui vérifiera votre fichier dans chaque répertoire parent pour voir s'il peut être ajouté par git. Exécutez-le dans le répertoire contenant le fichier de problème en tant que:

test-add.sh STOP_DIR FILENAME

STOP_DIRest le répertoire de niveau supérieur du projet Git et FILENAMEest le nom du fichier problématique (sans chemin d'accès). Il crée un fichier vide du même nom à chaque niveau de la hiérarchie (s'il n'existe pas) et essaie git add -nde voir s'il peut être ajouté (il se nettoie après lui-même). Il produit quelque chose comme:

FAILED:    /dir/1/2/3
SUCCEEDED: /dir/1/2

Le scénario:

#!/usr/bin/env bash
TOP=$1
FILE=$2
DIR=`pwd`
while : ; do
  TMPFILE=1
  F=$DIR/$FILE
  if [ ! -f $F ]; then
    touch $F
    TMPFILE=0
  fi
  git add -n $F >/dev/null 2>&1
  if [ $? = 0 ]; then
    echo "SUCCEEDED: $DIR"
  else
    echo "FAILED:    $DIR"
  fi
  if [ $TMPFILE = 0 ]; then
    rm $F
  fi
  DIR=${DIR%/*}
  if [ "$DIR" \< "$TOP" ]; then
    break
  fi
done 
edoloughlin
la source
1

Pour ajouter à la réponse principale de l'utilisation git check-ignore -v filename(merci BTW), j'ai trouvé que mon fichier .gitignore bloquait tout parce qu'il y avait une nouvelle ligne après un caractère générique, donc j'avais:

* .sublime-project

par exemple. Je viens de supprimer la nouvelle ligne, et le tour est joué! C'était réparé.

rekordboy
la source