Réparer une tête détachée Git?

1455

Je faisais du travail dans mon référentiel et j'ai remarqué qu'un fichier avait des changements locaux. Je n'en voulais plus, j'ai donc supprimé le fichier, pensant pouvoir simplement en extraire une nouvelle copie. Je voulais faire l'équivalent Git de

svn up .

L'utilisation git pullne semblait pas fonctionner. Des recherches aléatoires m'ont conduit à un site où quelqu'un a recommandé de faire

git checkout HEAD^ src/

( srcest le répertoire contenant le fichier supprimé).

Maintenant, je découvre que j'ai la tête détachée. Je n'ai aucune idée de ce que c'est. Comment puis-je annuler?

Daniel
la source
69
git checkout mastervous ramènera sur la branche principale. Si vous vouliez effacer les modifications de copie de travail, vous vouliez probablement le faire git reset --hard.
Abe Voelker
si vous ne vous êtes pas engagé, vous auriez pu le fairegit checkout -- src/
signe d'été
Essayez ceci: lien . En brefcreate temp branch - checkout temp branch - checkout master - delete temp branch
fidev
@AbeVoelker Que vouliez-vous dire dans les commentaires de working copy changes? Faites-vous référence aux modifications que vous avez apportées aux fichiers après avoir extrait un autre commit (c'est-à-dire les modifications que vous avez apportées dans un état de tête détaché)?
Minh Tran

Réponses:

2149

Tête détachée signifie que vous n'êtes plus sur une branche, vous avez extrait un seul commit dans l'historique (dans ce cas, le commit précédent à HEAD, ie HEAD ^).

Si vous souhaitez supprimer vos modifications associées à la tête détachée

Vous avez seulement besoin de vérifier la branche où vous étiez, par exemple

git checkout master

La prochaine fois que vous avez modifié un fichier et que vous souhaitez le restaurer dans l'état où il se trouve dans l'index, ne supprimez pas le fichier en premier, faites simplement

git checkout -- path/to/foo

Cela restaurera le fichier foo dans l'état où il se trouve dans l'index.

Si vous souhaitez conserver vos modifications associées à la tête détachée

  1. Exécuter git branch tmp- cela enregistrera vos modifications dans une nouvelle branche appelée tmp.
  2. Courir git checkout master
  3. Si vous souhaitez intégrer les modifications que vous avez apportées master, exécutez à git merge tmppartir de la masterbranche. Vous devriez être sur la masterbranche après avoir couru git checkout master.
ralphtheninja
la source
6
"Cela restaurera le fichier foo dans l'état où il était avant que vous y apportiez des modifications." -> il le restaurera à l'état dans lequel il se trouve dans l' index - veuillez modifier
Mr_and_Mrs_D
88
Pourquoi cette erreur se produit-elle en premier lieu? C'est une des choses pour lesquelles je déteste le git - un comportement totalement aléatoire parfois. Jamais eu de tels problèmes avec Mercurial.
Violet Giraffe
97
@VioletGiraffe Ce n'est ni une erreur ni quelque chose d'aléatoire - c'est simplement l'état dans lequel se trouve votre référentiel lorsque vous extrayez un commit précédent. La «tête détachée» sert d'avertissement que vous pouvez également créer ou pointer vers une branche si vous avez l'intention de faire un travail à partir de ce point. Mais si vous souhaitez simplement afficher cette balise ou ce commit, il n'y a rien de mal à être dans un état de tête détaché.
Neil Neyman
22
Ne faites pas cela si vous vous êtes engagé sur la tête détachée, voir les autres réponses. Si c'est le cas, vous pouvez consulter les mentions précédentes de Head Git dansPrevious HEAD position was 7426948...
KCD
9
@VioletGiraffe: vous avez un modèle mental de ce qui se passe basé sur Mercurial, mais vous utilisez Git. Si vous ne souhaitez pas ajuster votre modèle mental pour l'adapter au modèle de Git, les choses continueront à apparaître de manière aléatoire. C'est comme si vous vous promeniez à l'extérieur avec des lunettes de réalité virtuelle et que vous pensez que vous pilotez un avion mais que vous traversez vraiment la rue. Tu vas te faire heurter par des voitures.
iconoclaste du
477

Si vous avez modifié des fichiers que vous ne voulez pas perdre, vous pouvez les pousser. Je les ai validés en mode détaché et après cela, vous pouvez passer à une branche temporaire pour l'intégrer plus tard dans master.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Extrait de:

Que faire avec la validation effectuée dans une tête détachée

Toni Gamez
la source
27
Je trouve que c'est la solution préférée - surtout si vous souhaitez conserver les modifications que vous avez apportées lorsque vous avez extrait la version individuelle.
adswebwork
10
@adswebwork: Je suis d'accord. Toutes les autres réponses suggèrent de revenir à un état précédent et de perdre les modifications apportées localement dans l'état de tête détachée.
Sk8erPeter
6
pourquoi pas git stash? Car c'est la première chose qui me vient à l'esprit. la création d'une nouvelle succursale sera une exagération.
signe d'été
2
vous pouvez également git rebase my-temporary-worksupprimer la branche git branch -d my-temporary-workafin qu'elle apparaisse comme si vous vous êtes engagé en premier lieu dans la bonne branche.
Zoltán
@geekay git stashsemble être l'outil parfait pour ce cas. Pourriez-vous s'il vous plaît écrire une réponse avec les étapes suggérées pour y parvenir?
Zoltán
157

Une solution sans créer de branche temporaire.

Comment quitter («réparer») l'état HEAD détaché lorsque vous avez déjà modifié quelque chose dans ce mode et, éventuellement, souhaitez enregistrer vos modifications:

  1. Validez les modifications que vous souhaitez conserver. Si vous souhaitez reprendre l'une des modifications que vous avez apportées dans l'état HEAD détaché, validez-les. Comme:

    git commit -a -m "your commit message"
    
  2. Ignorez les modifications que vous ne souhaitez pas conserver. La réinitialisation matérielle supprimera toutes les modifications non validées que vous avez apportées dans l'état HEAD détaché:

    git reset --hard
    

    (Sans cela, l'étape 3 échouerait, se plaignant des fichiers non validés modifiés dans le HEAD détaché.)

  3. Découvrez votre succursale. Quittez l'état HEAD détaché en vérifiant la branche sur laquelle vous avez travaillé auparavant, par exemple:

    git checkout master
    
  4. Reprenez vos engagements. Vous pouvez maintenant reprendre les commits que vous avez effectués dans l'état HEAD détaché par sélection à la cerise, comme indiqué dans ma réponse à une autre question .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
tanius
la source
Le git reset --hardétait exactement étais - je besoin, parce que je veux en amont comme la source et les changements locaux doivent être enlevés.
Markus Zeller
Grande réponse, cela a fonctionné pour moi
MGLondon
130

Tête détachée signifie:

  1. Vous n'êtes plus sur une succursale,
  2. Vous avez extrait un seul commit dans l'historique

Si vous n'avez aucun changement: vous pouvez passer en maître en appliquant la commande suivante

  git checkout master

Si vous souhaitez conserver des modifications:

Dans le cas d'un HEAD détaché, valide le travail comme d'habitude, sauf qu'aucune branche nommée n'est mise à jour. Pour obtenir la branche principale mise à jour avec vos modifications validées, créez une branche temporaire où vous vous trouvez (de cette façon, la branche temporaire aura toutes les modifications validées que vous avez apportées dans la tête détachée), puis basculez vers la branche principale et fusionnez la branche temporaire avec le maître.

git branch  temp
git checkout master
git merge temp
Razan Paul
la source
2
parfait, puis après supprimer la température de la branche
Davi Menezes
64

Voici ce que je viens de faire après avoir réalisé que j'étais sur une tête détachée et que j'avais déjà fait quelques changements.

J'ai commis les changements.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

Je me suis souvenu du hachage (1fe56ad) du commit. Ensuite, j'ai vérifié la branche où j'aurais dû être.

$ git checkout master
Switched to branch 'master'

Enfin, j'ai appliqué les modifications du commit à la branche.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

Je pense que c'est un peu plus facile que de créer une branche temporaire.

Philippe Gerber
la source
2
Cela devrait être la réponse. Il récupère vos fichiers nuked.
BlindWanderer
2
Oui, c'est vraiment la chose la plus simple à faire - assez simple à retenir sans chercher sur le Web la prochaine fois que cela se produit. Validez, notez le hachage, revenez à la branche dans laquelle vous vouliez vous engager et git cherry-pick <hash>.
Mason
Merci pour la solution. Cela a aidé. Puis-je également ajouter que je devais faire un "git push origin master" afin que mon maître et origin / master pointent vers le même commit.
turnip424
1
Il s'agit essentiellement de la réponse de tanius (publiée plus d'un an auparavant).
Peter Mortensen
Merci à ce joyeux choix de revenir sur les derniers changements de tête de détachement
Omega Cube
55

Si vous avez apporté quelques modifications, puis réalisé que vous étiez sur une tête détachée, il existe une solution simple pour cela: stash -> checkout master -> stash pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

Vous aurez vos modifications non validées et votre tête "attachée" normale, comme si rien ne s'était passé.

mojuba
la source
2
Ont mis en signet ce mauvais garçon - enregistre la création d'une branche temporaire. Travaillé un régal.
Tim Tyler
1
Je me retrouve souvent dans un état HEAD détaché après avoir vérifié un sous-module git, puis y avoir apporté des modifications. Je trouve que c'est la solution la meilleure et la plus simple pour réparer les choses afin que je puisse conserver mes modifications.
user5359531
1
Cela ne fonctionne pas si vous avez déjà validé des modifications dans un état détaché?
Danijel
40

Lorsque vous extrayez un commit spécifique git, vous vous retrouvez dans un état de tête détachée ... c'est-à-dire que votre copie de travail ne reflète plus l'état d'une référence nommée (comme "master"). Ceci est utile pour examiner l'état passé du référentiel, mais pas ce que vous voulez si vous essayez réellement d'annuler les modifications.

Si vous avez apporté des modifications à un fichier particulier et que vous souhaitez simplement les supprimer, vous pouvez utiliser la checkoutcommande comme ceci:

git checkout myfile

Cela annulera toutes les modifications non validées et ramènera le fichier à l'état qu'il a dans la tête de votre branche actuelle. Si vous souhaitez supprimer les modifications que vous avez déjà validées, vous pouvez utiliser la resetcommande. Par exemple, cela réinitialisera le référentiel à l'état de la validation précédente, ignorant toutes les modifications ultérieures:

git reset --hard HEAD^

Cependant, si vous partagez le référentiel avec d'autres personnes, un git resetpeut être perturbateur (car il efface une partie de l'historique du référentiel). Si vous avez déjà partagé des modifications avec d'autres personnes, vous voulez généralement regarder à la git revertplace, ce qui génère un "anticommit" - c'est-à-dire qu'il crée un nouveau commit qui "annule" les modifications en question.

Le Git Book contient plus de détails.

larsks
la source
1
Comme je l'ai dit dans la réponse de @ ralphtheninja, git checkout path/to/foopourrait entrer en conflit avec git checkout some-branch, il serait donc préférable d'utiliser git checkout -- path/to/foopour éviter ces conflits.
Diego Lago
30

HEAD est dans un pointeur, et en conséquence, il pointe - directement ou indirectement - vers un commit particulier:

  HEAD attaché signifie qu'il est attaché à une branche (c'est-à-dire qu'il pointe vers une branche).
Détaché un moyen de tête qu'il est pas attaché à une branche, à savoir qu'il pointe directement à certains commettras.

entrez la description de l'image ici

En d'autres termes:

  • S'il pointe directement sur un commit , le HEAD est détaché .
  • S'il pointe indirectement sur un commit (c'est-à-dire qu'il pointe sur une branche qui, à son tour, pointe sur un commit), le HEAD est attaché .

Pour mieux comprendre les situations avec HEAD attaché / détaché, montrons les étapes menant au quadruplet d'images ci-dessus.

Nous commençons avec le même état du référentiel (les images dans tous les quadrants sont les mêmes):

entrez la description de l'image ici


Maintenant, nous voulons effectuer git checkout- avec différentes cibles dans les images individuelles (les commandes au-dessus d'eux sont grisées pour souligner que nous allons seulement appliquer ces commandes):

entrez la description de l'image ici


Telle est la situation après avoir exécuté ces commandes:

entrez la description de l'image ici

Comme vous pouvez le voir, la HEAD pointe vers la cible dugit checkout commande - vers une branche (les 3 premières images du quadruplet), ou (directement) vers un commit (la dernière image du quadruplet).

Le contenu du répertoire de travail est également modifié pour être conforme à la validation appropriée (instantané), c'est-à-dire à la validation pointée (directement ou indirectement) par la HEAD.


Nous sommes donc maintenant dans la même situation qu'au début de cette réponse:

entrez la description de l'image ici

MarianD
la source
6
Je ne l'ai pas lu, mais j'ai voté pour les jolies photos que vous avez faites;).
Carlo Wood
@Carlo, merci!
MarianD
22

Puisque "état de tête détaché" vous a sur une branche temporaire, utilisez simplement git checkout -ce qui vous place sur la dernière branche sur laquelle vous étiez.

Mike
la source
1
soyez prudent, vous perdrez tous les commits que vous avez faits lorsque vous étiez en état de tête détachée.
Ajak6
@ Ajak6 Vous ne perdez pas vraiment ces commits. Ils sont toujours disponibles via git refloget peuvent être repris dans une nouvelle agence ou via git cherry-pickune agence existante. Voir cette question .
tanius
7

Pour clarifier davantage la réponse de @Philippe Gerber, la voici:

git cherry-pick

Avant cherry-pick, un git checkout masterest nécessaire dans ce cas. De plus, il n'est nécessaire qu'avec un commitin detached head.

Timo
la source
6

Addenda

Si la succursale dans laquelle vous souhaitez retourner était le dernier paiement que vous avez effectué, vous pouvez simplement utiliser checkout @{-1}. Cela vous ramènera à votre paiement précédent.

En outre, vous pouvez alias cette commande avec, par exemple, de git global --config alias.prevsorte que vous avez juste besoin de taper git prevpour revenir à la caisse précédente.

David Brower
la source
4

Être en "tête détachée" signifie que HEAD fait référence à un commit spécifique sans nom (par opposition à une branche nommée) (cf: https://git-scm.com/docs/git-checkout section Tête détachée )

Pour résoudre le problème, il vous suffit de sélectionner la branche qui a été sélectionnée auparavant par

git checkout @{-1}

Tapoter. ANDRIA
la source
2

Lorsque vous êtes dans une situation de tête détachée et que vous avez créé de nouveaux fichiers, assurez-vous d'abord que ces nouveaux fichiers sont ajoutés à l'index, par exemple avec:

git add .

Mais si vous avez seulement modifié ou supprimé des fichiers existants, vous pouvez ajouter (-a) et valider avec un message (-m) en même temps via:

git commit -a -m "my adjustment message"

Ensuite, vous pouvez simplement créer une nouvelle branche avec votre état actuel avec:

git checkout -b new_branch_name

Vous aurez une nouvelle branche et tous vos ajustements seront là dans cette nouvelle branche. Vous pouvez ensuite continuer à pousser vers la télécommande et / ou à commander / tirer / fusionner à votre guise.

DZet
la source
1

Git m'a dit comment faire.

si vous avez tapé:

git checkout <some-commit_number>

Enregistrez le statut

git add .
git commit -m "some message"

Alors:

 git push origin HEAD:<name-of-remote-branch>
Sterling Diaz
la source
1

Je voulais garder mes changements donc je corrige ça

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

ça marche pour moi

CRLZXO
la source
1

Pointe normalement HEADsur une branche. Quand il ne pointe pas vers une branche à la place quand il pointe vers un hachage de validation comme 69e51cela signifie que vous avez un HEAD détaché. Vous devez pointer deux branches pour résoudre le problème. Vous pouvez faire deux choses pour y remédier.

  1. git checkout other_branch // Impossible lorsque vous avez besoin du code dans ce commit hash
  2. créez une nouvelle branche et pointez le hachage de validation sur la branche nouvellement créée.

HEAD doit pointer vers une branche, pas un hachage de validation est la règle d'or.

Krishnadas PC
la source
c'est pourquoi j'ai eu cette même erreur. J'ai extrait une révision, puis extrait à nouveau la révision actuelle / la plus récente au lieu de passer à la branche, qui aurait correctement attaché la tête. Merci pour l'aide.
Rahul Thakur
1

Une tête détachée signifie que vous n'avez pas extrait correctement votre branche ou que vous venez d'extraire un seul commit.

Si vous rencontrez un tel problème, stockez d' abord vos modifications locales afin de ne pas les perdre.

Après cela ... passez à la caisse de votre choix à l'aide de la commande:

Disons que vous voulez une branche MyOriginalBranch:

git checkout -b someName origin / MyOriginalBranch

Dhirendra Gautam
la source
1

vous l'avez probablement fait git reset --hard origin/your-branch .

Essayez de juste git checkout your-branch

Johnny Cage
la source
0
git pull origin master

travaillé pour moi. Il s'agissait simplement de donner explicitement le nom de la télécommande et de la branche.

Amjedonline
la source
0

Dans mon cas, je cours git status et j'ai vu que j'avais quelques fichiers non suivis sur mon répertoire de travail.

Je devais juste les nettoyer (car je n'en avais pas besoin) pour exécuter le rebase que je voulais effectuer.

falsarella
la source
0

Cela fonctionne pour moi, il attribuera une nouvelle branche pour la tête détachée:

git checkout nouveau_nom_branché détaché_tête_garbage_nom

Alok Gupta
la source
0

Le HEAD détaché signifie que vous n'êtes actuellement sur aucune branche. Si vous souhaitez conserver vos modifications actuelles et simplement créer une nouvelle branche, voici ce que vous faites:

git commit -m "your commit message"
git checkout -b new_branch

Par la suite, vous pouvez potentiellement fusionner cette nouvelle branche avec d'autres branches. La commande git "a dog" est toujours utile :

git log --all --decorate --oneline --graph
gebbissimo
la source