git reset
Réinitialiser le HEAD courant à l’état indiqué
La commande 'git reset' sert à annuler des modifications en déplaçant le HEAD de la branche courante vers un commit donné. Elle a trois modes principaux : --soft (garde les modifications indexées), --mixed (par défaut - garde les modifications dans le répertoire de travail) et --hard (jette toutes les modifications). Cette commande est essentielle pour annuler des commits, désindexer des fichiers et gérer votre historique. Attention avec 'git reset --hard', qui jette définitivement les modifications.
Synopsis
git reset [-q] [<tree-ish>] [--] <pathspec>...
git reset [-q] [--pathspec-from-file=<file>] [<tree-ish>]
git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>...]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]Options
Choisir la bonne option
Modes de reset : qu’est-ce qui est conservé ?
Comprendre les trois modes principaux de reset et ce qu’il advient de vos modifications
| Commande | HEAD se déplace | Zone de préparation | Répertoire de travail | À utiliser quand |
|---|---|---|---|---|
--soft | Oui | Conservé (indexé) | Conservé | Annuler un commit pour le refaire avec des modifications |
--mixed (default) | Oui | Vidé (désindexé) | Conservé | Annuler un commit pour retoucher avant d’indexer |
--hard | Oui | Vidé | Modifications suivies PERDUES (non suivies gardées) | Jeter complètement le commit et toutes les modifications |
Reset, revert ou checkout
Choisir la bonne commande d’annulation selon la situation
| Commande | Modifie l’historique ? | Sans danger pour les commits poussés ? | Idéal pour |
|---|---|---|---|
git reset | Oui (déplace la branche) | Non - pose problème | Annuler des commits locaux pas encore poussés |
git revert | Non (ajoute un nouveau commit) | Oui - sans danger pour les branches partagées | Annuler des commits poussés sur des branches partagées |
git checkout -- file | No | Oui | Jeter les modifications non committées de fichiers précis |
Désindexer des modifications : reset ou restore
Le Git moderne propose git restore comme alternative à reset pour désindexer
| Commande | But | Touche les commits ? | Recommandé |
|---|---|---|---|
git reset HEAD file | Désindexer un fichier | No | Façon traditionnelle |
git restore --staged file | Désindexer un fichier | No | Façon moderne (Git 2.23+) |
git reset | Désindexer tous les fichiers | No | Fonctionne bien |
git restore --staged . | Désindexer tous les fichiers | No | Intention plus explicite |
Modes de reset avancés
Quand utiliser --merge et --keep plutôt que --hard
| Commande | Garde les modifications locales ? | S’interrompt en cas de conflit ? | Cas d’usage |
|---|---|---|---|
--hard | Non - détruit tout | No | Reset complet, les modifications n’importent pas |
--merge | Modifications non indexées seulement (les indexées sont perdues) | Oui | Abandonner une fusion en gardant le travail sans rapport |
--keep | Oui (dans les fichiers que le reset ne touche pas) | Oui | Annuler un commit mais garder les modifications locales sans rapport |
Exemples
Annuler le dernier commit, garder les modifications indexées
git reset --soft HEAD~1Recule HEAD d’un commit. Les modifications de ce commit restent indexées, prêtes à être committées de nouveau.
Annuler le dernier commit, garder les modifications dans le répertoire de travail
git reset HEAD~1Mode par défaut (--mixed). Recule HEAD d’un commit. Les modifications sont conservées mais désindexées.
Jeter complètement le dernier commit et les modifications
git reset --hard HEAD~1Recule HEAD d’un commit et jette TOUTES les modifications non committées des fichiers suivis. Avec prudence - le travail non committé perdu est irrécupérable (le commit lui-même reste dans git reflog).
Désindexer un fichier précis
git reset HEAD file.jsRetire file.js de la zone de préparation sans jeter les modifications. Le fichier reste modifié dans le répertoire de travail.
Exemples de workflows
git log --oneline -3Voir les commits récents pour confirmer lequel annuler
git reset --soft HEAD~1Annuler le commit, garder les modifications indexées
git statusVérifier que les modifications sont indexées
git commit -m "Better message"Committer de nouveau avec un nouveau message
git statusVoir ce qui est actuellement indexé
git reset HEAD unwanted-file.jsDésindexer un ou plusieurs fichiers
git statusVérifier que le fichier n’est plus indexé
git commitCommitter seulement les fichiers voulus
git statusRelire ce qui va être perdu
git stash(Facultatif) Mettre les modifications de côté au cas où
git reset --hard HEAD~1Jeter le dernier commit ET toutes les modifications suivies (les fichiers non suivis restent)
git statusVérifier que le répertoire de travail est propre
git reflogRetrouver le hash du commit d’avant le reset
git reset --hard abc1234Revenir sur ce hash de commit
git log --onelineVérifier que les commits sont restaurés
Dépannage
fatal: ambiguous argument 'HEAD~1': unknown revision
Cause : Vous êtes sur le commit initial - il n’y a pas de commit précédent sur lequel revenir
Vérifiez git log. S’il n’y a qu’un seul commit, vous ne pouvez pas reculer davantage. Utilisez git update-ref -d HEAD pour tout recommencer.
error: Entry 'app.js' not uptodate. Cannot merge.
Cause : Un fichier que --merge ou --keep devrait modifier a des modifications locales non committées, donc le reset est abandonné
Committez ou mettez de côté vos modifications d’abord, ou utilisez --hard si vous voulez les jeter
--hard utilisé par erreur, modifications perdues
Cause : Le reset hard jette définitivement tout le travail non committé
Si les modifications avaient été committées : git reflog pour retrouver le commit, puis git reset --hard <hash>. Si elles n’ont jamais été committées : elles sont sans doute perdues pour toujours.
Le reset a marché mais un collègue dit que l’historique est cassé
Cause : Vous avez réinitialisé des commits déjà poussés sur une branche partagée
Pour les branches partagées, utilisez plutôt git revert. Pour réparer : git reflog, retrouvez le commit d’origine, faites un reset dessus, puis un force push (en vous coordonnant avec l’équipe).
fatal: ambiguous argument 'HEAD' en lançant git reset HEAD file
Cause : Le dépôt n’a encore aucun commit, donc HEAD n’existe pas (ou le chemin est faux)
Retirez HEAD : git reset file.js (ou git rm --cached file.js). Vérifiez le chemin exact avec git status.
Astuces et pièges
Bonnes pratiques
- ✓N’utilisez jamais git reset sur des commits poussés sur des branches partagées - utilisez plutôt git revert
- ✓Lancez toujours git status avant un reset pour comprendre ce qui sera touché
- ✓Préférez --soft quand vous voulez refaire un commit avec des modifications
- ✓Faites git stash avant un reset --hard si vous risquez de vouloir récupérer vos modifications
- ✓Rappelez-vous que git reflog permet de rattraper la plupart des erreurs de reset (pour les modifications committées)
- ✓Utilisez git reset HEAD <file> pour désindexer des fichiers au lieu de réinitialiser des commits entiers
- ✓Pensez à git restore --staged, l’alternative moderne pour désindexer des fichiers
Erreurs fréquentes
- ✗Utiliser 'git reset --hard' sans réaliser qu’il supprime définitivement les modifications non committées. Vérifiez toujours deux fois avant d’utiliser --hard.
- ✗Réinitialiser des commits déjà poussés sur un dépôt distant partagé. Cela réécrit l’historique et pose problème aux collaborateurs. Utilisez plutôt 'git revert'.
- ✗Confondre 'git reset' et 'git revert'. Reset recule le pointeur de branche ; revert crée un nouveau commit qui annule des modifications.
- ✗Ne pas savoir qu’on peut se rattraper d’un mauvais reset avec 'git reflog', pour retrouver le hash du commit précédent.
- ✗Utiliser 'git reset --hard HEAD' pour jeter des modifications de travail alors que 'git checkout -- .' ou 'git restore .' conviendrait mieux.
FAQ
Soft garde les modifications indexées. Mixed (par défaut) les garde dans le répertoire de travail mais désindexées. Hard jette tout. Retenez : soft = annuler le commit seulement, mixed = annuler le commit + désindexer, hard = tout annuler.
Pour les modifications committées : oui, retrouvez le hash du commit d’origine avec git reflog, puis faites un reset dessus. Pour les modifications non committées perdues par --hard : en général non, elles ont définitivement disparu.
HEAD~1 signifie « un commit avant HEAD ». HEAD~2, deux commits en arrière, etc. Vous pouvez aussi utiliser directement des hashes de commit, comme git reset abc1234.
Reset pour les commits locaux pas encore poussés - il réécrit proprement l’historique. Revert pour les commits poussés sur des branches partagées - il crée un nouveau commit qui annule les modifications sans réécrire l’historique.
Utilisez git reset HEAD filename pour désindexer un fichier précis. HEAD ne bouge pas et aucun commit n’est touché : le fichier est simplement retiré de la zone de préparation.
Il supprime définitivement les modifications non committées. Contrairement aux modifications committées (récupérables via le reflog), un travail jamais committé ne peut pas être récupéré après un reset hard.