Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 316 minDébutant

Le fichier .gitignore et les secrets

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • dire ce qui ne doit jamais entrer dans un dépôt ;
  • écrire un .gitignore adapté à ton projet ;
  • garder les secrets dans un .env et fournir un .env.example ;
  • réagir si un secret est parti dans un commit.

3 exercices corrigés

Le fichier .gitignore liste les fichiers et dossiers que Git doit ignorer : dépendances réinstallables, fichiers générés, réglages personnels de l'éditeur et surtout les fichiers qui contiennent des secrets, comme le .env. Ce chapitre donne sa syntaxe, des modèles prêts pour les langages du BTS SIO, la méthode pour arrêter de suivre un fichier déjà commité, et la procédure à suivre quand un mot de passe est parti sur GitHub.

Ce qui ne doit pas entrer dans un dépôt

Un dépôt contient ce qu'il faut pour reconstruire le projet, et rien d'autre.

À ignorerExemplesPourquoi
Les dépendancesnode_modules/, vendor/ (Composer), packages/Énormes, réinstallables avec npm install ou composer install à partir du fichier de dépendances, qui lui est versionné
Les fichiers générésdist/, build/, bin/, obj/, *.class, __pycache__/Produits par la compilation : on versionne la source, pas le résultat
Les secrets.env, appsettings.Development.json avec un mot de passe, clés privées *.pemQuiconque lit le dépôt lirait les mots de passe
Les donnéesSauvegardes *.sql de production, fichiers déposés par les utilisateurs (uploads/), bases SQLite de travailDonnées personnelles, volume, et ce n'est pas du code
Les journaux et fichiers temporaires*.log, *.tmp, *.swpPropres à une exécution
Les fichiers du système et de l'éditeur.DS_Store (macOS), Thumbs.db (Windows), .idea/, .vs/Propres à ta machine

La syntaxe du .gitignore

Le fichier s'appelle exactement .gitignore, sans extension, et se place à la racine du dépôt. Une règle par ligne :

RègleCe qu'elle ignore
fichier.txtTout fichier ou dossier nommé fichier.txt, à n'importe quel niveau
/fichier.txtSeulement celui de la racine (le / initial ancre la règle au dossier du .gitignore)
dossier/Un dossier de ce nom et tout son contenu, à n'importe quel niveau (le / final vise les dossiers seulement)
*.logTous les fichiers qui finissent par .log ; * remplace n'importe quelle suite de caractères sauf /
config/*.jsonLes .json directement dans config/, pas dans ses sous-dossiers
**/temptemp dans n'importe quel sous-dossier ; ** traverse les niveaux
logs/**/*.logLes .log à n'importe quelle profondeur sous logs/
!important.logException : ce fichier n'est pas ignoré, même si une règle précédente l'ignorait
# DépendancesUn commentaire

L'ordre compte : la dernière règle qui correspond l'emporte. Une exception ! ne fonctionne pas si le dossier parent est lui-même ignoré, car Git n'entre pas dans un dossier ignoré.

text
# Ignorer tous les fichiers de logs/ sauf le .gitkeep qui garde le dossier dans le dépôt
logs/*
!logs/.gitkeep

Git ne versionne pas les dossiers vides. Pour qu'un dossier existe dans le dépôt, on y place par convention un fichier vide nommé .gitkeep.

Des .gitignore pour les projets du BTS SIO

Tu n'as pas à tout écrire de zéro. GitHub propose un modèle par langage quand tu crées un dépôt, et le dépôt public github/gitignore en rassemble des centaines. Voici des bases courtes pour les projets que tu feras.

Node.js, Express et React :

text
# Dépendances
node_modules/

# Builds
dist/
build/

# Secrets et configuration locale
.env
.env.*
!.env.example

# Journaux
*.log
npm-debug.log*

# Couverture des tests
coverage/

# Système et éditeurs
.DS_Store
Thumbs.db
.idea/
.vscode/*
!.vscode/extensions.json

PHP et Symfony :

text
/vendor/
/var/
/public/uploads/
.env.local
.env.*.local
/.phpunit.cache/

Symfony a une convention à lui : le fichier .env est versionné et ne contient que des valeurs par défaut sans secret ; les vraies valeurs vont dans .env.local, ignoré. Les modèles créés par symfony new ou par Flex l'appliquent déjà.

C# et .NET (Visual Studio) :

text
bin/
obj/
.vs/
*.user
appsettings.Development.json

dotnet new gitignore génère le modèle complet maintenu par Microsoft. Pour un projet WinForms ou ASP.NET, c'est la bonne solution.

Python et Java : __pycache__/, .venv/, *.pyc d'un côté ; target/ (Maven), build/ et .gradle/ (Gradle), *.class de l'autre.

Le .env et le .env.example

Une application a besoin de réglages qui changent selon l'endroit où elle tourne : l'adresse de la base, son mot de passe, la clé qui signe les jetons de connexion. On les range dans des variables d'environnement, souvent lues depuis un fichier .env à la racine du projet.

text
# .env : jamais versionné
DB_HOST=localhost
DB_USER=sorbier_app
DB_PASSWORD=Kq7!vT2pL9zR
JWT_SECRET=4f9d2c7e8b1a6f3d0c5e9b2a7d4f1c8e

Le problème : un nouveau membre de l'équipe, ou la commission de l'E6, ne sait pas quelles variables créer. La solution est un fichier .env.example, versionné, qui liste les mêmes variables avec des valeurs factices :

text
# .env.example : versionné, copie-le en .env et remplis les valeurs
DB_HOST=localhost
DB_USER=sorbier_app
DB_PASSWORD=change-moi
JWT_SECRET=genere-une-longue-chaine-aleatoire

Le README explique : « copie .env.example en .env et remplis les valeurs ». Ce couple .env ignoré et .env.example versionné est ce que la commission s'attend à trouver dans ton dépôt (préparer son dépôt pour l'examen).

Vérifier qu'un fichier est bien ignoré

Après avoir écrit ton .gitignore, git status ne doit plus afficher les fichiers ignorés. Pour comprendre pourquoi un fichier est ignoré, ou ne l'est pas :

bash
git check-ignore -v .env
text
.gitignore:7:.env	.env

La règle .env de la ligne 7 du .gitignore ignore ce fichier. Si la commande n'affiche rien, aucune règle ne l'ignore. git status --ignored liste en plus les fichiers ignorés présents dans ton dossier.

Un fichier ignoré mais déjà suivi

C'est le piège classique. Tu ajoutes .env au .gitignore, mais git status continue d'afficher modified: .env. La raison : le .gitignore ne concerne que les fichiers non suivis. Un fichier déjà commité reste suivi, quelles que soient les règles.

Pour arrêter de le suivre sans le supprimer de ton disque :

bash
git rm --cached .env
git commit -m "Retire .env du suivi"

--cached agit seulement sur la zone de préparation : le fichier reste sur ton disque, mais il ne fera plus partie des prochains commits. Pour un dossier entier, ajoute -r : git rm -r --cached node_modules.

Le .gitignore global

Les fichiers propres à ta machine (.DS_Store, Thumbs.db, les réglages de ton éditeur) n'ont pas leur place dans le .gitignore de chaque projet. Range-les dans un fichier global, valable pour tous tes dépôts :

bash
git config --global core.excludesFile ~/.gitignore_global

Puis écris tes règles dans ~/.gitignore_global. Pour ignorer un fichier dans un seul dépôt sans toucher au .gitignore partagé, utilise .git/info/exclude, qui n'est jamais versionné.

Que faire si un secret est parti dans un commit

Ça arrive à tout le monde, une fois. Le réflexe à avoir dépend d'une seule question : le commit a-t-il été poussé ?

Le commit n'a pas été poussé. Le secret n'existe que sur ta machine. Retire-le du commit avant que quiconque le voie :

bash
# Le secret est dans le dernier commit
echo ".env" >> .gitignore
git rm --cached .env
git add .gitignore
git commit --amend --no-edit

--amend remplace le dernier commit par une version sans le .env (modifier le dernier commit). Si le secret est dans un commit plus ancien, mais toujours non poussé, un rebase interactif permet de corriger ce commit (chapitre 7).

Le commit a été poussé. Considère le secret comme public, même si le dépôt est privé et même s'il n'est resté en ligne que trente secondes : des robots scrutent en permanence les dépôts publics à la recherche de clés, et un dépôt privé se clone, se partage et devient parfois public. La procédure, dans cet ordre :

  1. Révoquer le secret. Change le mot de passe de la base, régénère la clé d'API, crée un nouveau jeton. C'est la seule étape qui protège vraiment : un secret révoqué ne vaut plus rien, qu'il traîne dans l'historique ou non.
  2. Vérifier les dégâts. Consulte les journaux du service concerné : connexions inconnues, appels d'API, frais facturés. Préviens ton responsable ou ton tuteur.
  3. Retirer le fichier du suivi avec git rm --cached et l'ajouter au .gitignore, comme ci-dessus, puis pousser.
  4. Nettoyer l'historique si le dépôt est public ou si le secret ne peut pas être changé. L'outil recommandé par la documentation de Git est git filter-repo, un programme Python à installer à part (pip install git-filter-repo, ou le paquet git-filter-repo de ta distribution) :
bash
# Dans un clone frais du dépôt
git filter-repo --invert-paths --path .env
git remote add origin https://github.com/ton-pseudo/sorbier-frais.git
git push origin --force --all
git push origin --force --tags

--path .env --invert-paths réécrit chaque commit de l'historique en supprimant ce fichier. Par sécurité, git filter-repo retire le dépôt distant origin de ta configuration : tu dois le rajouter avant de pousser. Chaque commit réécrit change d'empreinte : tous les membres de l'équipe doivent ensuite recloner le dépôt, sinon un simple git push de leur part réintroduirait l'ancien historique. Sur GitHub, des copies peuvent subsister dans les forks et dans les pull requests en cache : pour un secret sensible, le support de GitHub peut les purger.

Les garde-fous automatiques

Mieux vaut que l'outil t'arrête avant le push :

  • La protection contre les secrets de GitHub (secret scanning push protection) est active par défaut sur les dépôts publics : si ton commit contient une clé reconnue (jeton GitHub, clé AWS, clé Stripe…), GitHub refuse le push et t'indique le fichier et la ligne. Elle ne reconnaît pas un simple mot de passe de base de données : elle ne remplace pas ta vigilance.
  • Des outils comme Gitleaks analysent ton dépôt et son historique en local ou dans ton pipeline d'intégration continue, et détectent aussi des motifs génériques.
  • Un .gitignore posé au premier commit, avec .env dedans, avant tout git add ..

Exercices

Exercice 1 sur 3 Que fait cette règle ? Réussi À revoir

Pour chaque fichier, dis s'il est ignoré par ce .gitignore, placé à la racine du dépôt :

text
*.log
!erreurs.log
/build/
config/*.local.json
  1. serveur.log
  2. logs/erreurs.log
  3. build/app.js
  4. src/build/outil.js
  5. config/base.local.json
  6. config/prod/base.local.json
Voir la réponseMasquer la réponse de l'exercice 1
  1. Ignoré : il correspond à *.log.
  2. Non ignoré : *.log l'ignore, mais l'exception !erreurs.log, écrite après, l'emporte. Sans /, elle vaut à n'importe quel niveau.
  3. Ignoré : /build/ vise le dossier build de la racine.
  4. Non ignoré : le / initial ancre la règle à la racine, src/build/ n'est pas concerné.
  5. Ignoré : il est directement dans config/ et correspond à *.local.json.
  6. Non ignoré : * ne traverse pas les /, et le fichier est dans un sous-dossier de config/. Il faudrait config/**/*.local.json.

Tu avais trouvé ?

Exercice 2 sur 3 Le .env déjà commité Réussi À revoir

Hugo a commité et poussé le .env de l'API il y a trois jours, avec le mot de passe de la base de test et la clé qui signe les jetons de connexion. Le dépôt est public. Il vient d'ajouter .env au .gitignore, mais git status affiche toujours modified: .env.

  1. Pourquoi le .gitignore n'a-t-il aucun effet ?
  2. Donne, dans l'ordre, les actions à mener.
  3. Que doit faire Lina après le nettoyage de l'historique ?
Voir la réponseMasquer la réponse de l'exercice 2
  1. Le .gitignore ne s'applique qu'aux fichiers non suivis. Le .env a déjà été commité : Git continue de le suivre.
  2. D'abord révoquer : changer le mot de passe du compte MySQL et générer une nouvelle clé de signature des jetons (les anciens jetons deviennent invalides, les utilisateurs devront se reconnecter). Ensuite vérifier les journaux du serveur de test. Puis git rm --cached .env, commit et push. Enfin, comme le dépôt est public, nettoyer l'historique avec git filter-repo --invert-paths --path .env dans un clone frais, rajouter le distant et pousser avec --force. Créer au passage un .env.example avec des valeurs factices.
  3. Sauvegarder son propre .env, puis supprimer son clone et recloner le dépôt. Si elle poussait depuis son ancien clone, elle réintroduirait les commits qui contiennent le secret.

Tu avais trouvé ?

Exercice 3 sur 3 Écrire un .gitignore Réussi À revoir

Écris le .gitignore d'un projet Symfony qui contient aussi un dossier front/ avec une application React. Le front a ses propres dépendances npm et produit un dossier front/dist. Les utilisateurs déposent des justificatifs dans public/uploads/. On garde le dossier public/uploads/ dans le dépôt, vide.

Voir la réponseMasquer la réponse de l'exercice 3
text
# Symfony
/vendor/
/var/
.env.local
.env.*.local

# Justificatifs déposés : on garde le dossier, pas son contenu
/public/uploads/*
!/public/uploads/.gitkeep

# Front React
/front/node_modules/
/front/dist/

# Système et éditeurs
.DS_Store
Thumbs.db
.idea/

Il faut créer le fichier vide public/uploads/.gitkeep et le versionner. La règle /public/uploads/* ignore le contenu du dossier, pas le dossier lui-même : c'est pour cela que l'exception fonctionne. Avec /public/uploads/, Git n'entrerait plus dans le dossier et l'exception serait sans effet.

Tu avais trouvé ?

Chapitre terminé !

Fais les 3 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Annuler en Git : restore, reset, revert et reflogRevoir le sommaire du cours