web-dev-qa-db-fra.com

Quelle est la différence entre "git reset" et "git checkout"?

J'ai toujours pensé que git reset et git checkout étaient identiques, dans le sens où les deux ramènent le projet à un commit spécifique. Cependant, j'estime qu'ils ne peuvent pas être exactement les mêmes car cela serait redondant. Quelle est la différence réelle entre les deux? Je suis un peu confus, car le svn n'a que svn co pour annuler la validation.

AJOUTÉE

VonC et Charles ont très bien expliqué les différences entre git reset et git checkout. Mon interprétation actuelle est que git reset rétablit toutes les modifications sur un commit spécifique, alors que git checkout prépare plus ou moins une branche. J'ai trouvé les deux diagrammes suivants assez utiles pour arriver à cette compréhension:

http://a.imageshack.us/img651/1559/86421927.pnghttp://a.imageshack.us/img801/1986/resetr.png

Ajouté 3

From http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html =, checkout and reset peut émuler la base.

enter image description here

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

enter image description here

402
prosseek
  • git reset concerne spécifiquement la mise à jour de l'index , en déplaçant le HEAD.
  • git checkout est sur le point de mettre à jour l’arbre de travail (vers l’index ou l’arborescence spécifiée). Il ne mettra à jour le HEAD que si vous extrayez une branche (sinon, vous vous retrouverez avec un HEAD détaché ).
    (en fait, avec Git 2.23 Q3 2019, ce sera git restore , pas nécessairement _git checkout_)

Par comparaison, puisque svn n'a pas d'index, seul un arbre de travail, svn checkout , copie une révision donnée dans un répertoire séparé.
L’équivalent le plus proche de _git checkout_ serait:

  • svn update (si vous êtes dans la même branche, ce qui signifie la même URL SVN)
  • svn switch (si vous achetez par exemple la même branche, mais à partir d'une autre URL de dépôt SVN)

Ces trois modifications de l'arbre de travail (_svn checkout_, update, switch) n'ont qu'une seule commande dans git: _git checkout_.
Mais puisque git a aussi la notion d’index (cette "zone intermédiaire" entre le référentiel et l’arbre de travail), vous avez aussi _git reset_.


Thinkeye mentionne dans les commentaires l'article " Reset Demystified ".

Par exemple, si nous avons deux branches, 'master' et 'develop' pointant vers des commits différents, et nous sommes actuellement sur 'develop' (donc HEAD pointe dessus) et nous courons _git reset master_, 'develop' lui-même va maintenant pointer vers le même commit que 'master'.

Par contre, si nous exécutons plutôt _git checkout master_, 'develop' ne bougera pas, HEAD lui-même le fera. HEAD va maintenant pointer sur 'master'.

Donc, dans les deux cas, nous déplaçons HEAD vers le point de commettre A, mais la façon dont nous procédons est très différente. reset déplacera la branche HEAD pointe vers, l'extraction déplace HEAD lui-même pour pointer vers une autre branche.

http://git-scm.com/images/reset/reset-checkout.png

Sur ces points, cependant:

LarsH ajoute dans les commentaires :

Cependant, le premier paragraphe de cette réponse est trompeur: "_git checkout_ ... mettra à jour le HEAD uniquement si vous extrayez une branche (sinon, vous vous retrouverez avec un HEAD détaché)" .
Pas vrai: _git checkout_ mettra à jour le HEAD même si vous validez un commit qui n'est pas une branche (et oui, vous vous retrouvez avec un HEAD séparé, mais il a quand même été mis à jour ).

_git checkout a839e8f updates HEAD to point to commit a839e8f.
_

De Novo d'accord dans les commentaires :

@LarsH est correct.
La deuxième puce a une idée fausse de ce que HEAD mettra à jour le HEAD uniquement si vous extrayez une branche.
HEAD va où que vous soyez, comme une ombre.
L'extraction d'une référence non liée à une branche (une étiquette, par exemple) ou d'un commit directement déplacera HEAD. La tête détachée ne signifie pas que vous vous êtes détaché de la tête, cela signifie que la tête est détachée d'une référence de branche, ce que vous pouvez voir, par exemple, _git log --pretty=format:"%d" -1_.

  • Les états principaux attachés commenceront par _(HEAD ->_,
  • détaché affichera toujours _(HEAD_, mais n'aura pas de flèche vers une branche réf.
177
VonC

Dans sa forme la plus simple, reset réinitialise l'index sans toucher à l'arbre de travail, tandis que checkout modifie l'arbre de travail sans toucher à l'index.

Réinitialise l'index pour qu'il corresponde à HEAD, arbre de travail laissé seul:

git reset

Conceptuellement, cela vérifie l'index dans l'arbre de travail. Pour obtenir quoi que ce soit réellement, vous devez utiliser -f pour le forcer à écraser les modifications locales. Ceci est une fonctionnalité de sécurité permettant de s’assurer que le formulaire "sans argument" n’est pas destructeur:

git checkout

Une fois que vous commencez à ajouter des paramètres, il est vrai qu'il y a un certain chevauchement.

checkout est généralement utilisé avec une branche, une balise ou une validation. Dans ce cas, il réinitialisera HEAD et l'index à la validation donnée, tout en effectuant l'extraction de l'index dans l'arbre de travail.

De même, si vous fournissez --hard à reset, vous pouvez demander à reset de remplacer l’arborescence de travail et de réinitialiser l’index.

Si vous avez actuellement une branche extraite extraite, il y a une différence cruciale entre reset et checkout lorsque vous fournissez une autre branche ou un commit. reset changera la branche actuelle pour qu'elle pointe sur le commit sélectionné, alors que checkout laissera la branche actuelle seule mais extraira la branche fournie ou le commit à la place.

D'autres formes de reset et commit impliquent la fourniture de chemins.

Si vous fournissez des chemins à reset, vous ne pourrez pas fournir --hard et reset changera uniquement la version d'index des chemins fournis à la version de la livraison fournie (ou HEAD si vous ne spécifiez pas un commit).

Si vous fournissez des chemins à checkout, comme reset, la version d'index des chemins fournis sera mise à jour afin de correspondre à la validation fournie (ou HEAD), mais elle utilisera toujours la version d'index du fichier. chemins fournis dans l’arbre de travail.

64
CB Bailey

Un cas d'utilisation simple lors de l'annulation d'un changement:
1. Utilisez reset si vous souhaitez annuler la création d’un fichier modifié.
2. Utilisez checkout si vous souhaitez ignorer les modifications apportées aux fichiers non staged.

30
John Doe

Atlassian nous donne une excellente explication sur réinitialisation de git , git checkout et ainsi, git revert . Dans cet article, nous expliquons les différentes utilisations de ces commandes à différents niveaux - fichier, instantané par étape et validation.

https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

9
Rochadsouza

La différence principale en un mot est que reset déplace la référence de branche actuelle , alors que checkout ne le fait pas (il déplace HEAD).

Comme l'explique le livre Pro Git sous Réinitialiser démystifié ,

La première chose que reset fera est que déplace ce que HEAD pointe vers . Ce n’est pas la même chose que changer HEAD lui-même (ce que fait checkout); reset déplace la branche vers laquelle pointe HEAD. Cela signifie que si HEAD est défini sur la branche master (c'est-à-dire que vous êtes actuellement sur la branche master), l'exécution de git reset 9e5e6a4 commencera par créer master pointant vers 9e5e6a4. [emphase ajoutée]

Voir aussi la réponse de VonC pour un extrait de texte et de diagramme très utile du même article, que je ne vais pas reproduire ici.

Bien sûr, il existe beaucoup plus de détails sur les effets que checkout et reset peuvent avoir sur l’index et l’arbre de travail, en fonction des paramètres utilisés. Il peut y avoir beaucoup de similitudes et de différences entre les deux commandes. Mais à mon avis, la différence la plus cruciale est de savoir s'ils déplacent la pointe de la branche actuelle.

8
LarsH

Les deux commandes (reset et checkout) sont complètement différentes.

checkout X IS PAS reset --hard X

Si X est un nom de branche, checkout X modifiera la branche actuelle, alors que reset --hard X ne le fera pas.

1
wiki1000