Git restore porte le coup de grâce à git checkout

Git restore achève git checkout dans une mise en scène dramatique

git checkout a longtemps été la commande tout-en-un de Git. Branches, fichiers, restauration… elle faisait tout, et c’est bien là le problème : trop de fonctions, trop d’ambiguïtés, trop de pièges.

Pour mieux comprendre ce que GitCheckout faisait auparavant côté branches, commence par lire GitSwitch, l’assassin de git checkout.

⚡️ Résumé express

En 2019, les développeurs de Git ont tranché : il fallait séparer les responsabilités.

  • 👉 git switch a repris la gestion des branches.
  • 👉 git restore s’est occupé de la restauration des fichiers.

Résultat: git checkout est relégué au rang de commande héritée, tolérée pour la compatibilité, mais à éviter au quotidien.

📚 Pour ceux qui aiment lire la doc officielle


(Mais si tu veux comprendre ce qu’il se passe vraiment et éviter les pièges du quotidien, continue à lire 👇)

😡 Quand la communauté a craqué

Une foule de développeurs à bout de nerfs après avoir perdu des modifications à cause de git checkout

Si git restore a vu le jour, c’est parce que la communauté avait atteint son point de rupture avec git checkout.

Même après des années, git checkout restait un mystère et les auteurs de Git eux-mêmes l’avouent : leur propre commande était devenue un piège.

"I've been working with Git for years, but my knowledge is limited to very basic workflows"

Développeur sur Stack Overflow
"People are confused by these different ways to use git checkout, as you can see from the many questions regarding git checkout here on Stack Overflow"

Discussion sur Stack Overflow
"git checkout doing too many things is a source of confusion for many users (and it even bites old timers sometimes)"

Commit officiel Git d787d31 par Nguyễn Thái Ngọc Duy, 2 avril 2019
"I've lost plenty of data with git. Most of it has to do with innocuous-sounding commands that don't ask for confirmation when deleting data. For example, git checkout filename is equivalent to{' '} svn revert filename. Of course git checkout branchname does something completely different."

Témoignage sur Stack Overflow
"If a branch and a file share the same name, git will default to switching branches, but that doesn't stop bash autocomplete from ruining the day"

Même développeur, même thread Stack Overflow
"Here's a crazy idea: If you have an innocuous action and a dangerous action, do not label them with the same command"

Réponse sur Stack Overflow
"The ambiguity of the git syntax constantly forces you to reach for a cheat sheet. The commands do not clearly describe their corresponding actions"

Article "The most confusing git terminology"

🩻 L’autopsie de git checkout

Un médecin légiste qui fait l'autopsie de git checkout

Qui peut, sans regarder la documentation ou tester dans son terminal, expliquer la différence entre ces commandes ? Fais le test dans ton équipe, tu verras qu'il y a de fortes chances pour que personne ne sache répondre correctement.

BASH
git checkout HEAD -- . git checkout -- . git checkout HEAD git checkout fichier.txt

💀 Piège 1 - Annuler toutes les modifs (Arbre de travail + index)

BASH
git checkout HEAD -- .

Git prend les fichiers qui sont dans HEAD et vient écraser l'arbre de travail et l'index. Et bien entendu, pas de retour arrière possible 😱.

💀 Piège 2 - Annuler les modifs en cours non indexées

BASH
git checkout -- .

Contrairement à git checkout -- . on ne précise pas ici la source (HEAD). => Dans ce cas de figure git se base sur l'index pour venir mettre à jour l'arbre de travail. Tu trouves ça intuitif ? Moi non plus.

Et bien entendu, toujours pas de retour arrière possible 😱.

💀 Piège 3 - Restaurer un fichier

BASH
git checkout fichier.txt

On ne précise pas la source (HEAD), donc normalement git devrait se baser sur l'index. Oui mais non. Comme on passe un fichier en paramètre, git va se baser sur le HEAD et annuler toutes les modifs du fichier, qu'elles soient indexées ou non.

Mais par contre si tu as eu le malheur d'appeler ta branche fichier.txt (bon ok c'est vraiment peu probable) et bien tu finiras par faire un checkout de ta branche fichier.txt et non pas de restaurer ton fichier fichier.txt.

C'est ça d'avoir une commande qui fait tout : un coup elle change de branche, une autre fois elle crée une branche, et dans d'autres contextes elle reset l'index et/ou le working directory (ta copie de travail). C'est un peu la roulette russe, non ?

💀Piège 4 - Le mode "Detached HEAD" surprise

BASH
git checkout HEAD

Celle là c'est cadeau. On pourrait croire qu'elle ne fait rien, alors qu'en fait elle nous fait passer en mode détaché ! Et oui c'est comme si on avait voulu changer de branche, comme avec un git checkout feature/auth, sauf que la référence que l'on a passé est HEAD, on pointe donc directement sur le commit. N'étant plus sur une branche, il va falloir faire attention à ne pas perdre son travail au prochain changement de branche 😉.

BASH
git checkout HEAD Note: switching to 'HEAD'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c <new-branch-name> Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at 8776833 ✨ feat: Ajoute des diagrammes pour git checkout

📋 Petit tableau récap de git checkout :

CommandeSource → DestinationEffet
git checkout HEAD -- .HEAD → Index + Working treeAnnule toutes les modifs + reset index
git checkout -- .Index → Working treeAnnule modifs non validées (sans toucher à l’index)
git checkout HEADPasse en mode détaché (HEAD detached)Ne change rien aux fichiers
git checkout fichier.txtHEAD → Index + Working tree (sauf si fichier.txt est une branche)Restaure un fichier… sauf si c’est une branche !

🌈 Git restore : l'alternative claire à git checkout

Un paysage féérique qui illustre la naissance de git restore

En 2019, Git 2.23 introduit une alternative claire :
👉 git switch pour les branches
👉 git restore pour annuler les modifs sur les fichiers

📝 Une syntaxe explicite

On est d'accord, le problème de git checkout n'est pas que la commande ne fonctionne pas, mais plutôt que la commande fait trop de choses et ses options ne sont pas claires :

  • est-on en train de faire un changement de branche ?
  • ou un reset complet ?
  • ou une annulation de modifs ?
  • etc.

Pour répondre à cela les équipes Git se sont calées sur le principe de responsabilité unique (Single Responsibility Principle, SRP) et c'est tant mieux ! Ainsi en 2019 ils introduisent git restore et simplifient le process avec 2 options :

  • --worktree → pour mettre à jour l'arbre de travail
  • --staged → pour mettre à jour l'index

Une dernière option quant à elle permet de choisir un commit d'origine autre que HEAD :

  • --source → pour utiliser un commit différent de celui sur lequel on est.

🌲 L'option --worktree

BASH
git restore --worktree <fichier>

Enfin une option claire pour annuler les modifs en cours dans l'arbre de travail.

Petit rappel : les modifs en cours sont celles qui n'ont pas encore été indexées (à ne pas confondre avec l'ensemble des modifs = modifs dans la copie de travail + modifs dans l'index).

Pour cette raison, en interne Git va logiquement se reposer sur l'index pour venir écraser les fichiers dans l'arbre de travail.

Comme c'est le besoin le plus fréquent, les équipes Git en ont fait l'option par défaut. Donc si tu n'utilises pas d'autres options, ces 2 commandes sont équivalentes :

BASH
git restore --worktree <fichier> git restore <fichier> # --worktree par défaut

📦 L'option --staged

BASH
git restore --staged <fichier>

Comme son nom l'indique, on cherche ici à supprimer les modifs que l'on avait enregistrées dans l'index via git add. Pour réinitialiser l'index, git va l'écraser avec le contenu de HEAD.

Cette commande n'est absolument pas dangereuse car les modifications en cours restent présentes dans la copie de travail (working directory).

Dit autrement, cette commande permet d'annuler tous les git add effectués depuis le dernier commit tout en laissant les modifs en cours dans la copie de travail.

🔀 Et si on cumulait les deux options : --worktree --staged

BASH
git restore --worktree --staged <fichier>

Comme prévu, Git va enchaîner les 2 options :


  • 1ère étape : restauration de l'index (--> --staged)
  • 2ème étape : restauration de l'arbre de travail (--> --worktree)

🔥 A la fin des 2 étapes, on a un alignement parfait entre l'arbre de travail, l'index et HEAD.

🎯 L'option --source

BASH
git restore --source=<commit> <fichier>

Cette option est différente des 2 autres options, car comme son nom l'indique elle ne sert pas à indiquer la zone cible mais le point de départ.

Par défaut, et c'est le cas dans 99% des cas, on voudra partir de HEAD.

Mais dans certains cas, il peut être utile de récupérer les informations à partir d'un commit spécifique, et c'est ce que permet l'option --source.

Récupérer un fichier d’une autre branche sans changer de branche

Tu es sur main mais tu veux récupérer uniquement la version de docker-compose.yml de feature-x :

BASH
git restore --source=feature-x docker-compose.yml

👉 Tu n’as pas besoin de faire git switch feature-x puis de copier-coller le fichier. C’est un vrai gain de temps.

Revenir à l’état d’un fichier avant un bug

Un bug est apparu après le commit abc123. Tu veux tester rapidement si la version précédente de app.js corrige le problème :

BASH
git restore --source=abc123 app.js

👉 Tu isoles le bug sans reset/checkout de tout le repo.

Travailler avec une version “propre” d’un seul fichier

Tu as commencé à modifier config.json, mais tu veux repartir de la version qui existait au tag v1.0.0 :

BASH
git restore --source=v1.0.0 config.json

👉 Tu gardes ton repo à jour, mais avec ce fichier dans une version plus ancienne.

Cherry-pick manuel de fichiers

Tu sais qu’un collègue a fait une modif utile dans un commit précis, mais tu veux seulement son fichier README.md, pas tout le commit :

BASH
git restore --source=commit_sha README.md

👉 Tu évites un cherry-pick complet et tu prends uniquement le fichier qui t’intéresse.

Construire un patch partiel

Avant un refactoring, tu veux avoir à disposition deux versions d’un même fichier (HEAD et une version ancienne) pour les comparer. Avec --source, tu remets l’ancienne version directement dans ton WD pour faire un diff local.

BASH
git restore --source=v1.0.0 config.json

✅ En résumé :

  • --source est rare au quotidien.
  • Il devient vraiment utile quand tu veux restaurer un fichier précis d’une autre référence (branche, commit, tag) sans toucher le reste du repo.

📋 Tableau récap de git restore

OptionSource → DestinationEffet
git restore . est la même chose que git restore --worktree .Index → Working treeRestaure tous les fichiers depuis l'index vers l'arbre de travail. Cela a pour effet d'annuler les modifications en cours non indexées
git restore --staged .HEAD → IndexRestaure tous les fichiers depuis HEAD vers l'index (unstage). Cela revient à supprimer tous les git add effectués depuis le dernier commit
git restore --staged --worktree .HEAD → Index → Working treeSupprime tous les changements, que ce soit dans l'index ou dans l'arbre de travail
git restore --source=HEAD~2 .HEAD~2 → Working treeRécupération de la version d'un fichier d'une autre référence (branche, commit, tag)

⏳ Avant 2019 vs Maintenant

ActionAvant 2019 (checkout)Maintenant (restore)Gain
Annuler modifs working treegit checkout -- filegit restore <fichier>✅ Explicite
Unstager un fichier🚨 pas possible avec git checkout. Il faut passer par reset pour avoir l'équivalent : git reset HEAD filegit restore --staged <fichier>✅ Logique
Reset complet (WD + Index)git checkout HEAD -- filegit restore --staged --worktree <fichier>✅ Clair
Depuis un commitgit checkout abc123 -- filegit restore --source=abc123 <fichier>✅ Source explicite

⚰️ Git checkout est-il vraiment mort ?

Les frères git restore et git switch regardent vers le futur

Git restore n’est pas juste une nouvelle commande. C’est l’exécuteur qui a achevé ce que git switch avait commencé.

En revanche, non, il n'est pas mort. Il survit pour la rétrocompatibilité. Mais soyons clairs : c’est une relique.

  • git switch → branches
  • git restore → fichiers
  • git checkout → héritage à éviter

👉 1 job = 1 commande, c'est le principe de responsabilité unique (Single Responsibility Principle, SRP).

L’enquête est close. Git checkout peut enfin reposer en paix, pendant que switch et restore veillent sur nos dépôts.

❓ FAQ Express

Quelle différence entre restore et checkout pour les fichiers ?

👉 git restore est explicite et sûr, là où git checkout était ambigu car cette commande faisait trop de choses et ses options sont ambigües.

Git checkout va-t-il disparaître ?

Non. Il reste pour la compatibilité. Mais il est officiellement considéré comme “héritage”.

Depuis quelle version existe git restore ?

👉 Depuis Git 2.23 (août 2019), en même temps que git switch.

Dois-je oublier git checkout ?

Oui, dans ton quotidien. Utilise git switch et git restore à la place.

🚀 Va plus loin : Maîtrise Git en entreprise avec nos formations sur mesure

Formation Maître Git
Olivier Subirana
Tu viens d'explorer un aspect clé de Git, un outil essentiel pour une gestion de version efficace. Mais la véritable maîtrise de Git, celle qui transforme la productivité de tes équipes et sécurise tes projets, va bien au-delà des commandes individuelles.
Olivier Subirana
En tant que fondateur de formationgit.fr et expert en Git, je propose des formations "Maître Git" exclusivement dédiées aux entreprises. Fini les erreurs coûteuses, les conflits de fusion interminables et les incompréhensions au sein de tes équipes. Nos programmes sont conçus pour s'adapter précisément à tes besoins, que tu sois une startup en pleine croissance ou une grande entreprise avec des défis complexes.

Pourquoi choisir la formation "Maître Git" pour ton entreprise ?

  • Expertise certifiée: Bénéficie de l'expérience d'un formateur spécialisé, capable de démystifier Git pour tous les niveaux.
  • Programmes sur mesure: Chaque formation est adaptée à la culture de ton entreprise, à tes outils et à tes workflows spécifiques.
  • Productivité accrue: Des équipes formées à l'excellence Git travaillent plus vite, avec moins d'erreurs et une meilleure collaboration.
  • Sécurité renforcée: Apprends les bonnes pratiques pour protéger ton historique de code et éviter les pièges courants.

Prêt à transformer la gestion de version de ton entreprise ?

Ne laisse plus les complexités de Git freiner tes projets. Investis dans la compétence de tes équipes et assure une collaboration fluide et efficace.

Olivier Subirana
👉 Contacte-moi dès aujourd'hui pour discuter de tes besoins spécifiques et obtenir une proposition personnalisée pour ta formation "Maître Git" en entreprise.
Demande ta formation "Maître Git"