Je suis nouveau dans les complexités de branchement de Git. Je travaille toujours sur une seule branche et je valide les modifications, puis je pousse périodiquement vers mon origine distante.
Quelque part récemment, j'ai effectué une réinitialisation de certains fichiers pour les retirer de la validation des validations, puis plus tard rebase -i
pour supprimer quelques validations locales récentes. Maintenant, je suis dans un état que je ne comprends pas très bien.
Dans ma zone de travail, git log
montre exactement ce à quoi je m'attendais - je suis dans le bon train avec les commits que je ne voulais pas disparaître, et les nouveaux là-bas, etc.
Mais je viens de pousser vers le référentiel distant, et ce qui est différent - quelques commits que j'avais tués dans le rebase ont été poussés, et les nouveaux commis localement ne sont pas là.
Je pense que "master / origin" est détaché de HEAD, mais je ne suis pas sûr à 100% de ce que cela signifie, comment le visualiser avec les outils de ligne de commande et comment le corriger.
I did a reset of some files to get them out of commit staging
partie? désolé pour les questions :)Réponses:
Tout d'abord, clarifions ce qu'est HEAD et ce qu'il signifie lorsqu'il est détaché.
HEAD est le nom symbolique du commit actuellement extrait. Lorsque HEAD n'est pas détaché (situation «normale» 1 : vous avez extrait une branche), HEAD pointe en fait vers le «ref» d'une branche et la branche pointe vers le commit. HEAD est ainsi «attaché» à une succursale. Lorsque vous effectuez un nouveau commit, la branche vers laquelle pointe HEAD est mise à jour pour pointer vers le nouveau commit. HEAD suit automatiquement car il pointe simplement vers la branche.
git symbolic-ref HEAD
rendementsrefs/heads/master
La branche nommée «master» est extraite.
git rev-parse refs/heads/master
yield17a02998078923f2d62811326d130de991d1a95a
Ce commit est la pointe ou la «tête» actuelle de la branche principale.
git rev-parse HEAD
donne aussi17a02998078923f2d62811326d130de991d1a95a
C'est ce que signifie être un «ref symbolique». Il pointe vers un objet via une autre référence.
(Les références symboliques ont été initialement implémentées sous forme de liens symboliques, mais ont ensuite été transformées en fichiers simples avec une interprétation supplémentaire afin de pouvoir être utilisées sur des plates-formes qui n'ont pas de liens symboliques.)
Nous avons
HEAD
→refs/heads/master
→17a02998078923f2d62811326d130de991d1a95a
Lorsque HEAD est détaché, il pointe directement vers une validation, au lieu de pointer indirectement vers celle-ci via une branche. Vous pouvez penser à une TÊTE détachée comme étant sur une branche sans nom.
git symbolic-ref HEAD
échoue avecfatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
renvoie17a02998078923f2d62811326d130de991d1a95a
Comme il n'est pas une référence symbolique, il doit pointer directement vers le commit lui-même.
Nous avons
HEAD
→17a02998078923f2d62811326d130de991d1a95a
La chose importante à retenir avec une HEAD détachée est que si la validation vers laquelle elle pointe n'est pas référencée (aucune autre référence ne peut l'atteindre), elle deviendra alors "suspendue" lorsque vous retirerez une autre validation. Finalement, ces validations pendantes seront élaguées via le processus de collecte des ordures (par défaut, elles sont conservées pendant au moins 2 semaines et peuvent être conservées plus longtemps en étant référencées par le reflog de HEAD).
1 Il est tout à fait correct de faire un travail «normal» avec une TETE détachée, il vous suffit de garder une trace de ce que vous faites pour éviter d'avoir à repasser l'historique perdu du reflog.
Les étapes intermédiaires d'un rebase interactif se font avec une TETE détachée (en partie pour éviter de polluer le reflog de la branche active). Si vous terminez l'opération de rebase complète, il mettra à jour votre branche d'origine avec le résultat cumulé de l'opération de rebase et rattachera HEAD à la branche d'origine. Je suppose que vous n'avez jamais complètement terminé le processus de rebase; cela vous laissera une HEAD détachée pointant vers la validation qui a été traitée le plus récemment par l'opération de rebase.
Pour récupérer de votre situation, vous devez créer une branche qui pointe vers la validation actuellement pointée par votre HEAD détaché:
(ces deux commandes peuvent être abrégées en
git checkout -b temp
)Cela rattachera votre HEAD à la nouvelle
temp
branche.Ensuite, vous devez comparer le commit actuel (et son historique) avec la branche normale sur laquelle vous vous attendiez à travailler:
(Vous voudrez probablement expérimenter avec les options de journal: ajouter
-p
, laisser de côté--pretty=…
pour voir le message de journal entier, etc.)Si votre nouvelle
temp
branche semble bonne, vous voudrez peut-être mettre à jour (par exemple)master
pour la signaler:(ces deux commandes peuvent être abrégées en
git checkout -B master temp
)Vous pouvez ensuite supprimer la branche temporaire:
Enfin, vous voudrez probablement pousser l'histoire rétablie:
Vous devrez peut-être ajouter
--force
à la fin de cette commande pour pousser si la branche distante ne peut pas être «accélérée» vers le nouveau commit (c'est-à-dire que vous avez abandonné, ou réécrit un commit existant, ou sinon réécrit un peu d'histoire).Si vous étiez au milieu d'une opération de rebase, vous devriez probablement la nettoyer. Vous pouvez vérifier si un rebase était en cours en recherchant le répertoire
.git/rebase-merge/
. Vous pouvez nettoyer manuellement le rebasage en cours en supprimant simplement ce répertoire (par exemple, si vous ne vous souvenez plus du but et du contexte de l'opération de rebase active). Habituellement, vous utiliseriezgit rebase --abort
, mais cela fait une réinitialisation supplémentaire que vous voulez probablement éviter (il ramène HEAD à la branche d'origine et le réinitialise au commit d'origine, ce qui annulera une partie du travail que nous avons fait ci-dessus).la source
man git-symbolic-ref
: "Dans le passé,.git/HEAD
était un lien symbolique pointant versrefs/heads/master
. Lorsque nous voulions passer à une autre branche, nous l'avons faitln -sf refs/heads/newbranch .git/HEAD
, et quand nous voulions savoir sur quelle branche nous nous trouvions, nous l'avons faitreadlink .git/HEAD
. Mais les liens symboliques ne sont pas entièrement portables , ils sont donc désormais obsolètes et les références symboliques (comme décrit ci-dessus) sont utilisées par défaut. "git branch -f master HEAD && git checkout master
est suffisant - en supposant que votre objectif est de garder votre tête actuelle mais de la désigner commemaster
. D'autres objectifs ont également un sens et appellent d'autres recettes.Faites juste ceci:
Ou, si vous souhaitez conserver des modifications, procédez comme suit:
la source
git reset
devrait venir avec un avertissement "Si vous n'avez aucune idée de ce que vous faites, arrêtez-le". Je viens de me remettre d'une heure de terreur en pensant que j'avais perdu la dernière semaine de travail. Merci!J'ai rencontré ce problème et quand j'ai lu la réponse la plus votée:
J'ai pensé: Ah-ha! Si
HEAD
est le nom symbolique du commit de paiement actuel, je peux le réconciliermaster
en le rebasant contremaster
:Cette commande:
master
HEAD
revenir au pointHEAD
divergé demaster
master
Le résultat final est que tous les commits qui étaient dans
HEAD
mais pas lemaster
sont égalementmaster
.master
reste vérifié.Concernant la télécommande:
L'historique distant ne peut plus être avancé rapidement à l'aide de votre historique local. Vous devrez forcer-push (
git push -f
) pour écraser l'historique distant. Si vous avez des collaborateurs, il est généralement judicieux de coordonner cela avec eux afin que tout le monde soit sur la même page.Après avoir poussé
master
à distanceorigin
, votre branche de suivi à distanceorigin/master
sera mise à jour pour pointer vers le même commit quemaster
.la source
git reflog
avec lequel vous souhaitez réinitialiser votre branche, puis réinitialisez votre branche avec ce commit avecgit rest —hard $commit
Regardez ici pour une explication de base de la tête détachée:
http://git-scm.com/docs/git-checkout
Ligne de commande pour le visualiser:
ou
vous obtiendrez une sortie comme ci-dessous:
Les
* (no branch)
spectacles que vous êtes en tête détachée.Vous auriez pu arriver à cet état en faisant un
git checkout somecommit
etc. et cela vous aurait averti de ce qui suit:Maintenant, pour les mettre sur le maître:
Faites un
git reflog
ou même justegit log
et notez vos commits. Maintenantgit checkout master
etgit merge
les commits.Éditer:
Pour ajouter, utilisez
git rebase -i
non seulement pour supprimer / tuer les commits dont vous n'avez pas besoin, mais aussi pour les modifier. Il vous suffit de mentionner «modifier» dans la liste de validation et vous pourrez modifier votre validation, puis émettre ungit rebase --continue
pour continuer. Cela aurait garanti que vous ne veniez jamais dans une tête détachée.la source
Obtenez votre commit détaché sur sa propre branche
Courez simplement
git checkout -b mynewbranch
.Ensuite, exécutez
git log
et vous verrez que la validation est maintenantHEAD
sur cette nouvelle branche.la source
mynewbranch
rattache-t-il à quelque chose?si vous venez de créer une branche principale et que vous souhaitez revenir au "développement" ou à une fonctionnalité, procédez comme suit:
Remarque: vérifier l' origine / développer .
Vous êtes dans un état HEAD détaché . Vous pouvez regarder autour de vous, apporter des modifications expérimentales et les valider, et vous pouvez annuler toutes les validations que vous effectuez dans cet état sans impact sur les branches en effectuant une autre extraction ...
puis
Ça marche :)
la source
Si vous voulez pousser votre HEAD détachée actuelle (cochez
git log
avant), essayez:pour envoyer votre HEAD détaché dans la branche principale à l'origine. Si votre push est rejeté, essayez d'
git pull origin master
abord d'obtenir les modifications depuis l'origine. Si vous ne vous souciez pas des modifications par rapport à l'origine et qu'elles sont rejetées, car vous avez effectué un rebase intentionnel et que vous souhaitez remplacer origin / master par votre branche actuellement détachée - vous pouvez alors la forcer (-f
). Si vous avez perdu l'accès aux validations précédentes, vous pouvez toujours exécutergit reflog
pour voir l'historique de toutes les branches.Pour revenir sur une branche principale, tout en conservant les modifications, essayez les commandes suivantes:
Voir: Git: "Pas actuellement sur aucune branche." Existe-t-il un moyen simple de revenir sur une branche, tout en conservant les modifications?
la source
J'ai trouvé cette question lors de la recherche
You are in 'detached HEAD' state.
Après avoir analysé ce que j'avais fait pour arriver ici, par rapport à ce que j'avais fait dans le passé, j'ai découvert que j'avais fait une erreur.
Mon débit normal est:
Cette fois, j'ai fait:
Le problème est que j'ai accidentellement fait:
Plutôt que:
Le correctif (dans ma situation) consistait simplement à exécuter la commande ci-dessus, puis à continuer le flux:
la source
Les éléments suivants ont fonctionné pour moi (en utilisant uniquement le maître de branche):
Le premier pousse la tête détachée à l'origine distante.
Le second passe au maître de branche.
Le troisième récupère la TETE qui s'attache au maître de branche.
Des problèmes peuvent survenir à la première commande si le push est rejeté. Mais cela ne serait plus un problème de tête détachée, mais concerne le fait que la tête détachée n'est pas au courant de certains changements à distance.
la source
Je viens de rencontrer ce problème aujourd'hui et je suis presque sûr de l'avoir résolu en faisant:
J'étais sur mon ordinateur de travail lorsque j'ai compris comment faire cela, et maintenant je rencontre le même problème sur mon ordinateur personnel. Il faudra donc attendre jusqu'à lundi quand je serai de retour à l'ordinateur de travail pour voir exactement comment je l'ai fait.
la source
Si vous êtes absolument sûr que HEAD est en bon état:
Vous ne pouvez probablement pas pousser à l'origine, car votre maître a divergé de l'origine. Si vous êtes sûr que personne d'autre n'utilise le dépôt, vous pouvez forcer:
Plus utile si vous êtes sur une branche de fonctionnalité que personne d'autre n'utilise.
la source
Tout ce que vous avez à faire est «git checkout [nom-branche]» où [nom-branche] est le nom de la branche d'origine à partir de laquelle vous êtes entré dans un état de tête détaché. Le (détaché de asdfasdf) disparaîtra.
Ainsi, par exemple, dans la branche «dev», vous extrayez le commit asdfasd14314 ->
vous êtes maintenant dans un état de tête détaché
'git branch' affichera quelque chose comme ->
mais pour sortir de l'état de tête détaché et revenir au dev ->
puis 'git branch' listera ->
mais c'est bien sûr si vous n'avez pas l'intention de conserver des modifications par rapport à l'état de tête détachée mais je me retrouve à faire cela beaucoup pas l'intention de faire des changements mais juste de regarder un commit précédent
la source
Comme l'a souligné Chris, j'ai eu la situation suivante
git symbolic-ref HEAD
échoue avecfatal: ref HEAD is not a symbolic ref
Cependant
git rev-parse refs/heads/master
, pointait vers un bon commit d'où je pouvais récupérer (dans mon cas, le dernier commit et vous pouvez le voir en utilisantgit show [SHA]
J'ai fait beaucoup de choses désordonnées après cela, mais ce qui semble avoir été réparé est juste,
git symbolic-ref HEAD refs/heads/master
Et la tête est re-attachée!
la source
Au lieu de faire
git checkout origin/master
fais juste
git checkout master
puis
git branch
confirmera votre succursale.la source
J'ai eu ce problème aujourd'hui, où j'avais mis à jour un sous-module, mais je n'étais sur aucune branche. Je m'étais déjà engagé, donc le stockage, le paiement, le stockage ne fonctionneraient pas. J'ai fini par choisir le commit de la tête détachée. Donc, immédiatement après avoir commis (lorsque la poussée a échoué), j'ai fait:
Ma pensée est allée: je suis sur une tête détachée, mais je veux être maître. En supposant que mon état détaché ne soit pas très différent de master, si je pouvais appliquer mon commit à master, je serais défini. C'est exactement ce que fait la sélection.
la source
Si vous avez fait quelques commits au-dessus du master et que vous voulez juste "fusionner en arrière"
master
là-bas (c'est-à-dire que vous voulezmaster
pointerHEAD
), le one-liner serait:master
, même si elle existe déjà (ce qui revient à se déplacermaster
et c'est ce que nous voulons).HEAD
, où vous êtes.master
suite.J'ai trouvé cela particulièrement utile dans le cas des sous-référentiels, qui se trouvent également être dans un état détaché assez souvent.
la source
J'ai eu le même problème et je l'ai résolu en suivant les étapes suivantes.
Si vous devez conserver vos modifications
git checkout master
commande pour vous remettre dans la branche principale.git checkout -b changes
etgit checkout -B master changes
Si vous n'avez pas besoin de vos modifications
Pour supprimer tous les fichiers non suivis de votre exécution de branche
git clean -df
.Ensuite, vous devez effacer toutes les modifications non mises en scène dans votre référentiel. Pour ce faire, vous devez exécuter
git checkout --
Enfin, vous devez remettre votre branche dans la branche principale en utilisant la
git checkout master
commande.la source
Pour moi, c'était aussi simple que de supprimer à nouveau la branche locale, car je n'avais pas de commits locaux que je voulais pousser:
J'ai donc fait:
Et puis vérifier à nouveau la branche:
la source
Lorsque je me trouve personnellement dans une situation où il s'avère que j'ai apporté des modifications alors que je ne suis pas
master
(c'estHEAD
-à- dire détaché juste au-dessus dumaster
et il n'y a pas de commits entre les deux), le stockage peut aider:la source
En termes simples, l'état HEAD détaché signifie que vous n'êtes pas extrait de HEAD (ou tip) d'une branche .
Comprendre avec un exemple
Dans la plupart des cas, une branche est une séquence de plusieurs validations comme:
Commit 1: master -> branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)
Commit 2: master -> 123be6a76168aca712aea16076e971c23835f8ca -> branch_HEAD (100644a76168aca712aea16076e971c23835f8ca)
Comme vous pouvez le voir ci-dessus en cas de séquence de validations, votre branche pointe vers votre dernière validation. Donc, dans ce cas, si vous réglez pour valider 123be6a76168aca712aea16076e971c23835f8ca, vous serez alors en état de tête détachée puisque HEAD de votre branche pointe vers 100644a76168aca712aea16076e971c23835f8ca et techniquement, vous êtes vérifié à HEAD d'aucune agence. Par conséquent, vous êtes dans l'état HEAD détaché.
Explication théorique
Dans ce blog, il indique clairement qu'un référentiel Git est un arbre de validations, chaque validation pointant vers son ancêtre avec chaque pointeur de validation est mis à jour et ces pointeurs vers chaque branche sont stockés dans les sous-répertoires .git / refs. Les balises sont stockées dans .git / refs / tags et les branches sont stockées dans .git / refs / heads. Si vous regardez l'un des fichiers, vous trouverez que chaque balise correspond à un seul fichier, avec un hachage de validation de 40 caractères et comme expliqué ci-dessus par @Chris Johnsen et @Yaroslav Nikitenko, vous pouvez consulter ces références.
la source
Je me suis retrouvé dans un état vraiment idiot, je doute que quelqu'un d'autre le trouve utile ... mais juste au cas où
que j'ai finalement fixé avec
la source
Cela a parfaitement fonctionné pour moi:
1.
git stash
pour enregistrer vos modifications localesSi vous souhaitez
git clean -df
git checkout -- .
supprimer les modifications, git clean supprime tous les fichiers non suivis (avertissement: bien qu'il ne supprime pas les fichiers ignorés mentionnés directement dans .gitignore, il peut supprimer les fichiers ignorés résidant dans les dossiers) et git checkout efface toutes les modifications non mises en scène.
2.
git checkout master
pour passer à la branche principale (en supposant que vous voulez utiliser master)3.
git pull
pour tirer le dernier commit de la branche master4.
git status
afin de vérifier que tout a l'air bienla source
Dans mon cas, j'ai couru
git status
et j'ai vu que j'avais quelques fichiers non suivis dans mon répertoire de travail.Pour que le rebase fonctionne, je devais juste les nettoyer (car je n'en avais pas besoin).
la source
Si vous utilisez EGit dans Eclipse: supposez que votre maître est votre principale branche de développement
Après cela, vous devriez pouvoir vous rattacher au maître d'origine.
la source
J'ai eu le même problème. J'ai caché mes modifications avec
git stash
et réinitialisé la branche en local sur un commit précédent (je pensais que cela avait causé cela), puisgit pull
j'ai fait un et je ne détache pas cette tête maintenant. N'oubliez pasgit stash apply
d'avoir à nouveau vos modifications.la source
la source