infra / git-github
.gitignore avancé et gitattributes
Explication
Ce que vous allez apprendre
- Écrire des règles
.gitignoreprécises, avec exceptions et exclusions par profondeur - Comprendre pourquoi une règle
.gitignoren'affecte jamais un fichier déjà suivi - Retirer un fichier du suivi Git sans le supprimer du disque avec
git rm --cached - Utiliser
.gitattributespour normaliser les fins de ligne et marquer des fichiers binaires - Reconnaître le cas d'usage de Git LFS pour les gros fichiers binaires
Dans quel contexte ?
Un développeur ajoute par erreur son fichier secrets.json, contenant une clé d'API de paiement, au tout premier commit du projet boutique-api. En ajoutant secrets.json au .gitignore par la suite, il pense avoir réglé le problème, mais le fichier continue d'apparaître à chaque git status : la règle .gitignore ne s'applique jamais rétroactivement à un fichier déjà suivi.
Des fichiers qui n'ont rien à faire dans l'historique
D'abord, un projet contient toujours des fichiers qui n'ont aucun intérêt à être suivis par Git : des dépendances téléchargées automatiquement, des fichiers de build générés, des logs, des identifiants secrets.
Le risque de les inclure quand même
Les inclure encombrerait l'historique et, pire pour les secrets, pourrait constituer une vraie fuite de sécurité.
La solution : définir les exclusions une fois pour toutes
Le .gitignore définit ces exclusions une fois pour toutes, pour que Git n'en tienne jamais compte, même si quelqu'un les ajoute par erreur avec git add ..
Un piège fréquent, très concret
Une confusion classique : ajouter une règle .gitignore pour un fichier déjà suivi ne le retire pas rétroactivement de Git.
Ce qui se passe malgré la règle ajoutée
Le fichier continue d'apparaître comme modifié à chaque changement. Il faut une commande explicite pour dire à Git "arrête de suivre ce fichier", tout en le laissant sur le disque.
Piège dangereux
Ajouter secrets.json au .gitignore après qu'il ait déjà été commité ne le retire ni du suivi Git ni de l'historique déjà partagé. Utilise git rm --cached secrets.json pour arrêter de le suivre, et sache qu'un secret déjà poussé sur GitHub doit être considéré comme compromis et changé, pas seulement "caché".
Un problème différent : comment traiter certains fichiers
Une fois les exclusions réglées, .gitattributes s'attaque à un problème différent et plus subtil : comment Git doit-il traiter certains fichiers, plutôt que simplement les ignorer ou non.
Deux exemples concrets de ce que ça résout
Normaliser les fins de ligne évite des différences fantômes entre systèmes Windows et Unix, un fichier identique qui semble "modifié" uniquement à cause du type de saut de ligne. Marquer des fichiers comme binaires évite à Git de tenter des comparaisons ou fusions absurdes sur des images ou des PDF.
Le cas particulier des gros fichiers
Enfin, Git a été conçu pour du code texte, pas pour de gros fichiers binaires, comme des images sources ou des vidéos, qui gonfleraient démesurément la taille de l'historique.
La solution pour ce cas précis
Git LFS (Large File Storage) contourne cette limite en stockant réellement le contenu de ces gros fichiers ailleurs, ne gardant dans l'historique Git qu'une référence légère vers eux.
Fichier .gitattributes | Effet |
|---|---|
* text=auto eol=lf | Normalise les fins de ligne sur tout le dépôt |
*.png binary | Empêche Git de tenter un diff/merge texte sur ce fichier |
*.psd filter=lfs | Stocke le fichier via Git LFS plutôt que dans l'historique classique |
La dernière leçon de ce cours s'attaque à un problème de confiance que le simple nom d'auteur ne résout pas : prouver cryptographiquement qui a vraiment écrit un commit.
Commandes & code
.gitignore avancé & .gitattributes
# .gitignore - patterns avancés
node_modules/
dist/
*.log
# Exception : ne pas ignorer CE fichier précis malgré la règle *.log ci-dessus
!important.log
# Ignorer un dossier à n'importe quelle profondeur
**/tmp/
# Ignorer un fichier uniquement à la racine (pas dans les sous-dossiers)
/config.local.json
# Ignorer toutes les extensions d'un type, sauf un exemple versionné
*.env
!.env.example# Un fichier déjà TRACKÉ n'est pas affecté rétroactivement par .gitignore
echo "secrets.json" >> .gitignore
git status # secrets.json continue d'apparaître s'il était déjà suivi
# Il faut le retirer explicitement du suivi (le fichier reste sur le disque)
git rm --cached secrets.json
git commit -m "chore: stop tracking secrets.json"
# Debug : pourquoi un fichier est-il ignoré (ou pas) ?
git check-ignore -v config.local.json# .gitattributes - normalise les fins de ligne entre OS (évite les diffs fantômes)
* text=auto eol=lf
*.bat text eol=crlf
# Marque des fichiers comme binaires : Git ne tente jamais de diff/merge texte dessus
*.png binary
*.pdf binary
# Stratégie de merge dédiée pour un fichier généré automatiquement (garde toujours "ours")
package-lock.json merge=ours
# Exclut certains fichiers des exports "git archive" (changelog interne, scripts de dev)
CHANGELOG.internal.md export-ignore# Activer la stratégie de merge custom déclarée dans .gitattributes
git config merge.ours.driver true# Git LFS pour les gros fichiers binaires (images sources, vidéos, modèles ML)
git lfs install
git lfs track "*.psd"
git add .gitattributes # LFS ajoute ses propres règles ici automatiquement
git add design.psd
git commit -m "Add design mockup via LFS"Résumé
.gitignoren'affecte pas les fichiers déjà trackés :git rm --cachedest nécessaire.git check-ignore -vdiagnostique précisément quelle règle ignore (ou non) un fichier..gitattributesnormalise les fins de ligne et évite les diffs binaires illisibles.- Git LFS externalise le contenu des gros fichiers binaires hors de l'historique Git classique.
Exercices pratiques
Mission : réparer une fuite de secret déjà commitée
Objectif : Corriger un fichier sensible déjà suivi par Git malgré une règle .gitignore ajoutée après coup, et sécuriser durablement la situation.
Contexte
Un développeur a commité par erreur secrets.json, contenant une clé d'API de paiement, dès le premier commit de boutique-api. Il ajoute ensuite secrets.json au .gitignore, mais le fichier continue d'apparaître comme modifié à chaque git status.