La commande git reset est un outil complexe et polyvalent pour annuler les changements. Elle peut être appelée de trois façons, qui correspondent aux arguments de ligne de commande --soft, --mixed et --hard. Ces trois arguments renvoient chacun aux trois mécanismes de gestion des états internes de Git : l'arborescence des commits (HEAD), l'index de staging et le répertoire de travail.

git reset et les trois arborescences de Git

Pour bien comprendre l'utilisation de git reset, nous devons d'abord comprendre les systèmes de gestion d'états internes de Git. Parfois, ces mécanismes sont appelés les « trois arborescences » de Git. Le terme « arborescences » peut être un abus de langage, car ce ne sont pas strictement des structures de données d'arborescence traditionnelles. Il s'agit cependant de structures de données basées sur des nœuds et des pointeurs que Git utilise pour suivre une chronologie des éditions. La meilleure façon de démontrer ces mécanismes consiste à créer un ensemble de changements dans un dépôt et à le suivre via les trois arborescences. 

Pour commencer, nous allons créer un dépôt à l'aide des commandes suivantes :

$ mkdir git_reset_test
$ cd git_reset_test/
$ git init .
Initialized empty Git repository in /git_reset_test/.git/
$ touch reset_lifecycle_file
$ git add reset_lifecycle_file
$ git commit -m"initial commit"
[master (root-commit) d386d86] initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 reset_lifecycle_file

L'exemple de code ci-dessus crée un dépôt Git avec un seul fichier vide : reset_lifecycle_file. À ce stade, l'exemple de dépôt comporte un seul commit (d386d86) suite à l'ajout du fichier reset_lifecycle_file.

Le répertoire de travail

La première arborescence que nous étudierons est « le répertoire de travail ». Cette arborescence est synchronisée avec le système de fichiers local. Elle est représentative des changements immédiats apportés au contenu des fichiers et des répertoires.


$ echo 'hello git reset' > reset_lifecycle_file
$ git status 
On branch master 
Changes not staged for commit: 
(use "git add ..." to update what will be committed) 
(use "git checkout -- ..." to discard changes in working directory) 
modified: reset_lifecycle_file

Dans notre dépôt de démo, nous modifions le fichier reset_lifecycle_file et y ajoutons du contenu. Appeler git status montre que Git est conscient des changements apportés au fichier. Ces changements font actuellement partie de la première arborescence : « le répertoire de travail ». La commande git status peut être utilisée pour afficher les changements apportés au répertoire de travail. Ils seront affichés en rouge avec un préfixe « modified ».

Index de staging

Vient ensuite l'arborescence « Index de staging ». Cette arborescence procède au suivi des changements du répertoire de travail associés à l'action git add, à stocker dans le commit suivant. Cette arborescence constitue un mécanisme de mise en cache interne complexe. Git tente généralement de masquer à l'utilisateur les détails de mise en œuvre de l'index de staging.

Afin d'afficher l'état de l'index de staging, nous devons utiliser une commande Git moins connue : git ls-files. La commande git ls-files est principalement un utilitaire de débogage permettant de vérifier l'état de l'arborescence de l'index de staging.

git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 reset_lifecycle_file

Dans cet exemple, nous avons exécuté git ls-files avec l'option -s ou --stage. Sans l'option -s, la sortie git ls-files renvoie simplement une liste de noms de fichier et de chemins d'accès qui font actuellement partie de l'index. L'option -s affiche des métadonnées supplémentaires pour les fichiers dans l'index de staging. Ces métadonnées sont les bits de mode de contenu stagé, le nom d'objet et le numéro d'indexation. Nous nous intéressons au nom d'objet, la deuxième valeur (d7d77c1b04b5edd5acfc85de0b592449e5303770). Il s'agit d'une empreinte SHA-1 d'objet Git standard. C'est une empreinte d'un contenu des fichiers. L'historique des commits stocke ses propres empreintes SHA d'objet pour identifier des pointeurs vers les commits et les réfs, et l'index de staging dispose de ses propres empreintes SHA d'objet pour suivre les versions des fichiers dans l'index.

Ensuite, nous allons promouvoir le fichier reset_lifecycle_file modifié dans l'index de staging.


$ git add reset_lifecycle_file 

$ git status 

On branch master Changes to be committed: 

(use "git reset HEAD ..." to unstage) 

modified: reset_lifecycle_file

Dans cet exemple, nous avons appelé git add reset_lifecycle_file qui ajoute le fichier à l'index de staging. Après avoir appelé git status, reset_lifecycle_file s'affiche en vert sous « Changes to be committed ». Il est important de noter que git status n'est pas une vraie représentation de l'index de staging. La sortie de la commande git status affiche les changements entre l'historique des commits et l'index de staging. Examinons le contenu de l'index de staging à ce stade.

$ git ls-files -s
100644 d7d77c1b04b5edd5acfc85de0b592449e5303770 0 reset_lifecycle_file

Nous pouvons voir que l'empreinte SHA d'objet pour reset_lifecycle_file a été mise à jour de e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 en d7d77c1b04b5edd5acfc85de0b592449e5303770.

Historique des commits

L'arborescence finale est l'historique des commits. La commande git commit ajoute des changements à un instantané permanent dans l'historique des commits. Cet instantané contient également l'état de l'index de staging au moment du commit.

$ git commit -am"update content of reset_lifecycle_file"
[master dc67808] update content of reset_lifecycle_file
1 file changed, 1 insertion(+)
$ git status
On branch master
nothing to commit, working tree clean

Dans cet exemple, nous avons créé un commit avec un message "update content of resetlifecyclefile". L'ensemble de changements a été ajouté à l'historique des commits. Appeler git status à ce stade montre qu'il n'y a pas de changements en attente dans les arborescences. L'exécution de git log affichera l'historique des commits. Maintenant que nous avons suivi cet ensemble de changements dans les trois arborescences, nous pouvons commencer à utiliser git reset.

Fonctionnement

Au premier abord, git reset a un comportement semblable à git checkout. Tandis que git checkout agit uniquement sur le pointeur de la réf HEAD, git reset déplace à la fois le pointeur de la réf HEAD et le pointeur de la réf de la branche actuelle. Pour mieux comprendre ce comportement, examinez l'exemple suivant :

Cet exemple illustre une séquence de commits sur la branche principale (master). Les réfs HEAD et de branche principale (master) pointent actuellement vers le commit d. Exécutons et comparons git checkout b et git reset b.

git checkout b

Lorsque vous exécutez git checkout, la réf master pointe toujours vers d. La réf HEAD a été déplacée et pointe désormais vers le commit b. Le dépôt est désormais à l'état « HEAD détaché ».

git reset b

En comparaison, git reset déplace la réf HEAD et les réfs de branche vers le commit spécifié.

En plus de mettre à jour les pointeurs de réf de commit, git reset modifie l'état des trois arborescences. La modification du pointeur de réf est systématique et constitue une mise à jour de la troisième arborescence, celle des commits. Les arguments de ligne de commande --soft, --mixed et --hard indiquent comment modifier les arborescences Index de staging et Répertoire de travail.

Principales options

L'appel par défaut de git reset comprend les arguments implicites --mixed et HEAD. Par conséquent, l'exécution de git reset équivaut à celle de git reset --mixed HEAD. Sous cette forme, HEAD représente le commit spécifié. Au lieu de HEAD, n'importe quelle empreinte SHA-1 de commit Git peut être utilisée.

--hard

Il s'agit de l'option la plus directe. Malgré son usage fréquent, elle présente des DANGERS. Lorsque vous transmettez l'argument --hard, les pointeurs de la réf d'historique des commits sont mis à jour jusqu'au commit spécifié. L'index de staging et le répertoire de travail sont ensuite réinitialisés de sorte à correspondre à ceux du commit spécifié. Les changements apportés à l'index de staging et au répertoire de travail précédemment en attente sont réinitialisés de sorte à correspondre à l'état de l'arborescence des commits. Cela signifie que toute tâche en attente qui traînait dans l'index de staging et le répertoire de travail sera perdue.

Pour démontrer cet état de fait, poursuivons avec l'exemple de dépôt à trois arborescences mentionné précédemment. Apportons tout d'abord certains changements au dépôt. Exécutez les commandes suivantes dans l'exemple de dépôt :

$ echo 'new file content' > new_file
$ git add new_file
$ echo 'changed content' >> reset_lifecycle_file

Ces commandes ont créé un fichier intitulé new_file, que nous avons ajouté au dépôt. En outre, le contenu du fichier reset_lifecycle_file est modifié. Une fois ces changements en place, examinons l'état du dépôt grâce à git status.

$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: new_file
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: reset_lifecycle_file

Nous voyons désormais des changements en attente pour le dépôt. L'arborescence « Index de staging » présente un changement en attente pour l'ajout de new_file, et le répertoire de travail présente un changement en attente pour les changements apportés à reset_lifecycle_file.

Avant de poursuivre, examinons également l'état de l'index staging :

$ git ls-files -s
100644 8e66654a5477b1bf4765946147c49509a431f963 0 new_file
100644 d7d77c1b04b5edd5acfc85de0b592449e5303770 0 reset_lifecycle_file

Nous pouvons voir que new_file a été ajouté à l'index. Nous avons effectué des mises à jour dans reset_lifecycle_file, mais l'empreinte SHA de l'index de staging (d7d77c1b04b5edd5acfc85de0b592449e5303770) reste inchangée. Ce comportement est attendu, car git add n'a pas été utilisée pour promouvoir ces changements dans l'index de staging. Ces changements apparaissent dans le répertoire de travail.

Exécutons maintenant une commande git reset --hard et examinons le nouvel état du dépôt.

$ git reset --hard
HEAD is now at dc67808 update content of reset_lifecycle_file
$ git status
On branch master
nothing to commit, working tree clean
$ git ls-files -s
100644 d7d77c1b04b5edd5acfc85de0b592449e5303770 0 reset_lifecycle_file

Dans cet exemple, nous avons exécuté un « hard reset » à l'aide de l'option --hard. Git affiche une sortie indiquant que HEAD pointe vers le dernier commit dc67808. Nous vérifions ensuite l'état du dépôt grâce à git status. Git indique qu'aucun changement n'est en attente. Nous examinons également l'état de l'index de staging et nous nous apercevons qu'il a été réinitialisé à un point antérieur à l'ajout de new_file. Les changements apportés à reset_lifecycle_file et l'ajout de new_file ont été supprimés. Il est essentiel de noter que cette perte de données est définitive.

--mixed

Il s'agit du mode de fonctionnement par défaut. Les pointeurs de réf sont mis à jour. L'index de staging est réinitialisé à l'état du commit spécifié. Les changements annulés depuis l'index de staging sont déplacés vers le répertoire de travail. Continuons.

$ echo 'new file content' > new_file
$ git add new_file
$ echo 'append content' >> reset_lifecycle_file
$ git add reset_lifecycle_file
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: new_file
modified: reset_lifecycle_file
$ git ls-files -s
100644 8e66654a5477b1bf4765946147c49509a431f963 0 new_file
100644 7ab362db063f9e9426901092c00a3394b4bec53d 0 reset_lifecycle_file

Dans l'exemple ci-dessus, nous avons apporté certains changements au dépôt. À nouveau, nous avons ajouté un fichier new_file et modifié le contenu de reset_lifecycle_file. Ces changements sont ensuite appliqués à l'index de staging grâce à git add. Lorsque le dépôt est à cet état, nous exécutons le reset.

$ git reset --mixed
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: reset_lifecycle_file
Untracked files:
(use "git add ..." to include in what will be committed)
new_file
no changes added to commit (use "git add" and/or "git commit -a")
$ git ls-files -s
100644 d7d77c1b04b5edd5acfc85de0b592449e5303770 0 reset_lifecycle_file

Dans cet exemple, nous avons exécuté un « mixed reset ». Petit rappel : --mixed est le mode par défaut et a le même effet que la commande git reset. Lorsque l'on examine la sortie de git status et de git ls-files, on voit que l'index de staging a été réinitialisé à un état où reset_lifecycle_file était le seul fichier dans l'index. L'empreinte SHA d'objet pour reset_lifecycle_file a été réinitialisée à la version précédente.

L'important à retenir est que la commande git status nous montre que certains changements ont été apportés au fichier reset_lifecycle_file et qu'un fichier non suivi existe : new_file. Il s'agit du comportement --mixed explicite. L'index de staging a été réinitialisé, et les changements en attente ont été déplacés vers le répertoire de travail. Comparez cette opération au reset à l'aide de l'option --hard au cours de laquelle l'index de staging et le répertoire de travail ont été réinitialisés, entraînant la perte de ces mises à jour.

--soft

Lorsque l'argument --soft est transmis, les pointeurs de réf sont mis à jour, et le reset s'arrête. L'index de staging et le répertoire de travail ne sont pas modifiés. Ce comportement peut s'avérer difficile à démontrer clairement. Poursuivons avec notre dépôt de démo et préparons-le pour un « soft reset ».


$ git add reset_lifecycle_file 

$ git ls-files -s 

100644 67cc52710639e5da6b515416fd779d0741e3762e 0 reset_lifecycle_file 

$ git status 

On branch master 

Changes to be committed: 

(use "git reset HEAD ..." to unstage) 

modified: reset_lifecycle_file 

Untracked files: 

(use "git add ..." to include in what will be committed) 

new_file

Dans cet exemple, nous avons de nouveau utilisé git add pour promouvoir le fichier reset_lifecycle_file modifié dans l'index de staging. Nous confirmons que l'index a été mis à jour grâce à la sortie git ls-files. La sortie de git status affiche désormais la partie « Changes to be committed » en vert. Le fichier new_file mentionné dans les exemples précédents se situe dans le répertoire de travail sous forme de fichier non suivi. Exécutons rapidement rm new_file pour le supprimer, étant donné que nous n'en aurons pas besoin pour les exemples suivants.

Lorsque le dépôt est à cet état, nous exécutons un « soft reset ».

$ git reset --soft
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: reset_lifecycle_file
$ git ls-files -s
100644 67cc52710639e5da6b515416fd779d0741e3762e 0 reset_lifecycle_file

Dans cet exemple, nous avons exécuté un « soft reset ». L'examen de l'état du dépôt grâce à git status et git ls-files montre que rien n'a changé. C'est le comportement attendu. Un « soft reset » réinitialisera uniquement l'historique des commits. Par défaut, la commande git reset est appelée avec HEAD en tant que commit cible. Puisque notre historique des commits se situait déjà sur HEAD et que nous avons implicitement réinitialisé sur HEAD, rien n'a réellement changé.

Pour mieux comprendre et utiliser --soft, nous avons besoin d'un commit cible autre que HEAD. Nous avons reset_lifecycle_file en attente dans l'index de staging. Créons un commit.

$ git commit -m"prepend content to reset_lifecycle_file"

À ce stade, notre dépôt devrait comporter trois commits. Nous allons revenir au premier. Pour ce faire, nous allons avoir besoin de son ID. Vous le trouverez en affichant la sortie de git log.

$ git log
commit 62e793f6941c7e0d4ad9a1345a175fe8f45cb9df
Author: bitbucket <bitbucket@atlassian.com>
Date: Fri Dec 1 15:03:07 2017 -0800
prepend content to reset_lifecycle_file
commit dc67808a6da9f0dec51ed16d3d8823f28e1a72a
Author: bitbucket <bitbucket@atlassian.com>
Date: Fri Dec 1 10:21:57 2017 -0800
update content of reset_lifecycle_file
commit 780411da3b47117270c0e3a8d5dcfd11d28d04a4
Author: bitbucket <bitbucket@atlassian.com>
Date: Thu Nov 30 16:50:39 2017 -0800
initial commit

N'oubliez pas que les ID d'historique des commits seront uniques pour chaque système. Les ID de commit dans cet exemple seront donc différents que ceux que vous voyez sur votre machine personnelle. L'ID de commit qui nous intéresse dans le cadre de cet exemple est 780411da3b47117270c0e3a8d5dcfd11d28d04a4. Cet ID correspond au « commit initial ». Lorsque nous l'aurons trouvé, nous l'utiliserons comme cible pour notre « soft reset ».

Avant de faire un saut dans le passé, commençons par examiner l'état actuel du dépôt.

$ git status && git ls-files -s
On branch master
nothing to commit, working tree clean
100644 67cc52710639e5da6b515416fd779d0741e3762e 0 reset_lifecycle_file

Nous exécutons ici les deux commandes git status et git ls-files -s qui nous indiquent que des changements sont en attente dans le dépôt et que la version du fichier reset_lifecycle_file dans l'index de staging est 67cc52710639e5da6b515416fd779d0741e3762e. En gardant cela à l'esprit, exécutons un « soft reset » pour revenir à notre premier commit.

$git reset --soft 780411da3b47117270c0e3a8d5dcfd11d28d04a4
$ git status && git ls-files -s
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: reset_lifecycle_file
100644 67cc52710639e5da6b515416fd779d0741e3762e 0 reset_lifecycle_file

Le code ci-dessus exécute un « soft reset » et appelle également les deux commandes git status et git ls-files. Cette dernière génère l'état du dépôt. Nous pouvons examiner la sortie de l'état du dépôt et noter certains points intéressants. Tout d'abord, git status indique que des changements sont apportés à reset_lifecycle_file et les met en évidence en précisant qu'il s'agit de changements stagés pour le commit suivant. Ensuite, l'entrée git ls-files indique que l'index de staging n'a pas changé et conserve l'empreinte SHA précédente, 67cc52710639e5da6b515416fd779d0741e3762e.

Pour clarifier davantage ce qui s'est produit au cours de ce reset, examinons la commande git log :

$ git log
commit 780411da3b47117270c0e3a8d5dcfd11d28d04a4
Author: bitbucket <bitbucket@atlassian.com>
Date: Thu Nov 30 16:50:39 2017 -0800
initial commit

La sortie de journal montre désormais que l'historique des commits ne comprend qu'un seul commit. Cela permet d'illustrer clairement l'effet de l'argument --soft. Comme pour tous les appels de git reset, la première action consiste à réinitialiser l'arborescence des commits. Nos exemples précédents avec --hard et --mixed portaient tous deux sur HEAD et n'ont pas replacé l'arborescence des commits à temps. Au cours d'un « soft reset », il ne se passe rien d'autre.

La raison pour laquelle git status indique que des fichiers modifiés existent peut prêter à confusion. L'argument --soft ne touche pas l'index de staging. C'est pourquoi les mises à jour de notre index de staging sont revenues en arrière dans l'historique des commits. Cela peut être confirmé par la sortie de git ls-files -s indiquant que l'empreinte SHA de reset_lifecycle_file reste inchangée. Pour rappel, git status n'affiche pas l'état des « trois arborescences », elle les compare. Dans ce cas, elle indique que l'index de staging vient avant les changements dans l'historique des commits, comme si nous les avions déjà stagés.

Reset et revert

Si git revert constitue une méthode sûre pour annuler les changements, vous pouvez considérer git reset comme la méthode risquée. Avec git reset, le risque de perdre votre travail est réel. git reset ne supprimera jamais un commit. Toutefois, les commits peuvent devenir « orphelins », c'est-à-dire qu'il n'existe aucun chemin direct depuis une réf pour y accéder. Ces commits orphelins peuvent généralement être trouvés et restaurés grâce à la commande git reflog. Git supprimera définitivement les commits orphelins après avoir exécuté le « garbage collector » interne. Par défaut, Git est configuré pour exécuter le « garbage collector » tous les 30 jours. L'historique des commits constitue l'une des « trois arborescences Git ». Les deux autres, l'index de staging et le répertoire de travail, ne sont pas aussi permanentes que les commits. L'utilisation de cet outil demande une attention particulière, car il s'agit de l'une des seules commandes Git à pouvoir entraîner une perte de votre travail.

Alors que le revert est conçu pour annuler en toute sécurité un commit public, git reset vise à annuler les changements locaux apportés à l'index de staging et au répertoire de travail. Étant donné leurs objectifs distincts, les deux commandes sont implémentées différemment : un reset complet supprime un ensemble de changements, tandis que le revert conserve l'ensemble de changements d'origine et utilise un nouveau commit pour exécuter l'annulation.

Ne pas faire de reset de l'historique public

Vous ne devriez jamais utiliser git reset <commit> lorsque vous avez fait un push des instantanés après <commit> vers un dépôt public. Après sa publication, vous devez partir du principe que d'autres développeurs sont tributaires de votre commit.

La suppression d'un commit sur lequel d'autres membres de l'équipe ont continué de travailler pose de sérieux problèmes pour la collaboration. Lorsqu'ils essaient de se synchroniser avec votre dépôt, une partie de l'historique de projet semble avoir soudainement disparu. La séquence ci-dessous montre ce qu'il se passe lorsque vous essayez de réinitialiser un commit public. La branche origin/master est la version du dépôt centralisé de votre branche principale (master) locale.

Dès que vous ajoutez des commits après le reset, Git pense que votre historique local diverge de la branche origin/master, et le commit de merge requis pour synchroniser vos dépôts risque de perturber votre équipe.

Par conséquent, assurez-vous d'utiliser git reset <commit> sur une expérience locale qui a mal tourné, et non sur des changements publiés. Si vous devez corriger un commit public, la commande git revert est spécialement conçue à cet effet.

Exemples

git reset <file>

Cette commande supprime le fichier spécifié dans la zone de staging, mais ne modifie pas le répertoire de travail. Elle permet de stager un fichier sans écraser les changements.

git reset

Cette commande réinitialise la zone de staging de sorte à correspondre au commit le plus récent, sans modifier le répertoire de travail. Elle permet de stager tous les fichiers sans écraser les changements. Vous avez ainsi la possibilité de régénérer l'instantané stagé à partir de zéro.

git reset --hard

Cette commande réinitialise la zone de staging et le répertoire de travail de sorte à correspondre au commit le plus récent. Outre annuler le staging des changements, le flag --hard demande aussi à Git d'écraser tous les changements dans le répertoire de travail. En d'autres termes : cette commande annule tous les changements non commités. Vous devez donc vous assurer que vous voulez vraiment vous débarrasser de ce que vous avez développé en local avant de l'utiliser.

git reset <commit> 

Cette commande déplace la pointe de la branche actuelle vers commit, réinitialise la zone de staging de sorte qu'elle corresponde au commit le plus récent, mais ne touche pas au répertoire de travail. Tous les changements apportés depuis <commit> résideront dans le répertoire de travail, ce qui vous permet de commiter de nouveau l'historique de projet à l'aide d'instantanés plus propres et plus atomiques.

git reset --hard <commit> 

Cette commande déplace la pointe de la branche actuelle vers <commit>  et réinitialise la zone de staging ainsi que le répertoire de travail de sorte à correspondre au commit le plus récent. Elle annule non seulement les changements non commités, mais aussi les commits ultérieurs.

Annuler le staging d'un fichier

La commande git reset est fréquemment rencontrée lors de la préparation de l'instantané stagé. L'exemple suivant part du principe que vous avez deux fichiers appelés hello.py et main.py que vous avez déjà ajoutés au dépôt.

# Vous éditez les fichiers hello.py et main.py
# Vous stagez tout ce qui se trouve dans le répertoire actuel
git add.
# Vous réalisez que les changements dans les fichiers hello.py et main.py
# doivent être commités dans des instantanés différents
# Vous annulez le staging de main.py
git reset main.py
# Vous commitez uniquement hello.py
git commit -m "Make some changes to hello.py"
# Vous commitez main.py dans un instantané distinct
git add main.py
git commit -m "Edit main.py"

Comme vous pouvez le voir, git reset vous permet de conserver des commits très ciblés, puisque vous pouvez annuler le staging de changements non liés au prochain commit.

Supprimer les commits locaux

L'exemple suivant illustre une utilisation plus avancée. Il montre ce qui arrive lorsque vous avez travaillé sur un nouveau projet pendant un temps et que vous décidez de tout abandonner après avoir intégré certains instantanés à des commits.

# Vous créez un nouveau fichier appelé "foo.py" et vous y ajoutez du code
# Vous le commitez dans l'historique de projet
git add foo.py
git commit -m "Start developing a crazy feature"
# Vous éditez de nouveau "foo.py" et vous modifiez certains autres fichiers suivis
# Vous commitez un autre instantané
git commit -a -m "Continue my crazy feature"
# Vous décidez de laisser tomber la fonctionnalité et vous supprimez les commits associés
git reset --hard HEAD~2

La commande git reset HEAD~2 recule la branche actuelle de deux commits, ce qui supprime les deux instantanés que nous venons de créer à partir de l'historique du projet. N'oubliez pas que ce genre de reset ne devrait être utilisé que sur les commits non publiés. N'effectuez jamais l'opération ci-dessus si vous avez déjà fait un push de vos commits vers un dépôt partagé.

Résumé

Pour conclure, git reset est une commande puissante utilisée pour annuler des changements locaux liés à l'état d'un dépôt Git. git reset agit sur « les trois arborescences de Git ». Ces trois arborescences sont l'historique des commits (HEAD), l'index de staging et le répertoire de travail. Il existe trois options de ligne de commande qui correspondent à ces trois arborescences. Les options --soft, --mixed et --hard peuvent être transmises à git reset.

Dans cet article, nous avons utilisé un certain nombre de commandes Git supplémentaires afin d'illustrer les processus de reset. Pour en savoir plus sur ces commandes, reportez-vous aux pages correspondantes : git status, git log, git add, git checkout, git reflog et git revert.

Prêt à découvrir git reset ?

Essayez ce tutoriel interactif.

Démarrez maintenant