Annuler les commits et les changements
Dans cette section, nous allons aborder les stratégies et les commandes d'annulation Git disponibles. En premier lieu, il est important de noter que Git ne dispose pas de système d'annulation traditionnel comme ceux présents dans une application de traitement de texte. Il sera utile de vous abstenir de mapper des opérations Git à un modèle mental d'annulation traditionnel, quel qu'il soit. En outre, Git possède sa propre nomenclature pour les opérations d'annulation, et il convient de l'évoquer durant une discussion. Cette nomenclature inclut des termes comme reset, revert, check-out, clean, et bien d'autres.
Une métaphore amusante consiste à considérer Git comme un utilitaire de gestion des chronologies. Les commits sont des instantanés d'un point dans le temps ou de points d'intérêt tout au long de l'historique d'un projet. En outre, il est possible de gérer plusieurs chronologies en utilisant des branches. Lorsque vous faites des annulations dans Git, vous reculez généralement dans le temps ou vous revenez à une autre chronologie dans laquelle les erreurs n'ont pas été commises.
Ce tutoriel présente tous les outils nécessaires pour travailler avec les révisions précédentes d'un projet logiciel. Tout d'abord, nous verrons comment explorer d'anciens commits, puis nous parlerons de la différence entre le revert de commits publics dans l'historique du projet et le reset des changements non publiés en local, sur votre ordinateur.
Retrouvez des éléments perdus : comment passer en revue d'anciens commits
L'idée sous-jacente de tout système de contrôle de version est de stocker des copies sécurisées d'un projet afin que vous n'ayez plus à vous préoccuper de corrompre votre base de code. Une fois que vous avez créé un historique de projet pour les commits, vous pouvez passer en revue et revoir tous les commits de l'historique. La commande git log
constitue l'un des meilleurs outils pour passer en revue l'historique d'un dépôt Git. Dans l'exemple ci-dessous, nous utilisons git log pour obtenir la liste des derniers commits effectués dans une bibliothèque graphique open source populaire.
git log --oneline
e2f9a78fe Replaced FlyControls with OrbitControls
d35ce0178 Editor: Shortcuts panel Safari support.
9dbe8d0cf Editor: Sidebar.Controls to Sidebar.Settings.Shortcuts. Clean up.
05c5288fc Merge pull request #12612 from TyLindberg/editor-controls-panel
0d8b6e74b Merge pull request #12805 from harto/patch-1
23b20c22e Merge pull request #12801 from gam0022/improve-raymarching-example-v2
fe78029f1 Fix typo in documentation
7ce43c448 Merge pull request #12794 from WestLangley/dev-x
17452bb93 Merge pull request #12778 from OndrejSpanel/unitTestFixes
b5c1b5c70 Merge pull request #12799 from dhritzkiv/patch-21
1b48ff4d2 Updated builds.
88adbcdf6 WebVRManager: Clean up.
2720fbb08 Merge pull request #12803 from dmarcos/parentPoseObject
9ed629301 Check parent of poseObject instead of camera
219f3eb13 Update GLTFLoader.js
15f13bb3c Update GLTFLoader.js
6d9c22a3b Update uniforms only when onWindowResize
881b25b58 Update ProjectionMatrix on change aspect
Ressource connexe
Fiche de révision sur Git
DÉCOUVRIR LA SOLUTION
Découvrir Git avec Bitbucket Cloud
Chaque commit possède une empreinte d'identification SHA-1 unique. Ces identifiants sont utilisés pour explorer la chronologie commitée et réexaminer les commits. Par défaut, git log
affiche uniquement les commits pour la branche actuellement sélectionnée. Il est tout à fait possible que le commit que vous recherchez se trouve sur une autre branche. Vous pouvez afficher tous les commits sur toutes les branches en exécutant la commande git log --branches=*
. La commande git branch permet d'afficher et d'explorer d'autres branches. Lorsque vous appelez la commande git branch -a
, celle-ci renvoie une liste de tous les noms de branche connus. L'un de ces noms de branche peut ensuite être consigné à l'aide de la commande git log
.
Une fois que vous avez trouvé une référence de commit au point dans l'historique que vous souhaitez explorer, vous pouvez utiliser la commande git checkout
pour explorer ce commit. git checkout
est une méthode simple pour « charger » l'un de ces instantanés sauvegardés sur votre machine de développement. Durant le cours normal du développement, l'élément HEAD
pointe généralement vers la branche principale (main
) ou une autre branche locale, mais lorsque vous faites un check-out d'un ancien commit, HEAD
ne pointe plus vers une branche. Il pointe directement vers un commit. On parle alors d'état « HEAD
détaché », qui peut être illustré comme suit :
Lorsque vous faites le check-out d'un ancien fichier, vous ne déplacez pas le pointeur HEAD
. Ce dernier reste sur la même branche et le même commit, à l'état « HEAD détaché ». Vous pouvez ensuite faire un commit de l'ancienne version du fichier dans un nouvel instantané comme vous le feriez pour tout autre changement. Utiliser git checkout
dans un fichier permet donc de revenir à une ancienne version d'un fichier donné. Pour plus d'informations sur ces deux modes, consultez la page git checkout.
Afficher une ancienne version
Pour cet exemple, partons du principe que vous avez commencé à développer quelque chose d'un peu fou, mais que vous hésitez encore à le conserver ou pas. Pour vous aider à prendre une décision, vous souhaitez examiner l'état du projet avant le début de votre test. Tout d'abord, vous devez rechercher l'ID de la révision que vous souhaitez afficher.
git log --oneline
Supposons que votre historique de projet ressemble à ceci :
b7119f2 Continue doing crazy things
872fa7e Try something crazy
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
Vous pouvez utiliser git checkout
pour afficher le commit « Make some import changes to hello.txt » comme suit :
git checkout a1e8fb5
Ainsi, le statut de votre répertoire de travail correspond à celui du commit a1e8fb5
. Vous pouvez visualiser les fichiers, compiler le projet, effectuer des tests et même modifier des fichiers sans craindre de compromettre l'état actuel du projet. Rien de ce que vous ferez ici ne sera enregistré dans votre dépôt. Pour poursuivre le développement, vous devez revenir à l'état « actuel » de votre projet :
git checkout main
Cet exemple part du principe que vous développez sur la branche main
par défaut. Une fois que vous êtes revenu dans la branche main
, vous pouvez utiliser git revert ou git reset pour annuler les changements indésirables.
Annuler un instantané commité
Vous disposez de plusieurs stratégies différentes pour annuler un commit. Les exemples suivants partiront du principe que vous disposez d'un historique de commit comme le suivant :
git log --oneline
872fa7e Try something crazy
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
Nous allons nous concentrer sur l'annulation du commit 872fa7e Try something crazy
. Il était peut-être un peu trop insensé.
Comment annuler un commit avec git checkout
À l'aide de la commande git checkout
, nous pouvons faire un check-out du commit précédent, a1e8fb5
, pour rétablir le dépôt à un état antérieur au commit défaillant. Lorsque vous faites le check-out d'un commit donné, le dépôt est placé à l'état « HEAD détaché ». Cela signifie que vous ne travaillez plus sur une branche. À l'état détaché, tous les nouveaux commits que vous ferez seront orphelins lorsque repassez à une branche établie. Les commits orphelins seront supprimés par la commande garbage collection de Git. Cette dernière s'exécute à intervalles fixes et supprime les commits orphelins de façon permanente. Pour éviter leur suppression par la commande garbage collection, nous devons nous assurer de travailler sur une branche.
À l'état HEAD détaché, nous pouvons exécuter la commande git checkout -b nouvelle_branche_sans_commit_insensé
. Une branche appelée nouvelle_branche_sans_commit_insensé
va ainsi être créée, et l'état sera modifié en conséquence. Le dépôt se trouve maintenant sur une nouvelle chronologie dans laquelle le commit 872fa7e
n'existe plus. À ce stade, nous pouvons continuer de travailler sur cette nouvelle branche dans laquelle le commit 872fa7e
n'existe plus et la considérer comme « annulée ». Malheureusement, si vous avez besoin de la branche précédente, qui était peut-être votre main
, cette stratégie d'annulation n'est pas appropriée. Voyons un peu quelques autres stratégies d'annulation. Pour plus d'informations et d'exemples, consultez notre discussion approfondie sur git checkout.
Comment annuler un commit public avec git revert
Revenons à notre exemple d'historique de commit d'origine. Celui qui inclut le commit 872fa7e
. Cette fois, essayons de faire une annulation inversée. Si nous exécutons la commande git revert HEAD
, Git crée un nouveau commit qui sera l'exact opposé du dernier commit. Un nouveau commit est donc ajouté à l'historique de branche actuel, et celui-ci ressemble à ce qui suit :
git log --oneline
e2f9a78 Revert "Try something crazy"
872fa7e Try something crazy
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
À ce stade, nous avons techniquement « annulé » le commit 872fa7e
. Bien que le commit 872fa7e
existe toujours dans la chronologie, le nouveau commit e2f9a78
inverse les changements apportés dans 872fa7e
. Contrairement à notre précédente stratégie de check-out, nous pouvons continuer à utiliser la même branche. Cette solution est satisfaisante. C'est la méthode d'annulation idéale pour travailler avec des dépôts publics partagés. Si vous devez conserver un historique Git organisé et minime, cette stratégie peut ne pas vous satisfaire.
Comment annuler un commit avec git reset
Pour cette stratégie d'annulation, nous allons poursuivre avec notre exemple. git reset est une commande étendue aux multiples usages et fonctions. Si nous appelons la commande git reset --hard a1e8fb5
, l'historique de commit est réinitialisé sur ce commit donné. Lorsque nous examinons l'historique de commit avec la commande git log
, nous obtenons les résultats suivants :
git log --oneline
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
La sortie de journal indique que les commits e2f9a78
et 872fa7e
n'existent plus dans l'historique. À ce stade, nous pouvons continuer de travailler et de créer des commits comme si les commits « insensés » n'avaient jamais eu lieu. Cette méthode d'annulation de changements est la plus « propre » pour l'historique. La commande git reset est idéale pour les changements locaux ; elle ajoute cependant des complications lorsque vous travaillez avec un dépôt distant partagé. Si nous avons un dépôt distant partagé vers lequel nous avons fait un push du commit 872fa7e
et si nous essayons d'exécuter la commande git push
sur une branche dans laquelle l'historique a été réinitialisé, Git s'en aperçoit et renvoie une erreur. Git suppose que la branche dont vous faites un push n'est pas à jour en raison de ses commits manquants. Dans ces scénarios, vous devriez préférer git revert
comme méthode d'annulation.
Annuler le dernier commit
Dans la section précédente, nous avons vu différentes stratégies pour annuler des commits. Toutes sont également applicables au commit le plus récent. Mais, dans certains cas, vous ne pourrez peut-être pas supprimer ou restaurer le dernier commit. Il est possible qu'il ait été réalisé prématurément. Dans ce cas, vous pouvez modifier le commit le plus récent. Quand vous avez fait d'autres changements dans le répertoire de travail et que vous les avez stagés à des fins de commit à l'aide de git add, vous pouvez exécuter git commit --amend
. Cette commande va demander à Git d'ouvrir l'éditeur système configuré pour vous permettre de modifier le dernier message de commit. Les nouveaux changements seront ajoutés au commit modifié.
Annuler des changements non commités
Avant que les changements ne soient commités dans l'historique du dépôt, ils résident dans l'index de staging et dans le répertoire de travail. Vous devrez peut-être annuler des changements dans ces deux zones. L'index de staging et le répertoire de travail sont des mécanismes de gestion des états internes à Git. Pour des informations plus détaillées sur le fonctionnement de ces deux mécanismes, consultez la page git reset qui les explore en détail.
Le répertoire de travail
Le répertoire de travail est généralement synchronisé avec le système de fichiers local. Pour annuler des changements dans le répertoire de travail, vous pouvez modifier des fichiers comme vous le feriez normalement à l'aide de votre éditeur préféré. Git propose plusieurs utilitaires pour vous aider à gérer le répertoire de travail. La commande git clean est un utilitaire pratique pour annuler des changements dans le répertoire de travail. En outre, git reset
peut être appelée avec l'option --mixed
ou --hard
. Elle applique alors un reset sur le répertoire de travail.
L'index de staging
La commande git add permet d'ajouter des changements à l'index de staging. git reset
est principalement utilisée pour annuler les changements apportés à l'index de staging. Un reset avec l'option --mixed
déplace tout changement en attente de l'index de staging vers le répertoire de travail.
Annuler des changements publics
Lorsque vous travaillez en équipe sur des dépôts distants, des considérations supplémentaires entrent en ligne de compte lors de l'annulation de changements. git reset
devrait généralement être considérée comme une méthode d'annulation locale. Un reset devrait être utilisé lorsque vous annulez des changements dans une branche privée. Vous isolez ainsi nettement la suppression de commits des autres branches susceptibles d'être utilisées par d'autres développeurs. Des problèmes se posent lorsqu'un reset est exécuté sur une branche partagée et qu'un push est réalisé à distance sur cette branche à l'aide de git push
. Git bloque alors le push dans ce scénario, en arguant que la branche pushée n'est pas à jour par rapport à la branche distante, car elle ne contient pas tous les commits.
git revert
constitue la méthode privilégiée pour annuler un historique partagée. La commande revert est plus sûre que reset, car elle ne supprime pas de commits dans un historique partagé. Elle conserve les commits que vous souhaitez annuler et crée un nouveau commit qui inverse le commit indésirable. Cette méthode est plus sûre pour la collaboration à distance partagée, car un développeur hors site peut faire un pull de la branche et recevoir le nouveau commit inversé, lequel annule le commit indésirable.
Résumé
Nous avons couvert de nombreuses stratégies de haut niveau pour annuler des actions dans Git. Il est important de se rappeler qu'il existe plusieurs façons d'annuler dans un projet Git. La plupart des discussions de cette page abordent des sujets qui vont plus loin et sont expliqués plus en détail sur les pages propres aux commandes Git pertinentes. Les outils d'annulation les plus couramment utilisés sont git checkout, git revert et git reset. Voici quelques points clés à retenir :
- Une fois les changements commités, ils sont généralement permanents.
- Utilisez
git checkout
pour déplacer et passer en revue l'historique de commit. git revert
est le meilleur outil pour annuler les changements publics partagés.git reset
est le meilleur moyen d'annuler les changements privés locaux.
Outre les commandes d'annulation principales, nous avons également examiné d'autres outils Git : git log pour trouver les commits perdus, git clean pour annuler les changements non commités et git add pour modifier l'index de staging.
Chacune de ces commandes possède sa propre documentation détaillée. Pour en savoir plus sur une commande spécifique mentionnée dans cet article, consultez les liens correspondants.
Partager cet article
Thème suivant
Lectures recommandées
Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.