Retour au cours

infra / git-github

.gitignore avancé et gitattributes

Leçon 161 exercice

Explication

Ce que vous allez apprendre

  • Écrire des règles .gitignore précises, avec exceptions et exclusions par profondeur
  • Comprendre pourquoi une règle .gitignore n'affecte jamais un fichier déjà suivi
  • Retirer un fichier du suivi Git sans le supprimer du disque avec git rm --cached
  • Utiliser .gitattributes pour 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 .gitattributesEffet
* text=auto eol=lfNormalise les fins de ligne sur tout le dépôt
*.png binaryEmpêche Git de tenter un diff/merge texte sur ce fichier
*.psd filter=lfsStocke 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
# .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
bash
# 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
# .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
bash
# Activer la stratégie de merge custom déclarée dans .gitattributes
git config merge.ours.driver true
bash
# 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é

  • .gitignore n'affecte pas les fichiers déjà trackés : git rm --cached est nécessaire.
  • git check-ignore -v diagnostique précisément quelle règle ignore (ou non) un fichier.
  • .gitattributes normalise 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

1 disponible
1

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.

Résoudre l’exercice →