Est-il une différence entre "git reset --hard hash" et "git checkout de hachage"?

alors que reset et checkout ont des usages différents la plupart du temps, Je ne vois pas quelle différence il y a entre ces deux.

il y en a probablement un ou personne n'aurait pris la peine d'ajouter une option --hard pour faire quelque chose que le checkout de base peut faire.

Peut-être qu'il y a une différence est la façon dont vous voyez l'histoire?

42
demandé sur Arslan Ali 2010-03-30 01:55:02
la source

3 ответов

Cette réponse est le plus souvent cité à partir de ma réponse à une précédente question: git reset en anglais de .

Les deux sont très différents. Il en résulte le même état pour votre index et l'arbre de travail, mais l'histoire résultante et la branche courante ne sont pas les mêmes.

supposons que votre histoire ressemble à ceci, avec la branche principale actuellement cochée:

- A - B - C (HEAD, master)

et tu cours git reset --hard B . Vous aurez ceci:

- A - B (HEAD, master)      # - C is still here, but there's no
                            # branch pointing to it anymore

vous obtiendriez cet effet si vous utilisiez aussi --mixed ou --soft - la seule différence est ce qui arrive à votre arbre de travail et à votre index. Dans le cas --hard , l'arbre de travail et l'index correspondent à B .

maintenant, supposons que vous utilisiez git checkout B à la place.

- A - B (HEAD) - C (master)

vous avez fini dans un État de tête détaché. HEAD , arbre de travail, tous les index de match B , de même qu'avec le hard reset, mais la branche master a été laissé à C . Si vous faites un nouveau commit D à ce stade, vous obtiendrez ce qui n'est probablement pas ce que vous voulez:

- A - B - C (master)
       \
        D (HEAD)

donc, vous utilisez checkout pour, bien, vérifier que commettre. Vous pouvez jouer avec, faire ce que vous voulez, mais vous avez laissé votre branche derrière. Si vous voulez la branche déplacé trop, vous utilisez la réinitialisation.

53
répondu Cascabel 2017-05-23 14:45:43
la source

si la documentation fournie avec Git ne vous aide pas, jetez un oeil à une référence visuelle Git par Mark Lodato.

en particulier si vous comparez git checkout <non-branch> avec git reset --hard <non-branch> (liaison à chaud):

git checkout master~3 http://marklodato.github.com/visual-git-guide/checkout-detached.svg.png

git reset -- hard master~3 http://marklodato.github.com/visual-git-guide/reset-commit.svg.png

notez que dans le cas de git reset --hard master~3 vous laissez derrière vous une partie du DAG des révisions - certaines des propagations ne sont référencées par aucune branche. Ceux-ci sont protégés pendant (par défaut) 30 jours par refrog ; ils seraient finalement élagués (enlevés).

14
répondu Jakub Narębski 2012-03-14 23:43:27
la source

git-reset hash définit la référence de la branche au hachage donné, et éventuellement le vérifie, avec --hard .

git-checkout hash place l'arbre de travail au hachage donné; et à moins que le hachage soit un nom de branche, vous finirez avec une tête détachée.

en fin de compte, git traite de 3 choses:

                   working tree (your code)
-------------------------------------------------------------------------
                     index/staging-area
-------------------------------------------------------------------------
      repository (bunch of commits, trees, branch names, etc)

git-checkout par défaut ne fait que mettre à jour l'index et l'arbre de travail, et peut éventuellement mettre à jour quelque chose en le dépôt (avec l'option -b )

git-reset par défaut ne fait que mettre à jour le dépôt et l'index, et éventuellement l'arbre de travail (avec l'option --hard )

vous pouvez penser au dépôt comme ceci:

 HEAD -> master

 refs:
    master -> sha_of_commit_X
    dev -> sha_of_commit_Y

 objects: (addressed by sha1)

    sha_of_commit_X, sha_of_commit_Y, sha_of_commit_Z, sha_of_commit_A ....

git-reset manipule ce que les références de la branche indiquent.

supposons que votre histoire ressemble à ceci:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic2][topic3]

gardez à l'esprit que les branches ne sont que des noms qui progressent automatiquement lorsque vous commettez.

donc vous avez les branches suivantes:

 master -> Q
 dev -> Q
 topic1 -> G
 topic2 -> W
 topic3 -> W

et votre branche actuelle est topic2 , c'est-à-dire les têtes de topic2.

HEAD -> topic2

ensuite, git reset X réinitialisera le nom topic2 pour pointer vers X; ce qui signifie que si vous faites un commit P sur la branche topic2, les choses ressembleront à ceci:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic3]
                           \
                            P [topic2]
6
répondu hasen 2010-03-30 17:46:39
la source

Autres questions sur git git-checkout git-reset