Close

Resetting, checking out & reverting


The git reset, git checkout, and git revert commands are some of the most useful tools in your Git toolbox. They all let you undo some kind of change in your repository, and the first two commands can be used to manipulate either commits or individual files.

Comme elles sont très similaires, veillez à ne pas les confondre : à chaque scénario sa commande ! Dans cet article, nous allons comparer les configurations les plus courantes de git reset, git checkout et git revert. Ainsi, vous n'éprouverez aucune difficulté à utiliser ces commandes pour parcourir votre dépôt.

Les trois arborescences de Git

It helps to think about each command in terms of their effect on the three state management mechanisms of a Git repository: the working directory, the staged snapshot, and the commit history. These components are sometimes known as "The three trees" of Git. We explore the three trees in depth on the git reset page. Keep these mechanisms in mind as you read through this article.

Un checkout est une opération qui permet de déplacer le pointeur de réf HEAD vers un commit spécifique. Pour démontrer ce point, prenons l'exemple suivant.

Déplacement du pointeur de réf HEAD vers un commit spécifique
Bases de données
Ressource connexe

Comment déplacer un dépôt Git complet

Logo Bitbucket
DÉCOUVRIR LA SOLUTION

Découvrir Git avec Bitbucket Cloud

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

Sequence of commits on the main branch

Il s'agit d'une mise à jour de l'arborescence « Historique des commits ». La commande git checkout peut être utilisée dans un commit ou un périmètre de niveau fichier. Un checkout de niveau fichier modifiera le contenu du fichier pour correspondre à celui du commit spécifique.

Un revert est une opération qui prend un commit spécifique et crée un nouveau commit qui inverse le commit spécifique. La commande git revert peut uniquement être exécutée pour un périmètre de niveau commit et ne dispose d'aucune fonctionnalité de niveau fichier.

Un reset est une opération qui prend un commit spécifique et réinitialise les « trois arborescences » de sorte qu'elles correspondent à l'état du dépôt au niveau du commit spécifique. Un reset peut être appelé dans trois modes différents qui correspondent aux trois arborescences.

Le checkout et le reset sont généralement utilisés pour procéder à des « annulations » locales ou privées. Ils modifient l'historique d'un dépôt, ce qui peut entraîner des conflits lors d'un push vers des dépôts partagés distants. Le revert est considéré comme une opération sûre, étant donné qu'il crée un nouvel historique qui peut être partagé à distance et n'écrase pas un historique dont peuvent dépendre les membres de l'équipe à distance.

Git reset vs revert vs checkout reference


Le tableau ci-dessous répertorie les utilisations les plus courantes de toutes ces commandes. Veillez à le conserver pour vous y référer ultérieurement, car vous aurez sans doute besoin d'en utiliser au moins quelques-unes en tant que développeur Git.

Commande

Périmètre

Utilisations courantes

git reset

Périmètre

Niveau commit

Utilisations courantes

Discard commits in a private branch or throw away uncommitted changes

git reset

Périmètre

Niveau fichier

Utilisations courantes

Annuler le staging d'un fichier

Git checkout

Périmètre

Niveau commit

Utilisations courantes

Basculer entre les branches ou inspecter d'anciens instantanés

Git checkout

Périmètre

Niveau fichier

Utilisations courantes

Annuler des changements dans le répertoire de travail

Git revert

Périmètre

Niveau commit

Utilisations courantes

Annuler des commits dans une branche publique

Git revert

Périmètre

Niveau fichier

Utilisations courantes

(N/A)

Commit level operations


Les paramètres que vous définissez pour git reset et git checkout déterminent leur périmètre. Si vous ne spécifiez pas de chemin d'accès dans vos paramètres, ceux-ci s'appliqueront à tous les commits. Pour plus d'informations sur le sujet, consultez la section ci-dessous. Remarque : git revert n'a pas d'homologue au niveau fichier.

Reset a specific commit

À l'échelle des commits, la réinitialisation permet de déplacer la pointe d'une branche vers un autre commit. Elle peut également servir à supprimer des commits dans la branche courante. Par exemple, la commande suivante fait reculer la branche hotfix de deux commits.

git checkout hotfix git reset HEAD~2

Les deux commits situés à la fin de hotfix constituent désormais des commits libres ou orphelins. Cela signifie qu'ils seront supprimés au prochain nettoyage de type garbage collection effectué par Git. En d'autres termes, cette opération revient à supprimer les commits concernés. Elle peut être visualisée comme suit :

Reset de la branche hotfix sur HEAD-2

Cette utilisation de git reset constitue une manière simple d'annuler des changements qui n'ont pas encore été partagés. Cette commande est incontournable lorsque vous commencez à travailler sur une fonctionnalité, puis que tout à coup, vous vous rendez compte que vous vous êtes trompé et que vous voulez tout recommencer.

En plus de déplacer la branche courante, vous pouvez exécuter git reset pour modifier l'instantané stagé et/ou le répertoire de travail en y ajoutant l'un des flags suivants :

  • --soft – L'instantané stagé et le répertoire de travail restent inchangés.
  • --mixed – L'instantané stagé est aligné sur le commit spécifié, tandis que le répertoire de travail reste inchangé. C'est l'option par défaut.
  • --hard : l'instantané stagé et le répertoire de travail sont tous deux alignés sur le commit spécifié.

It’s easier to think of these modes as defining the scope of a git reset operation. For further detailed information visit the git reset page.

Faire un checkout des anciens commits

La commande git checkout est utilisée pour mettre à jour l'état du dépôt à un point spécifique de l'historique des projets. Une fois la branche nommée, vous pouvez basculer entre les branches.

git checkout hotfix

En interne, la commande ci-dessus a pour seul effet de déplacer HEAD vers une autre branche et de mettre à jour le répertoire de travail. Puisque cette opération est susceptible d'annuler vos changements en local, Git vous oblige à faire un commit ou un stash de tout changement dans le répertoire de travail qui sera perdu lors du checkout. Contrairement à git reset, git checkout ne déplace aucune branche.

Moving HEAD from main to hotfix

Vous pouvez également réaliser un checkout des commits arbitraires en ajoutant la référence du commit plutôt qu'une branche. Cette opération revient à faire un checkout d'une branche : la référence HEAD est déplacée vers le commit spécifié. Par exemple, la commande suivante va extraire le grand-parent du commit courant :

git checkout HEAD~2
Déplacer le HEAD vers un commit arbitraire

Elle peut s'avérer utile pour jeter un coup d'œil rapide à une ancienne version de votre projet. Cependant, puisqu'aucune référence de branche n'est associée au marqueur HEAD courant, vous passez à l'état HEAD détaché. Attention : si vous commencez à ajouter de nouveaux commits, il vous sera impossible de les récupérer une fois que vous aurez basculé sur une autre branche. C'est la raison pour laquelle vous devez toujours créer une nouvelle branche avant d'ajouter des commits à un HEAD détaché.

Undo public commits with revert

L'opération revert annule un commit en créant un nouveau commit. C'est une méthode sûre pour annuler des changements, car elle ne risque pas de réécrire l'historique du commit. Par exemple, la commande suivante détermine les changements contenus dans les commits (du 2e au dernier), crée un nouveau commit qui annule ces changements et ajoute le nouveau commit au projet existant.

git checkout hotfix git revert HEAD~2

Elle peut être visualisée comme suit :

Faire un revert des commits (du 2e au dernier)

Veillez à ne pas confondre cette commande avec git reset, qui modifie l'historique des commits existant. Par conséquent, utilisez git revert pour annuler des changements apportés à une branche publique, et git reset pour faire de même, mais sur une branche privée.

Gardez à l'esprit que git revert sert à annuler des changements commités, tandis que git reset HEAD permet d'annuler des changements non commités.

À l'instar de git checkout, git revert est susceptible d'écraser des fichiers dans le répertoire de travail et vous demandera donc de faire un commit ou un stash des changements qui risqueraient d'être perdus pendant le revert.

File-level operations


Les commandes git reset et git checkout permettent aussi d'utiliser un chemin d'accès optionnel en guise de paramètre. Leur comportement s'en trouve fortement modifié. Au lieu d'opérer sur des instantanés entiers, elles se limitent à un seul fichier.

Git reset a specific file

Associée à un chemin d'accès, la commande git reset met à jour l'instantané stagé staged snapshot pour l'aligner sur la version issue du commit spécifié. Par exemple, elle récupère la version de foo.py dans l'avant-dernier commit et l'indexe pour le prochain commit :

git reset HEAD~2 foo.py

Tout comme la version de git reset de niveau commit, elle est plus souvent utilisée avec HEAD plutôt qu'avec un commit arbitraire. L'exécution de git reset HEAD foo.py annulera foo.py. Les changements qu'il contient seront toujours apparents dans le répertoire de travail.

Transférer un fichier de l'historique des commits vers l'instantané stagé

Les flags --soft, --mixed et --hard n'ont aucun effet sur la version de git reset de niveau fichier, puisque l'instantané stagé est continuellement mis à jour, tandis que le répertoire de travail ne l'est jamais.

Git checkout file

L'extraction de fichiers s'apparente à l'utilisation de git reset associée à un chemin d'accès, à cela près que c'est le répertoire de travail qui est mis à jour, et non la zone de staging. Contrairement à la version de cette commande de niveau commit, la référence HEAD n'est pas déplacée, donc vous ne basculez pas entre les branches.

Transférer un fichier de l'historique des commits vers le répertoire de travail

Par exemple, la commande suivante aligne le fichier foo.py du répertoire de travail sur celui de l'avant-dernier commit :

git checkout HEAD~2 foo.py

Tout comme la version de git checkout de niveau commit, cette commande peut être utilisée pour examiner les anciennes versions d'un projet. Cependant, son périmètre est limité au fichier spécifié.

Si vous indexez et commitez le fichier extrait, il sera remplacé par son ancienne version. Remarque : cette opération supprime tous les changements ultérieurs apportés au fichier, alors que la commande git revert annule uniquement les changements apportés par le commit spécifié.

À l'instar de git reset, cette commande est souvent utilisée avec HEAD en guise de référence de commit. Par exemple, git checkout HEAD foo.py a pour effet d'ignorer les changements non stagés apportés à foo.py. Le résultat est le même que pour git reset HEAD --hard à cela près que seul le fichier spécifié est concerné.

Résumé


You should now have all the tools you could ever need to undo changes in a Git repository. The git reset, git checkout, and git revert commands can be confusing, but when you think about their effects on the working directory, staged snapshot, and commit history, it should be easier to discern which command fits the development task at hand.


Partager cet article

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.

Des personnes qui collaborent à l'aide d'un mur rempli d'outils

Le blog Bitbucket

Illustration DevOps

Parcours de formation DevOps

Démos Des démos avec des partenaires d'Atlassian

Fonctionnement de Bitbucket Cloud avec Atlassian Open DevOps

Inscrivez-vous à notre newsletter DevOps

Thank you for signing up