web-dev-qa-db-fra.com

Quelle est la différence entre git reset --mixed, --soft et --hard?

Je cherche à diviser un commit et je ne suis pas sûr de l'option de réinitialisation à utiliser.

Je regardais la page Pouvez-vous expliquer ce que "git reset" fait en anglais? , mais j’ai réalisé que je ne comprenais pas vraiment ce que l’index git ou la zone de transit était, et donc les explications n’ont pas aidé.

De plus, les cas d'utilisation de --mixed et de --soft sont identiques dans cette réponse (lorsque vous souhaitez corriger et réengager). Est-ce que quelqu'un peut le décomposer encore plus? Je réalise que --mixed est probablement l'option à utiliser, mais je veux savoir pourquoi. Enfin, qu'en est-il de --hard?

Quelqu'un peut-il me donner un exemple de flux de travail montrant comment sélectionner les 3 options?

576
Michael Chinen

Lorsque vous modifiez un fichier dans votre référentiel, la modification est initialement non mise en scène. Pour le commettre, vous devez le préparer (c'est-à-dire l'ajouter à l'index) à l'aide de git add. Lorsque vous effectuez une validation, les modifications validées sont celles qui ont été ajoutées à l'index.

git reset change, au minimum, l'endroit où la branche actuelle (HEAD) pointe. La différence entre --mixed et --soft est de savoir si votre index est également modifié ou non. Donc, si nous sommes sur la branche master avec cette série de commits:

- A - B - C (master)

HEADpoints à C et l'index correspond à C.

Lorsque nous exécutons git reset --soft B, master (et donc HEAD), pointe maintenant sur B, mais l'index a toujours les modifications de C; git status les montrera comme mis en scène. Donc, si nous exécutons git commit à ce stade, nous aurons un nouveau commit avec les mêmes modifications que C.


Bon, alors à partir d'ici encore:

- A - B - C (master)

Maintenant, faisons git reset --mixed B. (Remarque: --mixed est l'option par défaut). Encore une fois, master et HEAD pointent vers B, mais cette fois, l'index est également modifié pour correspondre à B. Si nous exécutons git commit à ce stade, rien ne se passera puisque l'index correspond à HEAD. Nous avons toujours les modifications dans le répertoire de travail, mais comme elles ne figurent pas dans l'index, git status les affiche comme non mises en scène. Pour les commettre, vous devez git add et ensuite commettre comme d'habitude.


Et finalement, --hard est identique à --mixed (cela change votre HEAD et votre index), sauf que --hard modifie également votre répertoire de travail. Si nous en sommes à C et exécutons git reset --hard B, les modifications ajoutées à C, ainsi que toutes les modifications non validées que vous avez, seront supprimées et les fichiers de votre copie de travail correspondront à commit B. Comme vous pouvez perdre définitivement les modifications de cette façon, vous devez toujours exécuter git status avant de procéder à une réinitialisation matérielle pour vous assurer que votre répertoire de travail est propre ou que vous acceptez de perdre vos modifications non validées.


Et enfin, une visualisation: enter image description here

1187
mkarasek

Veuillez noter qu'il s'agit d'une explication simplifiée, conçue comme une première étape pour tenter de comprendre cette fonctionnalité complexe.

Peut être utile pour les apprenants visuels qui souhaitent visualiser l'état de leur projet après chacune de ces commandes:


Pour ceux qui utilisent Terminal avec la couleur activée (Git config --global color.ui auto): 

git reset --soft A et vous verrez le contenu de B et C en vert (mis en scène et prêt à être utilisé) 

git reset --mixed A (ou git reset A) et vous verrez les éléments de B et C en rouge (non mis en scène et prêts à être mis en scène (verts) puis validés) 

git reset --hard A et vous ne verrez plus les modifications de B et C nulle part (comme si elles n'avaient jamais existé)


Ou pour ceux qui utilisent un programme graphique comme "Tower" ou "SourceTree"

git reset --soft A et vous verrez le contenu de B et C dans la zone "fichiers par étapes" prêt à être utilisé

git reset --mixed A (ou git reset A) et vous verrez les éléments de B et C dans la zone "fichiers non staged" prêts à être déplacés vers staged puis validés

git reset --hard A et vous ne verrez plus les modifications de B et C nulle part (comme si elles n'avaient jamais existé)

63
timhc22

Dans les termes les plus simples:

  • --soft: uncommit changes, les modifications sont laissées en étapes (index).
  • --mixed(par défaut): uncommit + unstage change, les modifications sont laissées dans arbre de travail.
  • --hard: uncommit + unstage + delete changes, il ne reste plus rien.
41
Mo Ali

Voici une explication de base pour les utilisateurs de TortoiseGit:

git reset --soft et --mixed laissez vos fichiers intacts. 

git reset --hard réellement changez vos fichiers pour correspondre au commit que vous avez réinitialisé.

Dans TortoiseGit, le concept de the index est très caché par l'interface graphique. Lorsque vous modifiez un fichier, vous n'avez pas besoin d'exécuter git add pour ajouter la modification à la zone/au stockage intermédiaire. Lorsqu’il s’agit simplement de modifications de fichiers existants qui ne changent pas de noms de fichiers, git reset --soft et --mixed sont identiques! Vous ne remarquerez une différence que si vous avez ajouté de nouveaux fichiers ou des fichiers renommés. Dans ce cas, si vous exécutez git reset --mixed, vous devrez rajouter vos fichiers à partir de la liste Non Versioned Files

21
James Lawruk

Dans ces cas-là, j'aime un visuel qui peut, espérons-le, expliquer ceci:

git reset --[hard/mixed/soft]:

 enter image description here

Donc, chaque effet est différent

  1. Dur => WorkingDir + Index + HEAD
  2. Mixte => Index + HEAD
  3. Soft => HEAD uniquement (index et répertoire de travail inchangés).
7
Tomer Ben David

Toutes les autres réponses sont bonnes, mais je trouve mieux de les comprendre en divisant les fichiers en trois catégories: unstaged, staged, commit:

  • --hard devrait être facile à comprendre, il restaure tout
  • --mixed (par défaut) :
    1. unstaged fichiers: ne change pas
    2. staged fichiers: déplacer vers unstaged
    3. commit fichiers: déplacer vers unstaged
  • --soft:
    1. unstaged fichiers: ne change pas
    2. staged fichiers: ne pas changer
    3. commit fichiers: déplacer vers staged

En résumé:

  • L'option --soft déplace tout (sauf les fichiers unstaged) dans staging area
  • L'option --mixed déplacera tout dans unstaged area
5
Hansen W

La différence de base entre les différentes options de la commande git reset est décrite ci-dessous.

  • --soft: réinitialise uniquement le HEAD sur le commit que vous sélectionnez. Fonctionne fondamentalement de la même manière que git checkout mais ne crée pas d’état détaché.
  • --mixed (option par défaut): Réinitialise le HEAD sur le commit que vous sélectionnez dans l'historique et annule les modifications apportées à l'index.
  • --hard: réinitialise le HEAD sur le commit que vous avez sélectionné dans l'historique, annule les modifications apportées à l'index et annule les modifications apportées à votre répertoire de travail.
1

Il y a un certain nombre de réponses ici avec une idée fausse sur git reset --soft. Bien qu'il existe une condition spécifique dans laquelle git reset --soft ne modifie que HEAD (à partir d'un état d'en-tête détaché), généralement (et pour l'utilisation prévue), il déplace la référence de branche que vous avez actuellement extraite. Bien sûr, cela ne peut pas être fait si aucune branche n’a été extraite (d’où la condition spécifique dans laquelle git reset --soft ne modifiera que HEAD). 

J'ai trouvé que c'était la meilleure façon de penser à git reset. Vous ne déplacez pas simplement HEAD ( tout ce qui fait cela ), vous déplacez également le réf. Branche, par exemple, master. Ceci est similaire à ce qui se produit lorsque vous exécutez git commit (la branche en cours se déplace avec HEAD), sauf qu'au lieu de créer (et de déplacer) un nouveau commit, vous passez à un précédent commettre.

C'est le point de reset, changer un branche en quelque chose d'autre qu'un nouveau commit, ne pas changer HEAD. Vous pouvez le voir dans l'exemple de documentation:

Annuler un commit, en faire une branche de sujet

          $ git branch topic/wip     (1)
          $ git reset --hard HEAD~3  (2)
          $ git checkout topic/wip   (3)
  1. Vous avez fait des commits, mais vous réalisez qu'ils étaient prématurés pour être dans la branche "maître". Vous souhaitez continuer à les polir dans une branche de sujet, créez donc une branche "sujet/balayage" à partir du HEAD actuel.
  2. Rembobinez la branche principale pour vous débarrasser de ces trois commits.
  3. Passez à la branche "topic/wip" et continuez à travailler.

Quel est le point de cette série de commandes? Vous voulez déplacer une branche _, ici master, de sorte que tant que vous avez master emprunté, vous exécutez git reset.

La réponse la plus votée ici est généralement bonne, mais j’ai pensé que j’ajouterais ceci pour corriger les réponses erronées.

Changer de branche

git reset --soft <ref>: réinitialise le pointeur de branche pour la branche actuellement extraite sur la validation à la référence spécifiée,. Les fichiers de votre répertoire de travail et de votre index ne sont pas modifiés. Commettre à partir de cette étape vous ramènera à l’endroit où vous étiez avant la commande git reset.

Changer votre index aussi

git reset --mixed <ref>

ou équivalent

git reset <ref>:

Est-ce que --soft fait ET réinitialise également l'index pour qu'il corresponde à la validation à la référence spécifiée. Alors que git reset --soft HEAD ne fait rien (parce qu'il dit déplacer la branche extraite vers la branche extraite), git reset --mixed HEAD, ou de manière équivalente git reset HEAD, est une commande courante et utile car elle réinitialise l'index à l'état de votre dernière validation.

Changez aussi votre répertoire de travail

git reset --hard <ref>: ce que --mixed fait ET écrase également votre répertoire de travail. Cette commande est similaire à git checkout <ref>, sauf que (et c’est le point crucial de reset) toutes les formes de git reset déplacer la référence de branche que HEAD pointe sur.}

Une note à propos de "telle commande déplace la tête":

Il n'est pas utile de dire qu'une commande déplace la HEAD. Toute commande qui change votre position dans votre historique de validation déplace la variable HEAD. C'est ce que la HEADest, un pointeur où que vous soyez. HEADis you , et bougera donc chaque fois que vous le ferez. 

1
De Novo

--soft: Indique à Git de réinitialiser HEAD sur un autre commit, aussi l'index et le répertoire de travail ne seront modifiés d'aucune façon. Tous les fichiers modifiés entre le HEAD d'origine et le commit seront mis en scène.

--mixed: Tout comme le logiciel, cela réinitialisera HEAD sur un autre commit. Il réinitialisera également l'index pour qu'il corresponde sans que le répertoire de travail ne soit touché. Toutes les modifications resteront dans le répertoire de travail et apparaîtront comme modifiées, mais pas par étapes.

--hard: tout est réinitialisé - il réinitialise HEAD sur un autre commit, réinitialise l'index et le répertoire de travail.

La principale différence entre --mixed et --soft est que votre index est également modifié ou non. Vérifiez plus à ce sujet ici .

1
Nesha Zoric

Une réponse courte dans quel contexte les 3 options sont utilisées:

Pour conserver les modifications actuelles dans le code mais réécrire l'historique de validation:

  • soft: Vous pouvez tout valider en même temps et créer un nouveau commit avec une nouvelle description (si vous utilisez torotise git ou la plupart des autres interfaces graphiques, c’est celui à utiliser, car vous pouvez toujours cocher les fichiers que vous voulez dans le commit et les créer. plusieurs commits de cette façon avec différents fichiers. Dans Sourcetree, tous les fichiers seraient stockés pour la validation.)
  • mixed: Vous devrez ajouter à nouveau les fichiers individuels à l'index avant de procéder à des validations (dans Sourcetree, tous les fichiers modifiés ne seraient pas mis en scène)

Pour réellement perdre vos modifications dans le code également:

  • hard: vous ne réécrivez pas simplement l'historique, mais vous perdez également toutes vos modifications jusqu'au moment de la réinitialisation.
1
Nickpick

Vous n'avez pas à vous forcer à vous rappeler les différences entre elles. Pensez à la façon dont vous avez réellement commis un commit.

1.Faire des changements.

2.git ajouter.

3.gc -m "j'ai fait quelque chose"

Doux, Mixte et Difficile est le moyen permettant d'abandonner les opérations que vous avez effectuées de 3 à 1.

Soft "fait semblant" de ne jamais vous voir avoir fait "gc -m".

Mixed "feint" de ne jamais voir que tu as fait "git add."

Dur "fait semblant" de ne jamais voir que vous avez modifié les fichiers. 

1
qinmu2127

Avant d’entrer dans ces trois options, il faut comprendre trois choses.

1) Histoire/HEAD

2) Stade/index

3) Répertoire de travail

reset --soft: l'historique a été modifié, HEAD a été modifié, le répertoire de travail n'est pas modifié.

reset --mixed: l'historique a été modifié, HEAD a été modifié, le répertoire de travail a été modifié avec des données non synchronisées.

reset --hard: l'historique a été modifié, HEAD a été modifié, le répertoire de travail est modifié avec des données perdues.

Il est toujours prudent d’utiliser Git --soft. On devrait utiliser une autre option dans l'exigence complexe.

1
Suresh Sharma

la réponse de mkarasek est excellente, en termes simples, nous pouvons le dire ...

  • git reset --soft: définissez la HEAD sur le commit prévu mais conservez vos modifications à partir des derniers commits
  • git reset --mixed: identique à git reset --soft mais la seule différence est qu'il ne modifie pas vos modifications depuis les derniers commits
  • git reset --hard: définissez votre HEAD sur la validation que vous spécifiez et réinitialisez toutes vos modifications depuis la dernière validation, y compris les modifications non validées. 
0
Vivek Maru