Préparation d'entretien 100% Gratuit angularforall.com

Entretien Git Senior — Workflows, Hooks et Internals

Git Senior Quiz-Git-Senior Git-Workflow Git-Hooks Git-Internals Entretien-Git-Senior Qcm-Git-Expert Git-Bisect Git-Reflog Gitflow Git-Submodules Git-Worktree Rebase-Interactif
Sénior 🔀 Mixte 20 questions ⏱ 20 min
📝

Entretien Git Senior — Workflows, Hooks et Internals

Maîtrisez Git en expert avec 20 questions niveau senior : workflows, hooks, rebase interactif, bisect, reflog et internals. Pour leads et architectes.

20 questions ⏱ ~20 min Niveau Sénior

Partager

Banque de révision : les 60 questions corrigées

Voici l'intégralité des 60 questions de « Entretien Git Senior — Workflows, Hooks et Internals », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.

  • fixup
  • squash (bonne réponse)
  • reword
  • edit
Explication : Dans git rebase -i, squash fond le commit dans le précédent et ouvre l'éditeur pour combiner les deux messages. fixup fait la même fusion mais jette le message du commit fusionné. reword ne fusionne rien, il ne fait que réécrire le message. edit met en pause le rebase pour amender le commit.
squash garde les messages, fixup les jette.

  • Elle déplace le commit en fin de liste
  • Elle supprime complètement le commit de l'historique réécrit (bonne réponse)
  • Elle marque le commit pour résolution de conflit
  • Elle convertit le commit en stash
Explication : Remplacer pick par drop (ou simplement supprimer la ligne) retire le commit de l'historique reconstruit. Les modifications qu'il portait sont alors perdues, sauf récupération via git reflog. C'est l'équivalent ciblé d'un git reset sur un seul commit du milieu de l'historique.
Supprimer la ligne équivaut à drop.

  • fixup réordonne les commits, squash ne le fait pas
  • squash crée un nouveau commit, fixup amende le précédent en place
  • fixup conserve le message du commit fusionné, squash le supprime
  • fixup ignore le message du commit fusionné, squash propose de le combiner (bonne réponse)
Explication : Les deux fusionnent un commit dans son prédécesseur. squash ouvre l'éditeur pour combiner les messages des deux commits. fixup applique silencieusement les changements et conserve uniquement le message du commit cible, sans ouvrir d'éditeur. C'est pourquoi git commit --fixup=<sha> associé à rebase -i --autosquash automatise le nettoyage.
fixup = squash silencieux.

  • git bisect run ./test.sh (bonne réponse)
  • git bisect auto ./test.sh
  • git bisect script ./test.sh
  • git bisect check ./test.sh
Explication : git bisect run <script> exécute le script à chaque étape de la dichotomie. Le code de sortie détermine le verdict : 0 signifie « good », 1 à 124 (sauf 125) signifie « bad », et 125 signifie « skip » (commit non testable). Git converge ainsi vers le premier commit fautif sans intervention manuelle.
Code de sortie 0 = good, 1 = bad, 125 = skip.

  • git bisect start, puis git bisect bad, puis git bisect good (bonne réponse)
  • git bisect good, puis git bisect bad, puis git bisect start
  • git bisect bad, puis git bisect start, puis git bisect good
  • git bisect start, puis git bisect run, puis git bisect good
Explication : On lance d'abord git bisect start, puis on marque la version actuelle cassée avec git bisect bad, puis un commit ancien sain avec git bisect good <sha>. Git checkout alors un commit médian. On répète bad/good jusqu'à isolation. Un git bisect reset final restaure la branche d'origine.
start, bad, good : Git fait le reste par dichotomie.

  • Elle désigne le commit parent numéro 2 de HEAD
  • Elle désigne la 3e position historique prise par HEAD selon le reflog (bonne réponse)
  • Elle désigne le 2e commit de la branche main
  • Elle désigne le commit fusionné lors du 2e merge
Explication : HEAD@{n} est une référence du reflog : elle pointe vers la valeur que HEAD avait n déplacements en arrière. HEAD@{0} est la position actuelle, HEAD@{2} l'avant-avant-dernière. On peut aussi utiliser une date : HEAD@{yesterday}. C'est l'outil clé pour récupérer un état perdu après un reset.
HEAD@{n} = position de HEAD il y a n déplacements.

  • git fsck --recover puis git checkout
  • git revert HEAD --restore
  • Retrouver le SHA via git reflog puis git reset --hard sur ce SHA (bonne réponse)
  • git stash pop --force
Explication : Le commit n'est pas détruit immédiatement : il devient dangling mais reste accessible. git reflog liste les positions récentes de HEAD ; on y repère le SHA perdu, puis on exécute git reflog git reset --hard HEAD@{1} ou directement sur le SHA. Tant que git gc n'a pas purgé l'objet (rétention par défaut 90 jours), la récupération est garantie.
Le reflog est ton filet de sécurité local.

  • pre-commit
  • commit-msg (bonne réponse)
  • post-commit
  • pre-push
Explication : Le hook commit-msg reçoit en argument le chemin du fichier temporaire contenant le message. Il peut donc le lire, le valider contre une regex (ex : feat:, fix:) et renvoyer un code non nul pour annuler le commit. pre-commit s'exécute avant que le message soit saisi, il sert plutôt au lint et aux tests.
commit-msg = validation du texte du message.

  • pre-receive
  • update
  • post-receive (bonne réponse)
  • post-update
Explication : post-receive s'exécute une fois, côté serveur, après que toutes les refs ont été mises à jour. Il reçoit sur stdin les triplets ancien-SHA / nouveau-SHA / nom-de-ref. C'est le point d'entrée classique pour notifier une CI, mettre à jour un site ou déclencher un déploiement. pre-receive, lui, peut rejeter le push avant écriture des refs.
post-receive = déclenchement post-push côté serveur.

  • prepare-commit-msg (bonne réponse)
  • commit-msg
  • pre-commit
  • applypatch-msg
Explication : prepare-commit-msg s'exécute après la génération du message par défaut mais avant l'ouverture de l'éditeur. Il reçoit le chemin du fichier de message et la source (message, merge, squash, template). On l'utilise pour injecter automatiquement un numéro de ticket, un préfixe de branche ou un template. commit-msg, lui, intervient après la saisie pour valider.
prepare-commit-msg agit avant l'éditeur, commit-msg après.

  • Husky chiffre les hooks pour la sécurité
  • Husky rend les hooks versionnables et partagés via le dépôt et package.json (bonne réponse)
  • Husky exécute les hooks côté serveur uniquement
  • Husky remplace le dossier .git par un dossier .husky chiffré
Explication : Les hooks natifs vivent dans .git/hooks, qui n'est pas versionné : impossible de les partager nativement avec l'équipe. Husky configure core.hooksPath vers un dossier .husky/ committé, garantissant que chaque développeur exécute les mêmes contrôles après npm install. Cela standardise lint, tests et validation de message à l'échelle du projet.
.git/hooks n'est pas versionné : Husky règle ce problème.

  • Le trunk-based interdit toute branche et tout merge
  • Le trunk-based privilégie des branches courtes et une intégration continue sur une branche principale unique (bonne réponse)
  • Gitflow ne possède pas de branche de release
  • Gitflow impose un déploiement continu en production
Explication : Le trunk-based development mise sur des branches très courtes (souvent moins d'un jour) fusionnées fréquemment dans main, soutenu par des feature flags pour masquer le code incomplet. Gitflow, lui, multiplie les branches de longue durée (develop, release/*, hotfix/*), ce qui retarde l'intégration et augmente les conflits. Le trunk-based est mieux adapté au déploiement continu.
Trunk-based : branches courtes, intégration fréquente.

  • Elle reçoit uniquement les correctifs de production urgents
  • Elle est la branche d'intégration où les fonctionnalités terminées sont fusionnées avant une release (bonne réponse)
  • Elle est déployée directement en production à chaque commit
  • Elle contient uniquement la documentation du projet
Explication : Dans Gitflow, develop est la branche d'intégration : les branches feature/* y sont fusionnées une fois terminées. Quand un lot de fonctionnalités est prêt, on crée une branche release/* à partir de develop. Les hotfix/* partent de main. main ne contient que des versions livrées et taguées.
develop intègre, main livre, dans Gitflow.

  • Une branche par environnement plus des branches de release
  • Un modèle simple : branches de fonctionnalité issues de main, pull request, merge, déploiement (bonne réponse)
  • Un modèle interdisant les pull requests
  • Un workflow réservé aux dépôts privés
Explication : Le GitHub Flow est volontairement minimaliste : main est toujours déployable, chaque travail part d'une branche dédiée, une pull request ouvre la revue et la discussion, puis le merge dans main déclenche le déploiement. Il n'y a pas de branche develop ni release. Le GitLab Flow ajoute, lui, des branches d'environnement (staging, production).
GitHub Flow : main + branches + PR, rien de plus.

  • Trois : blob, tree et commit
  • Quatre : blob, tree, commit et tag (bonne réponse)
  • Deux : commit et tree
  • Cinq : blob, tree, commit, tag et ref
Explication : Git stocke quatre types d'objets : le blob (contenu d'un fichier), le tree (un répertoire, listant blobs et sous-trees), le commit (instantané pointant vers un tree, des parents, auteur et message) et le tag annoté (objet pointant vers un autre objet avec métadonnées). Une ref n'est pas un objet mais un simple pointeur nommé vers un SHA.
blob, tree, commit, tag : les 4 objets de Git.

  • Le diff par rapport au commit parent
  • Une référence à un tree, les parents, l'auteur, le committer et le message (bonne réponse)
  • La liste complète des blobs modifiés et leur contenu
  • Uniquement le SHA du fichier modifié et son nouveau contenu
Explication : Un objet commit ne stocke pas de diff : il pointe vers un unique tree représentant l'instantané complet du projet à cet instant, vers zéro, un ou plusieurs commits parent, et contient les lignes author, committer et le message. Les diffs sont calculés à la demande entre deux trees. C'est un modèle d'instantanés, pas de deltas.
Git stocke des instantanés, pas des diffs.

  • Un fichier de sauvegarde du dossier de travail
  • Une archive compressée regroupant de nombreux objets avec compression delta (bonne réponse)
  • Un index des branches distantes
  • Un fichier journal des hooks exécutés
Explication : Les objets « loose » individuels finissent regroupés dans des packfiles (.git/objects/pack/*.pack), accompagnés d'un fichier .idx. Le packfile applique une compression delta entre objets similaires, réduisant fortement la taille du dépôt et accélérant les transferts réseau. git gc et git repack génèrent et optimisent ces fichiers.
Packfile = objets compressés en delta pour gagner de l'espace.

  • SHA-256 accélère significativement les opérations de commit
  • SHA-1 est vulnérable aux attaques de collision, SHA-256 renforce l'intégrité (bonne réponse)
  • SHA-256 réduit la taille des objets stockés
  • SHA-1 ne supportait pas les fichiers binaires
Explication : Des attaques de collision pratiques sur SHA-1 (ex : SHAttered) ont montré qu'on pouvait théoriquement forger deux objets de même empreinte. Git a donc introduit un mode de dépôt utilisant SHA-256, qui n'a pas de collision connue, pour garantir l'intégrité cryptographique de l'historique. La migration reste progressive pour des raisons de compatibilité de l'écosystème.
SHA-256 : réponse aux collisions de SHA-1.

  • .gitmodules (bonne réponse)
  • .gitsubmodule
  • .submodules
  • .git/config uniquement
Explication : git submodule add <url> <chemin> crée ou met à jour le fichier .gitmodules à la racine, qui est versionné et partagé. Il décrit le chemin et l'URL de chaque sous-module. Le dépôt parent enregistre en plus un gitlink : une entrée de tree pointant vers un SHA précis du sous-module. La config locale .git/config ne reçoit l'URL qu'après submodule init.
.gitmodules est versionné, .git/config est local.

  • Les sous-modules sont clonés mais leurs branches sont supprimées
  • Les dossiers de sous-modules restent vides tant qu'on ne fait pas submodule init et update (bonne réponse)
  • Les sous-modules écrasent le dépôt parent
  • Le clone échoue toujours en présence de sous-modules
Explication : Un git clone sans option ne récupère pas le contenu des sous-modules : leurs dossiers restent vides. Il faut ensuite git submodule update --init --recursive, ou cloner directement avec --recurse-submodules. Autre piège : un sous-module se trouve en detached HEAD sur le SHA enregistré, il faut donc faire attention en y committant directement.
clone --recurse-submodules évite les dossiers vides.

  • À compresser plusieurs branches dans un seul commit
  • À créer plusieurs répertoires de travail liés à un même dépôt, chacun sur une branche différente (bonne réponse)
  • À synchroniser deux dépôts distants
  • À transformer un sous-module en dépôt indépendant
Explication : git worktree add ../hotfix hotfix crée un second répertoire de travail rattaché au même dépôt .git, checkouté sur une autre branche. On peut ainsi corriger un bug urgent sans stash ni perdre l'état de la branche en cours. Chaque worktree a son index et son HEAD, mais partage les objets. Une même branche ne peut être active que dans un seul worktree.
worktree : plusieurs dossiers, un seul dépôt.

  • De rejouer automatiquement des résolutions de conflits déjà effectuées (bonne réponse)
  • De réinitialiser le dépôt à son état initial
  • De redémarrer un rebase interrompu
  • De répliquer un dépôt vers plusieurs remotes
Explication : rerere signifie « reuse recorded resolution ». Activé via git config rerere.enabled true, il enregistre la façon dont on résout un conflit. Si le même conflit réapparaît plus tard (typiquement lors de rebases répétés d'une branche de longue durée), Git réapplique automatiquement la résolution mémorisée. C'est un gain de temps majeur sur les longues branches.
rerere : Git mémorise et rejoue tes résolutions.

  • filter-repo fonctionne sans installer Git
  • filter-repo est plus rapide, plus sûr et évite les pièges connus de filter-branch (bonne réponse)
  • filter-branch ne réécrit pas l'historique
  • filter-repo réécrit uniquement les remotes, pas les commits
Explication : git filter-branch est notoirement lent et truffé de pièges (gestion incorrecte des refs, performances catastrophiques sur gros dépôts) ; la documentation Git le déconseille explicitement. git filter-repo, outil externe en Python, est bien plus rapide, sûr et expressif pour purger des fichiers sensibles ou découper un dépôt. Les deux réécrivent l'historique et changent donc tous les SHA.
filter-repo remplace officiellement filter-branch.

  • Un objet corrompu impossible à lire
  • Un objet inaccessible depuis toute ref ou tout reflog, candidat à la suppression par gc (bonne réponse)
  • Un objet appartenant à un sous-module non initialisé
  • Un objet stocké uniquement sur le remote
Explication : Un objet dangling n'est référencé par aucune branche, tag ni reflog. git fsck --lost-found les liste. Ils proviennent souvent de commits abandonnés (rebase, reset, amend). git gc les purge lorsqu'ils dépassent la durée de rétention (gc.pruneExpire, 2 semaines par défaut pour les objets non joignables). Avant gc, ils restent récupérables.
fsck --lost-found révèle les objets orphelins.

  • Compresser les objets en packfiles
  • Vérifier l'intégrité et la connectivité de la base d'objets (bonne réponse)
  • Supprimer les branches fusionnées
  • Synchroniser les refs avec le remote
Explication : git fsck (file system check) parcourt la base d'objets pour vérifier leur intégrité : sommes de contrôle, validité des liens entre commits, trees et blobs. Il signale les objets corrompus, manquants (missing) ou orphelins (dangling). C'est l'outil de diagnostic de référence et un point d'entrée pour récupérer du travail perdu via --lost-found.
fsck audite la santé de la base d'objets.

  • Elle exclut le commit sélectionné du résultat
  • Elle ajoute au message une ligne indiquant le SHA du commit d'origine (bonne réponse)
  • Elle applique le commit sans créer de nouveau commit
  • Elle inverse le commit comme un revert
Explication : Avec git cherry-pick -x <sha>, Git ajoute au message du nouveau commit une ligne (cherry picked from commit <sha>). Cela documente la traçabilité entre les deux commits, ce qui est précieux lorsqu'on porte un correctif d'une branche à une autre (backport). Sans -x, le lien d'origine n'est pas conservé dans le message.
-x trace l'origine du cherry-pick dans le message.

  • git cherry-pick A..B (bonne réponse)
  • git cherry-pick A--B
  • git cherry-pick A:B
  • git cherry-pick --range A B
Explication : La notation git cherry-pick A..B applique tous les commits accessibles depuis B mais pas depuis A : A est donc exclu, B inclus. Pour inclure aussi A, on utilise A^..B. C'est la même logique de plage que git log A..B. Cela permet de rejouer plusieurs correctifs consécutifs sur une autre branche en une seule commande.
A..B exclut A, inclut B (comme git log).

  • Elle fusionne feature dans main en 3 commits
  • Elle rejoue les commits de feature postérieurs à feature~3 sur le sommet de main (bonne réponse)
  • Elle supprime les 3 derniers commits de feature
  • Elle déplace main de 3 commits en arrière
Explication : git rebase --onto <nouvelle-base> <ancienne-base> <branche> rejoue les commits compris entre l'ancienne base (exclue) et la branche, par-dessus la nouvelle base. Ici, les commits de feature situés après feature~3 sont transplantés sur main. C'est l'outil idéal pour détacher une branche d'un mauvais point de départ ou extraire une sous-série de commits.
--onto : transplante précisément une tranche de commits.

  • git merge -X ours (bonne réponse)
  • git merge --strategy=octopus
  • git merge -X union
  • git merge --ff-only
Explication : L'option -X ours (option de la stratégie recursive/ort) résout automatiquement les zones en conflit en privilégiant notre version, tout en intégrant normalement les parties non conflictuelles de l'autre branche. À ne pas confondre avec la stratégie -s ours, qui ignore totalement le contenu de l'autre branche et ne garde que le nôtre.
-X ours résout les conflits ; -s ours ignore tout l'autre côté.

  • recursive
  • resolve
  • ort (bonne réponse)
  • octopus
Explication : Depuis Git 2.34, la stratégie de merge par défaut est ort (« Ostensibly Recursive's Twin »), qui remplace l'ancienne recursive. Réécrite en profondeur, ort est plus rapide, plus économe en mémoire, gère mieux les renommages et les conflits répertoire/fichier, et évite d'écrire des fichiers intermédiaires inutiles sur le disque pendant les merges et rebases.
ort = la nouvelle stratégie recursive, plus rapide.

  • force-with-lease est plus rapide sur les gros dépôts
  • force-with-lease échoue si le remote a reçu des commits que l'on n'a pas vus (bonne réponse)
  • force-with-lease ne réécrit jamais l'historique
  • force-with-lease ignore les hooks de pré-push
Explication : --force écrase la branche distante sans condition, au risque de détruire le travail d'un collègue poussé entre-temps. --force-with-lease vérifie d'abord que la ref distante correspond toujours à la valeur qu'on a localement connue ; si quelqu'un a poussé entre-temps, le push est refusé. C'est un garde-fou indispensable pour réécrire l'historique en équipe.
--force-with-lease : un push forcé qui protège des écrasements.

  • À remplacer le contenu d'un fichier dans le working directory
  • À substituer un objet par un autre lors de la lecture, sans réécrire l'historique (bonne réponse)
  • À échanger deux branches de nom
  • À remplacer le remote origin par un autre
Explication : git replace <objet> <remplacement> crée une ref dans refs/replace/ indiquant à Git de substituer transparemment un objet par un autre à la lecture. L'historique réel reste intact. C'est utile pour « greffer » deux historiques distincts ou tester une correction sans réécrire les SHA. Les remplacements ne sont pas propagés par défaut lors d'un push.
git replace : substitution virtuelle, sans réécriture.

  • Elles modifient le SHA du commit annoté
  • Elles sont stockées séparément et n'altèrent pas le commit ni son empreinte (bonne réponse)
  • Elles remplacent le message du commit
  • Elles ne peuvent annoter que des tags
Explication : git notes attache des métadonnées à un commit sans changer son SHA : les notes vivent dans une ref dédiée (refs/notes/commits). On peut ainsi ajouter a posteriori des informations (résultat de CI, revue, ticket) sans réécrire l'historique. Les notes ne sont pas poussées/tirées par défaut et nécessitent un refspec explicite.
git notes : métadonnées sans toucher au SHA.

  • Ils accélèrent les opérations de fetch
  • Ils prouvent cryptographiquement l'identité de l'auteur et l'intégrité du commit (bonne réponse)
  • Ils compressent le contenu du commit
  • Ils empêchent tout rebase ultérieur
Explication : La signature (git commit -S ou la signature SSH via gpg.format=ssh) ajoute une preuve cryptographique que le commit a bien été créé par le détenteur de la clé et n'a pas été altéré. Les plateformes affichent alors un badge « Verified ». C'est une mesure clé contre l'usurpation d'identité d'auteur, triviale autrement puisque user.email est librement configurable.
Signer un commit prouve « qui » et garantit l'intégrité.

  • Ne matérialiser dans le working directory qu'un sous-ensemble des fichiers du dépôt (bonne réponse)
  • Cloner uniquement les commits récents sans les anciens
  • Supprimer les fichiers volumineux de l'historique
  • Diviser un dépôt en plusieurs remotes
Explication : git sparse-checkout permet de ne matérialiser dans le répertoire de travail qu'un sous-ensemble de chemins, tout en conservant l'historique complet. Très utile sur les monorepos : un développeur ne checkout que le dossier de son équipe. Combiné au mode cone et à un partial clone, on peut même éviter de télécharger les blobs hors périmètre.
sparse-checkout : un working directory partiel sur un monorepo.

  • Le shallow clone limite la profondeur d'historique, le partial clone diffère le téléchargement de certains objets (bonne réponse)
  • Le shallow clone télécharge tout, le partial clone rien
  • Les deux sont des synonymes
  • Le partial clone supprime les branches distantes
Explication : Un shallow clone (--depth N) tronque l'historique aux N derniers commits : rapide mais limité pour l'archéologie de code et certains merges. Un partial clone (--filter=blob:none) récupère tout le graphe de commits mais diffère le téléchargement des blobs jusqu'à ce qu'ils soient réellement nécessaires. Le partial clone est plus souple pour les très gros dépôts.
shallow tronque l'historique, partial diffère les blobs.

  • Réparer les fichiers corrompus du working directory
  • Planifier et exécuter en arrière-plan des tâches d'optimisation du dépôt (bonne réponse)
  • Mettre à jour la version de Git installée
  • Synchroniser les hooks entre développeurs
Explication : git maintenance orchestre des tâches d'optimisation : mise à jour du commit-graph, prefetch des remotes, repack incrémental, expiration du reflog. git maintenance start les planifie en tâche de fond (cron, systemd, planificateur Windows). C'est l'évolution moderne du git gc automatique, pensée pour garder un gros dépôt performant sans intervention manuelle.
git maintenance : le gc moderne et planifié.

  • Le dépôt local a perdu sa connexion au remote
  • HEAD pointe directement sur un commit plutôt que sur une branche (bonne réponse)
  • La branche courante a été supprimée du remote
  • Le fichier HEAD du dossier .git est corrompu
Explication : En detached HEAD, HEAD référence directement un SHA de commit au lieu de pointer vers une branche. Cela arrive après git checkout <sha> ou un checkout de tag. Tout nouveau commit créé dans cet état n'est rattaché à aucune branche ; si on change de branche sans le sauvegarder, il devient orphelin. On le préserve avec git switch -c <nom>.
Detached HEAD : crée une branche avant de partir.

  • L'impossibilité d'utiliser des branches
  • La dégradation des performances de clone, checkout et statut à mesure que le dépôt grossit (bonne réponse)
  • L'absence totale de gestion des conflits
  • L'interdiction des pull requests
Explication : Dans un monorepo volumineux, le nombre de fichiers et la taille de l'historique dégradent les opérations comme clone, checkout et status. Les parades incluent sparse-checkout, partial clone, le commit-graph, l'index fsmonitor et git maintenance. Des outils comme Scalar (intégré à Git) regroupent ces optimisations pour rendre les très gros monorepos exploitables.
Monorepo : sparse-checkout + partial clone + commit-graph.

  • À définir les permissions des fichiers
  • À configurer par chemin la normalisation des fins de ligne, les filtres et le diff personnalisé (bonne réponse)
  • À lister les fichiers à ignorer
  • À stocker les identifiants des développeurs
Explication : .gitattributes applique des comportements par motif de chemin : normalisation des fins de ligne (text=auto, eol), marquage binaire, filtres clean/smudge (utilisés par Git LFS), pilotes de diff/merge personnalisés, ou export-ignore. Versionné, il garantit un traitement cohérent des fichiers entre tous les contributeurs, indépendamment de leur OS.
.gitattributes pilote le traitement par type de fichier.

  • Il compresse les fichiers binaires dans des packfiles dédiés
  • Il remplace le fichier par un pointeur texte et stocke le contenu sur un serveur LFS (bonne réponse)
  • Il découpe les fichiers en blocs de 64 Ko versionnés séparément
  • Il chiffre les fichiers volumineux avant le commit
Explication : Git LFS (Large File Storage) remplace, via un filtre clean/smudge configuré dans .gitattributes, le contenu du gros fichier par un petit fichier pointeur texte (OID, taille). Le contenu réel est stocké sur un serveur LFS distinct et téléchargé à la demande au checkout. Cela évite de gonfler l'historique Git avec des binaires lourds.
Git LFS : un pointeur dans Git, le binaire ailleurs.

  • La différence ligne à ligne entre deux fichiers
  • Une comparaison entre deux versions d'une même série de commits (bonne réponse)
  • La liste des commits non encore poussés
  • Le diff entre l'index et le working directory
Explication : git range-diff compare deux séries de commits entre elles, par exemple l'ancienne et la nouvelle version d'une branche après un rebase ou un amend. Il apparie les commits correspondants et montre comment chacun a évolué. C'est l'outil idéal pour réviser ce qui a changé entre deux itérations d'une pull request ou d'un patch set.
range-diff : « diff de diffs » entre deux versions d'une branche.

  • Le dernier commit de la branche cible
  • L'ancêtre commun le plus récent des deux branches à fusionner (bonne réponse)
  • Le premier commit du dépôt
  • Le commit créé à l'issue du merge
Explication : La merge base est l'ancêtre commun le plus récent des deux têtes à fusionner ; on la calcule avec git merge-base. L'algorithme de three-way merge compare chaque côté à cette base : si un seul côté a modifié une zone, la modification est prise ; si les deux l'ont changée différemment, un conflit est signalé. La base évite donc d'inventer de faux conflits.
La merge base est le point de référence du three-way merge.

  • Il est plus rapide à calculer
  • Il distingue ce qui a changé de chaque côté grâce à l'ancêtre commun, réduisant les faux conflits (bonne réponse)
  • Il ne produit jamais de conflit
  • Il fusionne automatiquement les fichiers binaires
Explication : Une simple comparaison à deux versions ne peut pas savoir qui a modifié une ligne : toute divergence semble conflictuelle. Le three-way merge introduit une troisième référence, la merge base, ce qui permet de distinguer « modifié d'un seul côté » (intégrable automatiquement) de « modifié des deux côtés » (vrai conflit). Cela réduit drastiquement les faux positifs.
La base commune transforme un faux conflit en intégration auto.

  • Il chiffre l'historique des commits
  • Il accélère le parcours du graphe de commits (log, merge-base, ancêtres) (bonne réponse)
  • Il remplace les packfiles d'objets
  • Il synchronise automatiquement les remotes
Explication : Le commit-graph (.git/objects/info/commit-graph) est un fichier d'index pré-calculé stockant métadonnées et relations de parenté des commits, avec un système de generation numbers. Il évite de désérialiser chaque objet commit lors des parcours du graphe, accélérant fortement git log, git merge-base et les calculs d'accessibilité sur les gros dépôts. git commit-graph write ou git maintenance le génère.
commit-graph : index pré-calculé du graphe de commits.

  • Une convention de nommage des branches
  • Une structure normalisée des messages de commit avec un type, un scope optionnel et une description (bonne réponse)
  • Un format de fichier .gitignore
  • Un protocole de transfert entre dépôts
Explication : Conventional Commits standardise le message sous la forme type(scope): description, avec des types comme feat, fix, chore, docs. Un ! ou un pied de message BREAKING CHANGE: signale une rupture. Cette structure permet de générer automatiquement le changelog et de déduire le bump de version SemVer.
feat/fix/chore : la grammaire des Conventional Commits.

  • fix
  • feat (bonne réponse)
  • docs
  • chore
Explication : Dans l'usage standard reliant Conventional Commits et SemVer (MAJEUR.MINEUR.CORRECTIF) : un fix incrémente le correctif, un feat incrémente la version mineure (nouvelle fonctionnalité rétrocompatible), et un BREAKING CHANGE incrémente la version majeure. Les types docs ou chore n'entraînent en général aucun bump de version publiée.
fix → patch, feat → minor, BREAKING → major.

  • Le tag léger ne peut pointer que sur un blob
  • Le tag annoté est un véritable objet Git avec auteur, date et message, le tag léger est un simple pointeur (bonne réponse)
  • Le tag léger est signé, le tag annoté ne l'est jamais
  • Le tag annoté n'est jamais poussé sur le remote
Explication : Un tag léger est juste une ref nommée pointant sur un commit, sans métadonnées. Un tag annoté (git tag -a) crée un véritable objet tag dans la base, contenant le tagueur, la date, un message et, éventuellement, une signature GPG/SSH. Pour des versions officielles, on utilise toujours des tags annotés, traçables et vérifiables.
Releases officielles : toujours un tag annoté.

  • reword
  • edit (bonne réponse)
  • fixup
  • pick
Explication : L'action edit (ou e) interrompt le rebase juste après avoir appliqué le commit concerné. On peut alors modifier les fichiers, scinder le commit, ajouter ou retirer des changements, puis git commit --amend et git rebase --continue. reword ne change que le message ; edit autorise une modification complète du contenu.
edit met le rebase en pause pour retoucher le commit.

  • Le dépôt reste détaché sur un commit intermédiaire au lieu de revenir à la branche d'origine (bonne réponse)
  • Le prochain commit sera automatiquement marqué bad
  • Toutes les branches sont supprimées
  • Git refuse toute commande tant que bisect n'est pas relancé
Explication : Pendant une session git bisect, Git checkout des commits intermédiaires en detached HEAD. Si on oublie git bisect reset, le dépôt reste sur le dernier commit testé au lieu de revenir à la branche initiale, et l'état de bisect persiste. git bisect reset nettoie cet état et restaure HEAD sur la branche de départ.
Termine toujours un bisect par git bisect reset.

  • Des copies compressées des objets blob
  • Des pointeurs nommés vers des SHA, stockés sous .git/refs ou dans packed-refs (bonne réponse)
  • Des fichiers de configuration des remotes
  • Des sauvegardes automatiques du working directory
Explication : Une ref est un nom lisible pointant vers un SHA : branches (refs/heads/), tags (refs/tags/), branches distantes (refs/remotes/). Elles existent comme petits fichiers sous .git/refs/ ou regroupées dans .git/packed-refs. HEAD est une ref symbolique pointant en général vers une branche. Manipuler une ref ne déplace qu'un pointeur, pas les objets.
Une branche est juste une ref : un pointeur vers un SHA.

  • recursive
  • resolve
  • octopus (bonne réponse)
  • ours
Explication : La stratégie octopus est automatiquement sélectionnée par git merge lorsqu'on fusionne trois branches ou plus simultanément, produisant un commit à plusieurs parents. Elle refuse cependant de continuer si des conflits nécessitent une résolution manuelle. Elle sert surtout à regrouper des branches thématiques indépendantes sans conflit, par exemple dans certaines branches d'intégration.
octopus : merge de 3+ branches sans conflit.

  • Il réordonne et marque automatiquement les commits fixup pour fusion avec leur cible (bonne réponse)
  • Il supprime tous les commits fixup de l'historique
  • Il transforme chaque commit en tag annoté
  • Il pousse automatiquement la branche après le rebase
Explication : git commit --fixup=<sha> crée un commit dont le message commence par fixup! . Lors d'un git rebase -i --autosquash, Git repositionne automatiquement ce commit juste après sa cible et lui affecte l'action fixup. Le développeur n'a plus qu'à valider la todo-list. C'est le workflow recommandé pour corriger proprement un commit déjà revu sans réécrire manuellement la liste.
--fixup + --autosquash = nettoyage d'historique automatisé.

  • git clean -fd
  • git prune (bonne réponse)
  • git checkout --orphan
  • git reset --keep
Explication : git prune supprime de la base les objets inaccessibles (non joignables depuis une ref ou un reflog) dont la date dépasse le seuil d'expiration. C'est une opération bas niveau habituellement déclenchée par git gc, qui combine repack, expiration de reflog et prune. git clean, à ne pas confondre, supprime des fichiers non suivis du working directory, pas des objets.
git prune nettoie les objets ; git clean les fichiers non suivis.

  • Elles interdisent les pull requests
  • Elles matérialisent l'état déployé de chaque environnement, le code y étant promu progressivement (bonne réponse)
  • Elles remplacent totalement la branche main
  • Elles servent uniquement à stocker la documentation
Explication : Le GitLab Flow enrichit le modèle simple de GitHub Flow avec des branches d'environnement (staging, pre-production, production). Le code « descend » de main vers ces branches au fur et à mesure de sa promotion. Chaque branche reflète exactement ce qui est déployé sur l'environnement correspondant, ce qui clarifie la traçabilité des déploiements.
GitLab Flow : une branche = un environnement déployé.

  • Elle annule le merge en cas de conflit
  • Elle force la création d'un commit de merge même si un fast-forward serait possible (bonne réponse)
  • Elle interdit la fusion de branches divergentes
  • Elle effectue le merge sans vérifier l'historique
Explication : Par défaut, si la branche cible n'a pas divergé, Git effectue un fast-forward : il avance simplement le pointeur, sans commit de merge. --no-ff force la création d'un commit de merge explicite, ce qui préserve dans l'historique la trace qu'une branche de fonctionnalité a existé. C'est une convention fréquente pour rendre l'historique lisible par fonctionnalité.
--no-ff garde une trace visible de la branche fusionnée.

  • pre-push (bonne réponse)
  • pre-commit
  • post-checkout
  • pre-receive
Explication : Le hook client pre-push s'exécute après que les commits sont prêts mais avant tout transfert réseau. Il reçoit sur stdin les refs et SHA concernés. Renvoyer un code non nul annule le push. On l'emploie typiquement pour lancer la suite de tests ou refuser de pousser sur une branche protégée. pre-receive, lui, s'exécute côté serveur.
pre-push : dernier rempart côté client avant l'envoi.

  • Tous les SHA des commits affectés changent, imposant une réécriture pour toute l'équipe (bonne réponse)
  • Le fichier reste récupérable indéfiniment via git checkout
  • Le remote se met à jour automatiquement sans push
  • Les branches locales sont supprimées définitivement
Explication : Réécrire l'historique avec git filter-repo recalcule le contenu des commits : tous les SHA à partir du premier commit modifié changent. Il faut donc un push --force et tous les collaborateurs doivent re-cloner ou réaligner leurs branches. De plus, le fichier sensible peut subsister dans des forks, des caches de plateforme ou le reflog : sa rotation (mot de passe, clé) reste indispensable.
Réécrire l'historique change tous les SHA : coordonne l'équipe.

  • Il stocke la configuration des remotes
  • Il représente la staging area : l'instantané préparé pour le prochain commit (bonne réponse)
  • Il contient la liste des branches distantes
  • Il journalise tous les déplacements de HEAD
Explication : Le fichier .git/index matérialise la staging area (ou cache) : c'est un instantané structuré du contenu qui constituera le prochain commit. git add y inscrit les fichiers, git commit en construit un objet tree. L'index agit comme zone tampon entre le working directory et l'historique, et permet aussi de gérer les états de conflit pendant un merge.
.git/index = la staging area de Git.

  • Pour accélérer la compilation du projet
  • Pour garantir des messages normalisés permettant la génération automatique du changelog et du versioning (bonne réponse)
  • Pour chiffrer les commits avant déploiement
  • Pour interdire l'usage des branches de fonctionnalité
Explication : Valider les Conventional Commits dans la CI (en plus du hook commit-msg local) garantit que chaque message respecte la convention, même si un développeur a contourné les hooks. Cette rigueur est la condition d'un pipeline de release automatisé : des outils comme semantic-release analysent les feat/fix/BREAKING CHANGE pour calculer la version SemVer, générer le changelog et publier le tag.
CI + Conventional Commits = versioning et changelog automatiques.