Question Pouvez-vous expliquer ce que "git reset" fait en anglais?


J'ai vu messages intéressants expliquer les subtilités à propos de git reset.

Malheureusement, plus je lis à ce sujet, plus il semble que je ne le comprends pas complètement. Je viens d'un arrière-plan SVN et Git est un tout nouveau paradigme. J'ai facilement mercurial, mais Git est beaucoup plus technique.

je pense git reset est près de hg revert, mais il semble qu'il y ait des différences.

Alors qu'est-ce que fait exactement git reset faire? Veuillez inclure des explications détaillées sur:

  • les options --hard, --soft et --merge;
  • la notation étrange que vous utilisez avec HEAD tel que HEAD^ et HEAD~1;
  • cas d'utilisation concrets et flux de travail;
  • conséquences sur la copie de travail, le HEAD et votre niveau de stress global.

591
2018-03-27 16:44


origine


Réponses:


En général, git resetLa fonction est de prendre la branche courante et de la réinitialiser pour pointer ailleurs, et éventuellement amener l'index et l'arbre de travail. Plus concrètement, si votre branche master (actuellement extraite) est comme ceci:

- A - B - C (HEAD, master)

et vous réalisez que vous voulez que le maître pointe vers B, pas C, vous utiliserez git reset B pour le déplacer là:

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

Digression: Ceci est différent d'une caisse. Si vous couriez git checkout B, vous auriez ceci:

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

Vous avez fini dans un état détaché HEAD. HEAD, arbre de travail, index tous les matchs B, mais la branche principale a été laissée à C. Si vous faites un nouveau commit D à ce stade, vous obtiendrez ceci, ce qui n'est probablement pas ce que vous voulez:

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

Rappelez-vous, reset ne fait pas de commit, il suffit de mettre à jour une branche (qui est un pointeur sur un commit) pour pointer vers un commit différent. Le reste est juste des détails de ce qui arrive à votre index et à votre arbre de travail.

Cas d'utilisation

Je couvre de nombreux cas d'utilisation pour git reset dans mes descriptions des différentes options dans la section suivante. Il peut vraiment être utilisé pour une grande variété de choses; le dénominateur commun est que tous impliquent la réinitialisation de la branche, de l'index et / ou de l'arbre de travail pour pointer sur / correspondre à un commit donné.

Les choses à faire attention de

  • --hard peut vous faire perdre vraiment du travail. Il modifie votre arbre de travail.

  • git reset [options] commit peut vous amener à (en quelque sorte) perdre des commits. Dans l'exemple de jouet ci-dessus, nous avons perdu le commit C. Il est toujours dans le repo, et vous pouvez le trouver en regardant git reflog show HEAD ou git reflog show master, mais il n'est plus accessible à partir de n'importe quelle branche.

  • Git supprime définitivement ces commits après 30 jours, mais jusque-là, vous pouvez récupérer C en pointant à nouveau une branche (git checkout C; git branch <new branch name>).

Arguments

Paraphrasant la page de manuel, l'usage le plus commun est de la forme git reset [<commit>] [paths...], qui réinitialisera les chemins donnés à leur état à partir de la validation donnée. Si les chemins ne sont pas fournis, l'arbre entier est réinitialisé, et si le commit n'est pas fourni, il est considéré comme HEAD (le commit actuel). C'est un modèle commun à travers les commandes git (par exemple, checkout, diff, log, bien que la sémantique exacte varie), donc cela ne devrait pas être trop surprenant.

Par exemple, git reset other-branch path/to/foo réinitialise tout dans path / to / foo à son état dans other-branch, git reset -- .réinitialise le répertoire courant à son état dans HEAD, et un simple git reset réinitialise tout à son état dans HEAD.

L'arbre de travail principal et les options d'index

Il y a quatre options principales pour contrôler ce qui arrive à votre arbre de travail et votre index pendant la réinitialisation.

Rappelez-vous, l'index est "zone de mise en scène" git - c'est où les choses vont quand vous dites git add en préparation à commettre.

  • --hard fait tout correspondre à l'engagement que vous avez réinitialisé. C'est le plus facile à comprendre, probablement. Tous vos changements locaux sont bousculés. Une utilisation principale consiste à souffler votre travail mais pas de commuter les commits: git reset --hard veux dire git reset --hard HEAD, c'est-à-dire ne changez pas la branche mais supprimez tous les changements locaux. L'autre consiste simplement à déplacer une branche d'un endroit à un autre et à synchroniser l'index et l'arbre de travail. C'est celui qui peut vraiment vous faire perdre du travail, car il modifie votre arbre de travail. Soyez très sûr que vous voulez jeter le travail local avant de courir reset --hard.

  • --mixed est le défaut, c'est-à-dire git reset veux dire git reset --mixed. Il réinitialise l'index, mais pas l'arbre de travail. Cela signifie que tous vos fichiers sont intacts, mais toute différence entre le commit d'origine et celui que vous avez réinitialisé s'affichera sous forme de modifications locales (ou de fichiers non suivis) avec l'état git. Utilisez ceci quand vous vous rendez compte que vous avez fait de mauvais commits, mais vous voulez garder tout le travail que vous avez fait pour que vous puissiez le réparer et le réengager. Pour valider, vous devrez à nouveau ajouter des fichiers à l'index (git add ...).

  • --soft ne touche pas l'index ou arbre de travail. Tous vos fichiers sont intacts comme avec --mixed, mais tous les changements apparaissent comme changes to be committed avec le statut git (c'est-à-dire enregistré en préparation de l'engagement). Utilisez ceci quand vous vous rendez compte que vous avez fait quelques mauvais commits, mais le travail est tout bon - tout ce que vous devez faire est de le recommencer différemment. L'index est intact, donc vous pouvez commettre immédiatement si vous voulez - le commit résultant aura tout le même contenu que celui où vous étiez avant de réinitialiser.

  • --merge a été ajouté récemment et est destiné à vous aider à abandonner une fusion échouée. C'est nécessaire parce que git merge vous permettra en fait de tenter une fusion avec un arbre de travail sale (avec des modifications locales) tant que ces modifications sont dans des fichiers non affectés par la fusion. git reset --merge réinitialise l'index (comme --mixed - toutes les modifications apparaissent en tant que modifications locales), et réinitialise les fichiers affectés par la fusion, mais laisse les autres seuls. Nous espérons que tout sera restauré comme avant la fusion. Vous l'utiliserez généralement comme git reset --merge (sens git reset --merge HEAD) parce que vous voulez seulement réinitialiser la fusion, pas réellement déplacer la branche. (HEAD n'a pas encore été mis à jour, car la fusion a échoué)

    Pour être plus concret, supposons que vous ayez modifié les fichiers A et B, et que vous essayiez de fusionner dans une branche qui a modifié les fichiers C et D. La fusion échoue pour une raison quelconque, et vous décidez de l'abandonner. Tu utilises git reset --merge. Cela ramène C et D à la façon dont ils étaient HEAD, mais laisse vos modifications à A et B seuls, car ils ne faisaient pas partie de la tentative de fusion.

Veulent en savoir plus?

je pense man git reset est vraiment très bon pour cela - peut-être avez-vous besoin d'un peu d'idée de la façon dont git travaille pour eux. En particulier, si vous prenez le temps de les lire attentivement, ces tableaux détaillant les états des fichiers dans l'index et l'arbre de travail pour toutes les différentes options et cas sont très utiles. (Mais oui, ils sont très denses - ils véhiculent énormément de l'information ci-dessus dans une forme très concise.)

Notation étrange

La "notation étrange" (HEAD^ et HEAD~1) vous mentionnez est simplement un raccourci pour spécifier des commits, sans avoir à utiliser un nom de hachage comme 3ebe3f6. Il est entièrement documenté dans le section "Spécification des révisions" de la page man pour git-rev-parse, avec beaucoup d'exemples et syntaxe associée. Le signe et le tilde signifient réellement différentes choses:

  • HEAD~ est court pour HEAD~1 et signifie le premier parent du commit. HEAD~2 signifie le premier parent du premier parent du commit. Penser à HEAD~n comme "n commet avant HEAD" ou "l'ancêtre de la nième génération de HEAD".
  • HEAD^ (ou HEAD^1) signifie également le premier parent du commit. HEAD^2 signifie le commit seconde parent. Rappelez-vous, une validation de fusion normale a deux parents - le premier parent est le commit fusionné, et le second parent est le commit qui a été fusionné. En général, les fusions peuvent effectivement avoir arbitrairement beaucoup de parents (fusion de poulpes).
  • le ^ et ~ les opérateurs peuvent être enfilés ensemble, comme dans HEAD~3^2, le deuxième parent de l'ancêtre de troisième génération de HEAD, HEAD^^2, le deuxième parent du premier parent de HEAD, ou même HEAD^^^, ce qui équivaut à HEAD~3.

caret and tilde


880
2018-03-27 16:48



Rappelez-vous que dans git tu as:

  • la HEAD aiguille, qui vous indique sur quel commit vous travaillez
  • la arbre de travail, qui représente l'état des fichiers sur votre système
  • la zone de transit (appelé aussi indice), qui «met en scène» les changements afin qu'ils puissent ensuite être commis ensemble

Veuillez inclure des explications détaillées sur:

--hard, --soft et --merge;

En ordre croissant de danger-ness:

  • --soft se déplace HEAD mais ne touche pas la zone de transit ou l'arbre de travail.
  • --mixed se déplace HEAD et met à jour la zone de transit, mais pas l'arbre de travail.
  • --merge se déplace HEAD, réinitialise la zone de transfert et essaie de déplacer tous les changements dans votre arbre de travail dans le nouvel arbre de travail.
  • --hard se déplace HEAD  et ajuste votre zone de préparation et l'arbre de travail à la nouvelle HEAD, jetant tout.

cas d'utilisation concrets et workflows;

  • Utilisation --soft quand vous voulez passer à un autre commit et rafistoler les choses sans "perdre votre place". C'est assez rare que vous en ayez besoin.

-

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

-

  • Utilisation --mixed (qui est la valeur par défaut) lorsque vous voulez voir à quoi les choses ressemblent à un autre commit, mais vous ne voulez pas perdre les modifications que vous avez déjà.

  • Utilisation --merge lorsque vous souhaitez vous déplacer vers un nouvel emplacement, mais intégrer les modifications que vous avez déjà dans cet arbre de travail.

  • Utilisation --hard pour tout effacer et commencer une nouvelle ardoise au nouveau commit.


75
2018-03-27 17:08



La poste Réinitialiser démystifié dans le blog Pro Git donne un très sans l'ombre d'un doute explication sur git reset et git checkout.

Après toute la discussion utile en haut de ce post, l'auteur réduit les règles aux trois étapes simples suivantes:

C'est essentiellement ça. le reset La commande écrase ces trois arbres dans un ordre spécifique, en s'arrêtant quand vous le leur dites.

  1. Déplacez n'importe quelle branche HEAD vers (arrêtez si --soft)
  2. PUIS, faites que l'Index ressemble à ça (arrêtez ici à moins que --hard)
  3. PUIS, faites ressembler le répertoire de travail à ça

Il y a aussi --merge et --keep options, mais je préfère garder les choses plus simples pour le moment - ce sera pour un autre article.


33
2017-07-19 14:37



Lorsque vous commettez quelque chose à git, vous devez d'abord mettre en scène (ajouter à l'index) vos changements. Cela signifie que vous devez ajouter tous les fichiers que vous voulez inclure dans ce commit avant que git ne les considère comme faisant partie du commit. Jetons d'abord un coup d'oeil sur l'image d'un repo git: enter image description here

Donc, c'est simple maintenant. Nous devons travailler dans un répertoire de travail, créer des fichiers, des répertoires et tout. Ces modifications sont des modifications non suivies. Pour les faire suivre, nous devons les ajouter à git index en utilisant git ajouter commander. Une fois qu'ils sont ajoutés à l'index git. Nous pouvons maintenant valider ces changements, si nous voulons le pousser vers le dépôt git.

Mais tout à coup nous avons appris à savoir en validant que nous avons un fichier supplémentaire que nous avons ajouté dans l'index n'est pas nécessaire de pousser dans le dépôt git. Cela signifie que nous ne voulons pas que ce fichier soit indexé. Maintenant, la question est de savoir comment supprimer ce fichier de l'index git, Puisque nous avons utilisé git ajouter pour les mettre dans l'index, il serait logique d'utiliser git rm? Faux! git rm va simplement supprimer le fichier et ajouter la suppression à l'index. Alors que faire maintenant:

Utilisation:-

git reset

Il efface votre index, laisse votre répertoire de travail intact. (simplement tout déconnecter).

Il peut être utilisé avec un certain nombre d'options avec. Il y a trois options principales à utiliser avec git reset: --hard, --soft et --mixed. Ceux-ci affectent ce qui est réinitialisé en plus du pointeur HEAD lorsque vous réinitialisez.

Premier, --difficile réinitialise tout. Votre répertoire actuel serait exactement comme si vous suiviez cette branche depuis le début. Le répertoire de travail et l'index sont modifiés en ce commit. C'est la version que j'utilise le plus souvent. git reset --hard est quelque chose comme svn revert .

Ensuite, le contraire complet, -doux, ne réinitialise pas l'arbre de travail ni l'index. Il ne déplace que le pointeur HEAD. Cela laisse votre état actuel avec des changements différents de ceux du commit que vous passez en place dans votre répertoire, et "mis en scène" pour valider. Si vous effectuez un commit localement mais n'avez pas poussé le commit sur le serveur git, vous pouvez réinitialiser le commit précédent, et recommit avec un bon message de commit.

Finalement, --mixteréinitialise l'index, mais pas l'arbre de travail. Donc, les changements sont toujours là, mais sont "non-staging" et devraient être ajoutés ou git commit -a. Nous l'utilisons parfois si nous nous engageons plus que nous le voulions avec git commit -a, nous pouvons annuler le commit avec git reset --mixed, ajouter les choses que nous voulons commettre et juste les valider.

Différence entre git revert et git reset : -


En termes simples, git reset est une commande pour "corriger les erreurs non-motivées" et Git Revert est une commande pour "erreur corrigée".

Cela signifie que si nous avons fait une erreur dans un changement et engagé et poussé la même chose à git repo, alors Git Revert est la solution. Et si dans le cas où nous avons identifié la même erreur avant de pousser / commettre, nous pouvons utiliser git reset pour résoudre le problème.

J'espère que cela vous aidera à vous débarrasser de votre confusion.


22
2017-07-07 17:15



TL; DR

git reset réinitialise le transfert vers la dernière validation. Utilisation --hard pour réinitialiser également les fichiers dans votre répertoire de travail à la dernière validation.

VERSION PLUS LONGUE

Mais c'est évidemment simpliste d'où les nombreuses réponses plutôt verbeuses. Il était plus logique pour moi de lire sur git reset dans le contexte de l'annulation des changements. Par exemple. regarde ça:

Si git revert est un moyen "sûr" d'annuler les changements, vous pouvez penser à git   réinitialiser comme méthode dangereuse. Lorsque vous annulez avec git reset (et le   les commits ne sont plus référencés par aucun ref ou le reflog), il y a   aucun moyen de récupérer la copie d'origine - c'est une annulation permanente. Les soins doivent   être pris en utilisant cet outil, car c'est l'une des seules commandes Git qui a le potentiel de perdre votre travail.

De https://www.atlassian.com/git/tutorials/undoing-changes/git-reset 

et ça

Au niveau de la validation, la réinitialisation est un moyen de déplacer la pointe d'une branche vers un commit différent. Cela peut être utilisé pour supprimer des validations de la branche en cours.

De https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations 


6
2017-07-13 17:37



S'il vous plaît soyez conscient, ceci est une explication simplifiée destinée dans un premier temps à chercher à comprendre cette fonctionnalité complexe.

Peut être utile pour les apprenants visuels qui veulent visualiser à quoi ressemble leur état de 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 les choses de B et C en vert (mises en scène et prêtes à commettre)

git reset --mixed A (ou git reset A) et vous verrez les trucs de B et C en rouge (non mis en scène et prêt à être mis en scène (vert) et ensuite commis)

git reset --hard A et vous ne verrez plus les changements de B et C partout (ce sera comme s'ils n'avaient jamais existé)


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

git reset --soft A et vous verrez les choses de B et C dans la zone 'fichiers mis en scène' prêt à commettre

git reset --mixed A (ou git reset A) et vous verrez les choses de B et C dans la zone 'fichiers non stockés' prêts à être déplacés à mis en scène et ensuite commis

git reset --hard A et vous ne verrez plus les changements de B et C partout (ce sera comme s'ils n'avaient jamais existé)


2
2017-11-21 12:35



Il y a un très bon article pour expliquer Reset (inclure checkout / reverse et leur comparaison), j'espère que ça aide. https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/summary


1
2018-03-09 23:49