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.
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:
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.
git checkout bar
git reset --hard newbar
git branch -d newbar
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é ).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 commettreA
, mais la façon dont nous procédons est très différente.reset
déplacera la brancheHEAD
pointe vers, l'extraction déplaceHEAD
lui-même pour pointer vers une autre branche.
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.
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.
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.
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
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 faitcheckout
);reset
déplace la branche vers laquelle pointe HEAD. Cela signifie que si HEAD est défini sur la branchemaster
(c'est-à-dire que vous êtes actuellement sur la branchemaster
), l'exécution degit reset 9e5e6a4
commencera par créermaster
pointant vers9e5e6a4
. [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.
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.