Un dépôt Git ne doit contenir que ce que vous écrivez. Les dépendances installées, les artefacts de build, les journaux et les fichiers de configuration locale n'ont rien à y faire : ils alourdissent le dépôt, polluent les revues de code et exposent parfois des secrets.
Le fichier .gitignore répond à ce besoin. Il contient des motifs, un
par ligne, et Git écarte les fichiers qui leur correspondent. Une règle
détermine tout le reste : .gitignore ne filtre que les fichiers que Git ne
suit pas encore. Un fichier déjà commité continue d'être suivi, quelle que
soit la règle ajoutée ensuite. C'est l'origine de la quasi-totalité des
« mon .gitignore ne fonctionne pas ».
Ce guide couvre l'écriture des règles, mais surtout la vérification : savoir quelle règle s'applique à un fichier donné, lister ce que Git écarte, et distinguer un fichier réellement ignoré d'un fichier simplement non modifié.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Écrire des règles : jokers, ancrage à la racine, dossiers, négation
git check-ignore -v: savoir quelle ligne de quel fichier ignore un chemin- Deux pièges de vérification qui font croire à une règle inopérante
- Lister ce que Git ignore, et ce qu'il suit réellement
- Réparer le cas du fichier déjà suivi
- Les trois sources de règles : partagée, locale, globale
Prérequis
Section intitulée « Prérequis »- Git installé (installer et configurer Git). Toutes les commandes de ce guide fonctionnent depuis longtemps ; les sorties publiées ont été obtenues avec Git 2.43.0.
- Un dépôt initialisé et le cycle
add/commitcompris (créer un dépôt, enregistrer des modifications).
Ce qu'un .gitignore fait, et ce qu'il ne fait pas
Section intitulée « Ce qu'un .gitignore fait, et ce qu'il ne fait pas »Git classe chaque fichier du répertoire de travail dans l'une de trois catégories : suivi (il est dans l'index, Git surveille ses modifications), non suivi (Git le voit mais ne le surveille pas), ou ignoré (Git le voit et a reçu l'ordre de ne pas le proposer).
.gitignore n'agit que sur la frontière entre les deux dernières. Il retire
du bruit un fichier non suivi pour qu'il n'apparaisse plus dans git status
et qu'un git add . ne l'attrape pas. Il n'a aucun effet sur un fichier
déjà suivi, et il ne supprime rien du disque ni de l'historique.
Voici un projet Node.js avant toute règle :
git status --short?? README.md?? debug.log?? dist/?? erreurs.log?? node_modules/?? src/Les fichiers utiles se noient parmi les dépendances et les artefacts.
Un .gitignore placé à la racine du dépôt règle le problème :
cat > .gitignore <<'EOF'# Dependances installees par npmnode_modules/
# Artefacts de builddist/
# Journaux, sauf celui qu'on veut versionner*.log!erreurs.log
# Secrets.envEOFgit status --short?? .gitignore?? README.md?? erreurs.log?? src/Le .gitignore apparaît lui-même dans la liste, et c'est voulu : il doit être
versionné pour que toute l'équipe partage les mêmes exclusions.
Vérifier ce que Git prend en compte
Section intitulée « Vérifier ce que Git prend en compte »Écrire une règle est facile, savoir si elle s'applique l'est moins. Trois questions reviennent : pourquoi ce fichier est-il ignoré, qu'est-ce que Git écarte au total, et qu'est-ce qu'il suit réellement. Chacune a sa commande dédiée.
git check-ignore : quelle règle s'applique
Section intitulée « git check-ignore : quelle règle s'applique »git check-ignore -v prend un chemin et répond en désignant la règle exacte
qui le concerne, au format fichier:ligne:motif suivi du chemin testé.
git check-ignore -v debug.log.gitignore:8:*.log debug.logLa réponse se lit : la ligne 8 du fichier .gitignore, qui contient le motif
*.log, s'applique à debug.log. C'est bien plus utile qu'un simple oui ou non,
surtout dans un projet qui empile plusieurs .gitignore.
git check-ignore -v dist/bundle.js.gitignore:5:dist/ dist/bundle.jsPiège 1 : une négation s'affiche comme une correspondance
Section intitulée « Piège 1 : une négation s'affiche comme une correspondance »L'option -v affiche tout motif qui correspond, y compris un motif de
négation. Or un motif commençant par ! signifie exactement l'inverse : le
fichier n'est pas ignoré.
git check-ignore -v erreurs.log.gitignore:9:!erreurs.log erreurs.logLa documentation officielle le formule ainsi : « Matching an exclude pattern
usually means the path is excluded, but if the pattern begins with ! then it
is a negated pattern and matching it means the path is NOT excluded ». Une
sortie non vide ne veut donc pas dire « ignoré » : il faut regarder si le
motif commence par !.
Le code de retour n'aide pas davantage en mode -v : il vaut 0 ici, alors
que le fichier n'est pas ignoré. Sans -v, en revanche, la réponse est nette,
car la commande ne liste plus que les chemins réellement écartés :
git check-ignore erreurs.log[aucune sortie, code de retour 1]C'est cette forme qu'il faut utiliser dans un script : code 0 signifie ignoré, code 1 signifie conservé.
Lister tout ce que Git écarte
Section intitulée « Lister tout ce que Git écarte »Pour la vue d'ensemble, git status --ignored ajoute les fichiers ignorés au
rapport habituel, préfixés de !! :
git status --ignored --short?? .gitignore?? README.md?? erreurs.log?? src/!! debug.log!! dist/!! node_modules/Cette sortie regroupe les dossiers entiers. Pour obtenir la liste fichier par fichier, ce qui est nécessaire avant de vérifier qu'aucun fichier utile ne s'est fait attraper par une règle trop large :
git ls-files --others --ignored --exclude-standarddebug.logdist/bundle.jsnode_modules/express/index.jsLes trois options se lisent ensemble : --others sélectionne les fichiers non
suivis, --ignored restreint aux ignorés, et --exclude-standard applique
les règles habituelles au lieu d'exiger qu'on les fournisse à la main.
Vérifier ce que Git suit réellement
Section intitulée « Vérifier ce que Git suit réellement »La commande symétrique répond à la question la plus importante avant un push :
git ls-filesElle liste le contenu de l'index, donc tout ce que Git surveille. Un fichier qui apparaît ici est suivi, quelles que soient vos règles d'exclusion. C'est le contrôle à faire quand vous soupçonnez qu'un fichier sensible est entré dans le dépôt.
Le piège du fichier déjà suivi
Section intitulée « Le piège du fichier déjà suivi »Voici le scénario le plus fréquent. Un fichier .env a été commité par
inadvertance, puis la règle .env a été ajoutée au .gitignore. La règle
semble sans effet, et la vérification donne un résultat déroutant :
git check-ignore -v .env[aucune sortie, code de retour 1]check-ignore affirme qu'aucune règle ne s'applique, alors que la ligne existe
bel et bien. L'explication tient en une phrase de la documentation : « tracked
files are not shown at all since they are not subject to exclude rules ». Un
fichier suivi n'est pas soumis aux règles d'exclusion, la commande n'a donc rien
à en dire.
L'option --no-index demande d'ignorer l'index et de ne consulter que les
règles. Elle a été ajoutée à Git pour exactement ce diagnostic :
git check-ignore -v --no-index .env.gitignore:12:.env .envLa règle était donc correcte depuis le début. Le problème n'est pas le motif, c'est l'index. La preuve tient en une commande :
git ls-files.envLa réparation consiste à retirer le fichier de l'index sans le supprimer du
disque, ce que fait git rm --cached :
git rm --cached .envgit status --shortD .env?? .gitignore?? README.md?? erreurs.log?? src/Le D signale que la suppression est indexée : le prochain commit retirera
le fichier du dépôt. Sur le disque, il est toujours là, et il est désormais
bien ignoré :
git check-ignore -v .env.gitignore:12:.env .envLes trois endroits où Git lit des règles
Section intitulée « Les trois endroits où Git lit des règles ».gitignore n'est pas la seule source. Git en consulte trois, qui répondent à
des besoins différents.
| Fichier | Portée | Versionné | Usage |
|---|---|---|---|
.gitignore | Le dépôt, pour toute l'équipe | Oui | Règles du projet : dépendances, artefacts, secrets |
.git/info/exclude | Votre copie locale du dépôt | Non | Vos fichiers de travail, sans imposer la règle aux autres |
core.excludesFile | Toutes vos machines et tous vos dépôts | Non | Fichiers de votre éditeur ou de votre système |
Le fichier local sert quand une exclusion ne concerne que vous. Elle n'a pas à
polluer le .gitignore partagé :
echo 'notes-perso.md' >> .git/info/excludegit check-ignore -v notes-perso.md.git/info/exclude:7:notes-perso.md notes-perso.mdLa règle globale s'applique à tous vos dépôts. C'est la bonne place pour les fichiers de votre outillage personnel, que vos collègues n'ont aucune raison de subir dans le fichier partagé :
git config --global core.excludesFile ~/.gitignore_globalecho '*.bak' >> ~/.gitignore_globalgit check-ignore -v serveur.js.bak/home/dev/.gitignore_global:1:*.bak serveur.js.bakL'intérêt de check-ignore -v apparaît pleinement ici : il nomme le fichier
source, donc vous savez immédiatement laquelle des trois est en cause.
La syntaxe des motifs
Section intitulée « La syntaxe des motifs »Un motif se lit de gauche à droite, et quatre mécanismes suffisent à couvrir la quasi-totalité des besoins.
Le joker * remplace n'importe quelle suite de caractères dans un nom :
*.log attrape debug.log comme application.log. La barre oblique finale
restreint la règle aux dossiers : dist/ ignore le dossier et tout son contenu,
là où dist attraperait aussi un fichier nommé dist.
La barre oblique initiale ancre la règle à la racine du dépôt. Sans elle, un motif s'applique à n'importe quelle profondeur, ce qui surprend souvent :
git check-ignore -v config.json.gitignore:13:/config.json config.jsongit check-ignore -v src/config.json[aucune sortie, code de retour 1]Le fichier de la racine est ignoré, celui de src/ ne l'est pas. Sans le /
initial, les deux l'auraient été.
Le point d'exclamation réintègre un fichier qu'une règle précédente excluait. L'ordre compte : une exception doit venir après la règle qu'elle contredit, puisque c'est le dernier motif correspondant qui l'emporte.
Forcer l'ajout d'un fichier ignoré
Section intitulée « Forcer l'ajout d'un fichier ignoré »Git refuse d'indexer un fichier ignoré, et le dit clairement :
git add debug.logThe following paths are ignored by one of your .gitignore files:debug.loghint: Use -f if you really want to add them.L'option -f passe outre. Elle se justifie pour un artefact qu'il faut
exceptionnellement versionner, par exemple un fichier de build de
référence servant de point de comparaison :
git add -f debug.loggit status --short debug.logA debug.logCe contournement crée précisément la situation décrite plus haut : le fichier
devient suivi, et la règle qui l'exclut n'a plus prise sur lui. Préférez donc
une négation explicite dans le .gitignore, qui reste lisible pour l'équipe,
plutôt qu'un -f dont personne ne gardera la trace.
Modèles prêts à l'emploi
Section intitulée « Modèles prêts à l'emploi »GitHub maintient une collection de modèles .gitignore par langage et par
outil, sur github.com/github/gitignore.
Partir de ces modèles évite d'oublier les fichiers propres à un écosystème,
comme __pycache__/ en Python ou .terraform/ en Terraform.
Ces modèles restent un point de départ. Vérifiez toujours le résultat avec
git status --ignored, car un modèle générique peut écarter un fichier que
votre projet doit versionner.
Dépannage
Section intitulée « Dépannage »Les symptômes se ressemblent tous, mais la cause diffère selon que le fichier est déjà suivi, qu'une négation le réintègre, ou que le motif ne correspond pas à ce que vous croyez. La colonne du milieu donne la commande qui tranche entre les trois.
| Symptôme | Comment trancher | Solution |
|---|---|---|
Le fichier apparaît encore dans git status | git ls-files <fichier> le retourne | Il est suivi : git rm --cached <fichier> |
check-ignore ne trouve aucune règle, pourtant elle existe | git check-ignore -v --no-index <fichier> la montre | Le fichier est suivi, même solution |
check-ignore -v affiche une règle mais le fichier n'est pas ignoré | Le motif affiché commence par ! | Une négation le réintègre, revoyez l'ordre des lignes |
| Une négation reste sans effet | La règle affichée est un dossier avec / final | Réintégrez d'abord le dossier parent |
| Une règle attrape trop de fichiers | git ls-files --others --ignored --exclude-standard | Ancrez le motif avec un / initial |
git add refuse le fichier | Message paths are ignored | git add -f, ou ajoutez une négation |
La règle ne vient pas du .gitignore du projet | La sortie de check-ignore -v nomme le fichier source | Regardez .git/info/exclude et core.excludesFile |
À retenir
Section intitulée « À retenir ».gitignorene filtre que les fichiers non suivis : un fichier déjà commité échappe à toute règle ajoutée après coup.git check-ignore -v <fichier>désigne la règle exacte, au formatfichier:ligne:motif.- Un motif affiché commençant par
!signifie que le fichier n'est PAS ignoré, malgré un code de retour 0. - Sans
-v, le code de retour est fiable : 0 pour ignoré, 1 pour conservé. C'est la forme à scripter. --no-indexrévèle la règle qui s'applique à un fichier suivi, et prouve que le motif est correct.git rm --cachedarrête le suivi sans supprimer le fichier du disque, mais ne nettoie pas l'historique.git ls-filesliste ce que Git suit réellement : le contrôle à faire avant de pousser.- Trois sources de règles :
.gitignorepartagé,.git/info/excludelocal,core.excludesFileglobal.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous portent sur les situations où le comportement observé contredit ce que la règle laisse attendre. Chaque réponse indique la commande de vérification qui permet de trancher sur votre propre dépôt.
La cause presque toujours identique
Le fichier était déjà suivi avant l'ajout de la règle. La documentation officielle est explicite : les fichiers suivis ne sont pas soumis aux règles d'exclusion.Le diagnostic
git ls-files .env
Si le fichier apparaît, il est suivi et c'est bien la cause.git check-ignore -v --no-index .env
.gitignore:12:.env .env
L'option --no-index prouve que la règle est correcte : seul l'index bloquait.La réparation
git rm --cached .env
Le fichier reste sur le disque, mais Git cesse de le suivre au prochain commit. Attention : son contenu demeure dans tous les commits antérieurs.Vérifié sur Git 2.43.0.La commande
git check-ignore -v debug.log
.gitignore:8:*.log debug.log
La sortie se lit : ligne 8 du fichier .gitignore, motif *.log, appliqué à debug.log.Pourquoi le nom du fichier source compte
Git lit des règles à trois endroits. La sortie indique lequel s'applique :| Sortie observée | Source |
|---|---|
.gitignore:8:*.log |
Règle partagée du dépôt |
.git/info/exclude:7:notes-perso.md |
Règle locale, non versionnée |
/home/dev/.gitignore_global:1:*.bak |
Règle globale de la machine |
Le piège
Avec-v, Git affiche tout motif qui correspond, négations comprises.git check-ignore -v erreurs.log
.gitignore:9:!erreurs.log erreurs.log
La documentation le précise : matching an exclude pattern usually means the path is excluded, but if the pattern begins with ! then it is a negated pattern and matching it means the path is NOT excluded.Le code de retour vaut 0 dans ce cas, alors que le fichier n'est pas ignoré.La forme fiable pour un script
git check-ignore erreurs.log
Sans -v, rien n'est affiché et le code de retour vaut 1. La règle est simple : 0 pour ignoré, 1 pour conservé.Vérifié sur Git 2.43.0.Vue d'ensemble
git status --ignored --short
?? README.md
!! debug.log
!! dist/
!! node_modules/
Le préfixe !! marque les fichiers ignorés. Les dossiers sont regroupés.Liste fichier par fichier
git ls-files --others --ignored --exclude-standard
debug.log
dist/bundle.js
node_modules/express/index.js
--others: les fichiers non suivis--ignored: restreint aux ignorés--exclude-standard: applique les règles habituelles
La cause
Git n'entre pas dans un dossier exclu. La négation portant sur un fichier interne n'est donc jamais évaluée.git check-ignore -v node_modules/patch-maison/correctif.js
.gitignore:2:node_modules/ node_modules/patch-maison/correctif.js
C'est bien node_modules/ qui l'emporte, pas la négation écrite plus bas.La solution
Réintégrer d'abord le dossier, puis le fichier :node_modules/
!node_modules/patch-maison/
L'autre cause fréquente
L'ordre des lignes. C'est le dernier motif correspondant qui gagne : une exception doit venir après la règle qu'elle contredit.Vérifié sur Git 2.43.0.Pour un seul dépôt
Le fichier.git/info/exclude n'est pas versionné : la règle ne concerne que votre copie.echo 'notes-perso.md' >> .git/info/exclude
git check-ignore -v notes-perso.md
.git/info/exclude:7:notes-perso.md notes-perso.md
Pour tous vos dépôts
git config --global core.excludesFile ~/.gitignore_global
echo '*.bak' >> ~/.gitignore_global
C'est la bonne place pour les fichiers de votre éditeur ou de votre système, que vos collègues n'ont aucune raison de subir dans le .gitignore du projet.Vérifié sur Git 2.43.0.Oui, et c'est tout l'intérêt
Le.gitignore est un fichier du projet. Le versionner garantit que chaque personne qui clone le dépôt hérite des mêmes exclusions, sans quoi un collaborateur réintroduira node_modules/ au premier git add ..Il apparaît d'ailleurs comme un fichier ordinaire dans git status :git status --short
?? .gitignore
?? README.md
Ce qui ne doit pas y aller
Les règles strictement personnelles (fichiers d'éditeur, brouillons) n'ont rien à y faire. Elles vont dans.git/info/exclude, qui n'est pas versionné.Vérifié sur Git 2.43.0.