git reset déplace HEAD et peut mettre à jour l'index et le working
directory selon le mode choisi : --soft (HEAD seul), --mixed
(HEAD + index, par défaut) ou --hard (les trois). Ce guide vous
apprend à choisir le bon mode selon votre situation, à comprendre
les 3 arbres internes de Git, et à éviter toute perte de données lors
d'un reset.
Prérequis : Enregistrer des modifications et Sélection de révisions.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre les 3 arbres de Git : HEAD, index et répertoire de travail
- Maîtriser
--soft,--mixedet--hardet leurs effets respectifs - Distinguer
reset,checkout,restoreetswitch: quand utiliser quoi - Annuler des modifications à différents stades du workflow
Les 3 arbres de Git
Section intitulée « Les 3 arbres de Git »Git manipule en permanence trois « arbres » (structures de données) qui contiennent chacun une version complète de votre projet. HEAD pointe sur le dernier commit de la branche courante, l'index stocke le contenu qui partira au prochain commit, et le working directory contient les fichiers que votre éditeur ouvre. Comprendre lequel des trois une commande touche suffit à prévoir si vous risquez de perdre du travail.
| Arbre | Rôle | Commande pour le voir |
|---|---|---|
| HEAD | Dernier commit (snapshot du repo) | git log --oneline -1 |
| Index (staging area) | Prochain commit en préparation | git diff --cached |
| Working Directory | Fichiers sur le disque | git diff |
Le workflow normal fait circuler les modifications de droite à gauche :
Working Dir → Index → HEAD git add git commitgit reset fait l'inverse : il déplace HEAD et peut propager le
changement vers l'index et/ou le working directory.
Les 3 modes de git reset
Section intitulée « Les 3 modes de git reset »Les trois modes se distinguent par le nombre d'arbres qu'ils
mettent à jour, dans un ordre cumulatif : --soft s'arrête à HEAD,
--mixed va jusqu'à l'index, --hard descend jusqu'aux fichiers du
disque. Sans option, Git applique --mixed. Un seul de ces modes,
--hard, peut détruire du travail que vous n'avez jamais commité.
--soft : déplacer HEAD uniquement
Section intitulée « --soft : déplacer HEAD uniquement »HEAD recule mais rien d'autre ne bouge : le contenu du commit annulé se retrouve intact dans l'index, prêt à être recommité.
git reset --soft HEAD~1- HEAD recule d'un commit
- Index inchangé → les modifications restent stagées
- Working directory inchangé
Usage : « annuler le dernier commit mais garder les modifications prêtes à être recommitées ».
# Regrouper les 3 derniers commits en un seulgit reset --soft HEAD~3git commit -m "feat: fonctionnalité complète"--mixed (défaut) : HEAD + index
Section intitulée « --mixed (défaut) : HEAD + index »C'est le mode appliqué quand vous n'écrivez aucune option : les
modifications retombent en non stagées, il faudra les repasser par
git add.
git reset HEAD~1 # --mixed est le défautgit reset --mixed HEAD~1 # Identique- HEAD recule d'un commit
- Index mis à jour → les modifications passent en non stagées
- Working directory inchangé
Usage : « annuler le commit et le staging, mais garder les fichiers modifiés ».
# Désélectionner un fichier (sans toucher au working dir)git reset HEAD fichier.py# Équivalent moderne :git restore --staged fichier.py--hard : HEAD + index + working directory
Section intitulée « --hard : HEAD + index + working directory »Ce mode réécrit les fichiers du disque pour les aligner sur le commit visé, sans demander de confirmation ni proposer de sauvegarde.
git reset --hard HEAD~1- HEAD recule d'un commit
- Index vidé
- Working directory écrasé → modifications perdues
Usage : « tout annuler, revenir à l'état exact d'un commit ».
# Revenir exactement à l'état de origin/maingit reset --hard origin/mainRécapitulatif visuel
Section intitulée « Récapitulatif visuel »Ce tableau se lit de gauche à droite : chaque colonne correspond à un arbre, et la dernière annonce le risque réel. Repérez la ligne du mode que vous vous apprêtez à taper, puis la colonne Working Dir. Tant qu'elle affiche « Inchangé », vos fichiers sur le disque sont préservés, quelle que soit la révision ciblée.
| Mode | HEAD | Index | Working Dir | Données perdues ? |
|---|---|---|---|---|
--soft | Déplacé | Inchangé | Inchangé | Non |
--mixed | Déplacé | Mis à jour | Inchangé | Non |
--hard | Déplacé | Mis à jour | Mis à jour | Oui (non commitées) |
reset sur un fichier
Section intitulée « reset sur un fichier »Quand vous spécifiez un chemin, reset ne déplace pas HEAD. Il met
à jour uniquement l'index pour ce fichier :
# Désélectionner un fichier (retirer du staging)git reset HEAD fichier.py# Identique à :git restore --staged fichier.pyAvec une révision :
# Remettre fichier.py dans l'index à la version de HEAD~3git reset HEAD~3 -- fichier.pyLe working directory n'est pas modifié, seul l'index est mis à jour.
reset vs checkout vs restore vs switch
Section intitulée « reset vs checkout vs restore vs switch »Depuis Git 2.23, switch et restore couvrent les usages qui
étaient auparavant tous concentrés sur checkout. Elles sont plus
explicites parce qu'une commande ne fait plus qu'une chose. Le tableau
donne la correspondance entre l'ancienne écriture et la nouvelle.
| Action | Ancienne syntaxe | Nouvelle syntaxe |
|---|---|---|
| Changer de branche | git checkout branche | git switch branche |
| Désélectionner un fichier | git reset HEAD fichier | git restore --staged fichier |
| Annuler les modifications d'un fichier | git checkout -- fichier | git restore fichier |
| Revenir à un commit (détached HEAD) | git checkout a1b2c3d | git switch --detach a1b2c3d |
git reset reste nécessaire pour déplacer HEAD d'une branche
(soft/mixed/hard). Les autres cas ont des commandes dédiées plus
claires.
reset vs revert
Section intitulée « reset vs revert »Les deux commandes annulent un changement, mais pas au même prix.
reset réécrit l'historique : les commits abandonnés changent de
place et disparaissent de la branche. revert ajoute au contraire un
nouveau commit qui applique l'inverse du commit visé, donc rien
n'est réécrit. Ce critère décide à lui seul dans le cas d'une branche
déjà poussée.
| Critère | git reset | git revert |
|---|---|---|
| Mécanisme | Supprime les commits | Crée un commit d'annulation |
| Historique | Réécrit (SHA changent) | Préserve (ajout d'un commit) |
| Commits partagés | Non, casse l'historique des autres | Oui, sûr pour les branches partagées |
| Granularité | Revient à un point | Annule un commit spécifique |
Règle simple : reset pour les commits locaux non poussés,
revert pour les commits partagés.
Cas pratiques
Section intitulée « Cas pratiques »Voici les cinq situations où git reset sert réellement au quotidien,
de la plus anodine à la plus délicate. Chacune indique le mode à
employer et l'état dans lequel vous retrouvez vos fichiers ensuite.
Toutes supposent une branche locale non poussée, sauf mention
contraire.
Annuler le dernier commit (garder les modifications)
Section intitulée « Annuler le dernier commit (garder les modifications) »Le commit disparaît de l'historique mais son contenu reste stagé, ce qui permet d'en refaire un tout de suite avec un meilleur message.
git reset --soft HEAD~1# Les modifications sont dans le staging, prêtes à être modifiéesDésélectionner tout le staging
Section intitulée « Désélectionner tout le staging »Sans révision ni chemin, git reset vise HEAD et se contente de
vider l'index : aucun commit n'est touché, aucun fichier n'est modifié.
git reset# Toutes les modifications passent de stagé à non stagéRevenir à origin/main après une série d'erreurs
Section intitulée « Revenir à origin/main après une série d'erreurs »Lancez d'abord git fetch : origin/main est une référence locale
qui peut dater, et le reset s'alignera sur cette copie, pas sur l'état
réel du serveur. L'opération est destructive pour tout travail non
commité.
git reset --hard origin/main# Working directory identique à origin/mainSéparer un gros commit en plusieurs
Section intitulée « Séparer un gros commit en plusieurs »--mixed remet les fichiers en non stagés, ce qui vous laisse les
rajouter un par un avec git add pour reconstituer plusieurs commits.
git reset --mixed HEAD~1# Les modifications sont dans le working dirgit add partie-1.pygit commit -m "feat: partie 1"git add partie-2.pygit commit -m "feat: partie 2"Récupérer après un reset --hard accidentel
Section intitulée « Récupérer après un reset --hard accidentel »Le reflog enregistre chaque position prise par HEAD, y compris celles qu'aucune branche ne référence plus ; les commits perdus y restent atteignables tant que le garbage collector ne les a pas supprimés. En revanche il ne consigne que des commits : le travail qui n'avait jamais été commité reste irrécupérable par cette voie.
# Le reflog conserve la position précédentegit reflog# a1b2c3d HEAD@{1}: reset: moving to origin/main# e4f5a6b HEAD@{2}: commit: ma feature importante
git reset --hard HEAD@{2}# Restauré !Dépannage
Section intitulée « Dépannage »Quatre situations reviennent systématiquement après un reset mal
ciblé. Partez du symptôme que vous observez dans git status, la
colonne du milieu donne la manipulation qui l'a provoqué. La dernière
ligne du tableau décrit un comportement normal, pas un incident.
| Symptôme | Cause probable | Solution |
|---|---|---|
Fichiers perdus après --hard | Reset destructif | git reflog + git reset --hard HEAD@{n} |
reset n'a pas désélectionné | Omission du chemin | git reset HEAD fichier.py (avec le chemin) |
| Collaborateurs cassés après reset | Commits partagés réécrits | Utilisez revert pour les commits partagés |
| Index ne correspond pas au working dir | --mixed appliqué | Normal : --mixed vide l'index, pas le working dir |
À retenir
Section intitulée « À retenir »- Git a 3 arbres : HEAD, Index (staging), Working Directory
--soft: déplace HEAD → modifications restent stagées--mixed(défaut) : déplace HEAD + vide l'index → modifications non stagées--hard: tout réinitialise → destructif pour les fichiers non commitéesresetsur un fichier = mettre à jour l'index (pas HEAD)resetpour commits locaux,revertpour commits partagés- Le reflog sauve toujours, même après un
--hardaccidentel
FAQ : git reset
Section intitulée « FAQ : git reset »Les questions ci-dessous portent sur les confusions les plus
fréquentes entre les trois modes, la récupération après un
--hard et le cas des branches déjà partagées.
| Mode | HEAD | Index | Working dir |
|---|---|---|---|
--soft |
déplacé | conservé | conservé |
--mixed (défaut) |
déplacé | réinitialisé | conservé |
--hard |
déplacé | réinitialisé | écrasé |
--soft garde tout prêt à recommitter, --mixed désindexe mais garde vos fichiers, --hard efface les modifications non committées. Seul --hard est destructif.git reset --soft HEAD~1 # annule le commit, garde tout indexé
git reset HEAD~1 # annule le commit, désindexe (mode mixed par défaut)
Le --soft est idéal pour corriger un commit trop rapide : vos modifications restent stagées, vous ajustez et recommittez. N'utilisez jamais --hard HEAD~1 ici : il effacerait définitivement les modifications du commit annulé.git reset |
git revert |
|
|---|---|---|
| Effet | Recule HEAD, réécrit l'historique |
Nouveau commit inverse |
| Historique | Modifié | Préservé |
| Usage | Commits locaux non poussés | Commits déjà partagés |
reset tant que le commit est local, revert dès qu'il a été poussé. Revert est sans danger en équipe car il n'altère rien de ce qui existe déjà.git add) sans perdre vos modifications :git restore --staged fichier.js # forme moderne (Git 2.23+)
git reset HEAD fichier.js # forme classique équivalente
Le fichier repasse en modifié non indexé : son contenu est intact, il n'est simplement plus dans le prochain commit. C'est l'opération inverse de git add.git reset --hard écrase sans confirmation les modifications non committées du working directory et de l'index.Deux garde-fous :- Avant : lancez
git statuspour voir ce que vous allez perdre, etgit stashsi vous voulez conserver le travail en cours ; - Après une erreur : les commits annulés restent récupérables un temps via
git reflogpuisgit reset --hard HEAD@{n}. En revanche, les modifications jamais committées sont perdues définitivement.
checkout en 2019 (version 2.23) :| Besoin | Commande moderne | Ancienne forme |
|---|---|---|
| Changer de branche | git switch |
git checkout <branche> |
| Annuler une modif de fichier | git restore |
git checkout -- <fichier> |
| Désindexer | git restore --staged |
git reset HEAD <fichier> |
| Déplacer HEAD / historique | git reset |
git reset |
reset reste l'outil de l'historique et de l'index, tandis que restore et switch couvrent les fichiers et les branches de façon moins ambiguë.