Hoe repareer ik een Git losstaand hoofd?

Ik was wat aan het werk in mijn repository en merkte dat een bestand lokale wijzigingen had. Ik wilde ze niet meer, dus ik heb het bestand verwijderd, denkend dat ik gewoon een nieuwe kopie kan afrekenen. Ik wilde het Git-equivalent van

. doen

svn up .

Het gebruik van git pullleek niet te werken. Wat willekeurig zoeken leidde me naar een site waar iemand aanraadde om te doen

git checkout HEAD^ src/

(srcis de map met het verwijderde bestand).

Nu kom ik erachter dat ik een losstaand hoofd heb. Ik heb geen idee wat dat is. Hoe kan ik het ongedaan maken?


Antwoord 1, autoriteit 100%

Detached head betekent dat je niet langer op een branch zit, je hebt een enkele commit in de geschiedenis uitgecheckt (in dit geval de commit voorafgaand aan HEAD, d.w.z. HEAD^).

Als u uw wijzigingen wilt verwijderendie zijn gekoppeld aan de losgemaakte HEAD

Je hoeft alleen af te rekenen in het filiaal waar je zat, bijvoorbeeld

git checkout master

De volgende keer dat u een bestand hebt gewijzigd en het wilt herstellen naar de staat waarin het zich in de index bevindt, moet u het bestand niet eerst verwijderen, maar gewoon doen

git checkout -- path/to/foo

Dit zal het bestand foo herstellen naar de staat waarin het zich in de index bevindt.

Als u uw wijzigingen behoudendie zijn gekoppeld aan de losgemaakte HEAD

  1. Voer git branch tmpuit – dit slaat je wijzigingen op in een nieuwe branch genaamd tmp.
  2. Voer git checkout master
  3. uit

  4. Als je de wijzigingen die je hebt gemaakt in masterwilt opnemen, voer je git merge tmpuit vanuit de branch master. Je zou in de masterbranch moeten zijn na het uitvoeren van git checkout master.

Antwoord 2, autoriteit 21%

Als je bestanden hebt gewijzigd die je niet wilt verliezen, kun je ze pushen. Ik heb ze in de detached-modus vastgelegd en daarna kun je naar een tijdelijke branch gaan om later in master te integreren.

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

Geëxtraheerd uit:

Wat te doen met commit gemaakt in een vrijstaande kop


Antwoord 3, autoriteit 7%

Een oplossing zonder een tijdelijke vestiging te maken.

Hoe u de losgemaakte HEAD-status kunt afsluiten (“repareren”) wanneer u al iets in deze modus hebt gewijzigden, optioneel, uw wijzigingen wilt opslaan:

  1. Voeg wijzigingen door die u wilt behouden.Als u een van de wijzigingen die u in de vrijstaande HEAD-status hebt aangebracht, wilt overnemen, moet u ze vastleggen. Vind ik leuk:

    git commit -a -m "your commit message"
    
  2. Wijzigingen negeren die u niet wilt behouden.De harde reset verwijdert alle niet-vastgelegde wijzigingen die u in de ontkoppelde HEAD-status heeft aangebracht:

    git reset --hard
    

    (Zonder dit zou stap 3 mislukken, klagen over gewijzigde niet-vastgelegde bestanden in de losgemaakte HEAD.)

  3. Bekijk je filiaal.Verlaat de vrijstaande HEAD-status door het filiaal waar je eerder aan hebt gewerkt te bekijken, bijvoorbeeld:

    git checkout master
    
  4. Neem je commits over.Je kunt nu de commits die je hebt gemaakt in de vrijstaande HEAD-status overnemen door cherry-picking, zoals getoond in mijn antwoord op een andere vraag.

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    

Antwoord 4, autoriteit 6%

Vrijstaande kop betekent:

  1. Je zit niet meer op een filiaal,
  2. Je hebt een enkele commit in de geschiedenis uitgecheckt

Als je geen wijzigingen hebt:je kunt overschakelen naar master door de volgende opdracht toe te passen

 git checkout master

Als u wijzigingen heeft die u wilt behouden:

In het geval van een ontkoppelde HEAD, werken commits zoals normaal, behalve dat geen benoemde branch wordt bijgewerkt. Om de master branch bijgewerkt te krijgen met je vastgelegde wijzigingen, maak je een tijdelijke branch waar je bent (op deze manier heeft de tijdelijke branch alle de vastgelegde wijzigingen die je hebt aangebracht in de ontkoppelde HEAD), schakel dan over naar de master-branch en merge de tijdelijke branch met de master.

git branch  temp
git checkout master
git merge temp

Antwoord 5, autoriteit 3%

HEAD is een pointer, en het wijst — direct of indirect— naar een bepaalde commit:

Bijgevoegd  HEAD betekent dat het is gekoppeld aan een tak(d.w.z. het wijstnaar een tak).
DetachedHEAD betekent dat het nietis gekoppeld aan een branch, d.w.z. het verwijst directnaar een commit.

voer hier de afbeeldingsbeschrijving in

Met andere woorden:

  • Als het verwijst naar een commit direct, is de HEAD losgemaakt.
  • Als het indirectnaar een commit wijst (dwz het verwijst naar een branch, die op zijn beurt naar een commit wijst), is de HEAD bijgevoegd.

Laten we, om situaties met bevestigde/losgemaakte HEAD beter te begrijpen, de stappen laten zien die leiden naar het viertal afbeeldingen hierboven.

We beginnen met dezelfde staat van de repository (afbeeldingen in alle kwadranten zijn hetzelfde):

voer hier de afbeeldingsbeschrijving in


Nu willen we git checkoutuitvoeren — met verschillende doelen in de individuele afbeeldingen (commando’s erboven worden gedimd weergegeven om te benadrukken dat we alleen die gaantoepassen commando’s):

voer hier de afbeeldingsbeschrijving in


Dit is de situatie nahet uitvoeren van deze commando’s:

voer hier de afbeeldingsbeschrijving in

Zoals je kunt zien, wijst de HEAD naar het doelvan het git checkoutcommando — naar een tak(eerste 3 afbeeldingen van de quadruplet), of (direct) aan een commit(de laatste afbeelding van de quadruplet).

De inhoud van de werkdirectory wordt ook gewijzigd om in overeenstemming te zijn met de juiste commit (snapshot), d.w.z. met de commit die (direct of indirect) door de HEAD wordt verwezen.


Dus nu bevinden we ons in dezelfde situatie als aan het begin van dit antwoord:

voer hier de afbeeldingsbeschrijving in


Antwoord 6, autoriteit 3%

Dit is wat ik net deed nadat ik me realiseerde dat ik een afstandelijk hoofd had en al enkele wijzigingen had aangebracht.

Ik heb de wijzigingen doorgevoerd.

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

Ik herinnerde me de hash (1fe56ad) van de commit. Toen heb ik het filiaal bekeken waar ik had moeten zijn.

$ git checkout master
Switched to branch 'master'

Eindelijk heb ik de wijzigingen van de commit toegepast op de branch.

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

Ik denk dat dit een beetje makkelijker is dan het maken van een tijdelijke branch.


Antwoord 7, autoriteit 3%

Als je wijzigingen hebt aangebracht en je realiseert je dat je op een afstandelijk hoofd zit, kun je het volgende doen: stash -> kassa-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'

Je hebt je niet-vastgelegde wijzigingen en je normale “bijgevoegde” HEAD, alsof er niets is gebeurd.


Antwoord 8, autoriteit 2%

Als je een specifieke commit uitcheckt in git, kom je terecht in een detached headstaat…dat wil zeggen, je werkkopie weerspiegelt niet langer de staat van een benoemde referentie (zoals “master”). Dit is handig om de vroegere staat van de repository te onderzoeken, maar niet wat u wilt als u daadwerkelijk probeert wijzigingen ongedaan te maken.

Als je wijzigingen hebt aangebracht in een bepaald bestand en je wilt ze gewoon weggooien, kun je de opdracht checkoutals volgt gebruiken:

git checkout myfile

Hiermee worden alle niet-vastgelegde wijzigingen genegeerd en wordt het bestand teruggezet naar de staat die het in de head van uw huidige branch heeft. Als je wijzigingen wilt negeren die je al hebt vastgelegd, kun je de opdracht resetgebruiken. Dit zal bijvoorbeeld de repository resetten naar de staat van de vorige commit, waarbij eventuele volgende wijzigingen worden genegeerd:

git reset --hard HEAD^

Als je de repository echter met andere mensen deelt, kan een git resetstorend werken (omdat het een deel van de geschiedenis van de repository wist). Als je al wijzigingen met andere mensen hebt gedeeld, wil je over het algemeen in plaats daarvan naar git revertkijken, dat een “anticommit” genereert — dat wil zeggen, het creëert een nieuwe commit die de wijzigingen in “ongedaan maakt”. vraag.

Het Git Bookbevat meer details.


Antwoord 9

Sinds “detached head state” je op een tijdelijke branch heeft, gebruik je gewoon git checkout -waarmee je op de laatste branch waar je was.


Antwoord 10

je hebt waarschijnlijk git reset --hard origin/your-branchgedaan.

Probeer gewoon git checkout your-branch


Antwoord 11

Om het antwoord van @Philippe Gerber verder te verduidelijken, hier is het:

git cherry-pick

Voor cherry-pickis in dit geval een git checkout masternodig. Verder is het alleen nodig met een commitin detached head.


Antwoord 12

Detached head betekent dat je je branch niet goed hebt uitgecheckt of dat je net een enkele commit hebt uitgecheckt.

Als u een dergelijk probleem tegenkomt, verbergtdan eerst uw lokale wijzigingen, zodat u uw wijzigingen niet kwijtraakt.

Daarna… reken je gewenste branch af met het commando:

Stel dat je een filiaal MyOriginalBranch wilt:

git checkout -b someName origin/MyOriginalBranch


Antwoord 13

In “detached head” staan betekent dat HEAD verwijst naar een specifieke niet nader genoemde commit (in tegenstelling tot een benoemde branch) (cf: https://git-scm.com/docs/git-checkoutsectie Vrijstaande kop).
In werkelijkheid betekent dit dat je een commit hebt uitgecheckt, maar er is geen branchnaam aan gekoppeld.

Je kunt ervoor kiezen om alleen een nieuwe branch te maken die is gekoppeld aan je commit door

git branch new-branch-name.

Hiermee kunt u uw huidige status in een nieuw filiaal opslaan.

Of u wilt misschien terugkeren naar de vorige staat en om dit te doen, moet u de vertakking selecteren die eerder werd geselecteerd door

git checkout @{ -1}


Antwoord 14

Aanvulling

Als het filiaal waarnaar u wilt terugkeren de laatste kassa was die u heeft gemaakt, kunt u eenvoudig checkout @{ -1}gebruiken. Hiermee gaat u terug naar uw vorige kassa.

Verder kun je dit commando een alias geven met bijvoorbeeld git global --config alias.prevzodat je gewoon git prevhoeft in te typen om terug te gaan naar de vorige kassa.


Antwoord 15

Git heeft me verteld hoe ik het moet doen.

als je hebt getypt:

git checkout <some-commit_number>

Sla de status op

git add .
git commit -m "some message"

Dan:

git push origin HEAD:<name-of-remote-branch>

Antwoord 16

Normaal gesproken verwijst HEADnaar een vertakking. Als het in plaats daarvan niet naar een branch wijst als het naar een commit-hash zoals 69e51verwijst, betekent dit dat je een losgekoppelde HEAD hebt. U moet het twee een vertakking aanwijzen om het probleem op te lossen. Je kunt twee dingen doen om het op te lossen.

  1. git checkout other_branch // Niet mogelijk als je de code in die commit hash
  2. nodig hebt

  3. maak een nieuwe branch aan en verwijs de commit-hash naar de nieuw aangemaakte branch.

HEAD moet naar een branch wijzen, niet een commit-hash is de gouden regel.


Antwoord 17

Als je in een detached head-situatie zit en nieuwe bestanden hebt aangemaakt, zorg er dan eerst voor dat deze nieuwe bestanden aan de index worden toegevoegd, bijvoorbeeld met:

git add .

Maar als je alleen bestaande bestanden hebt gewijzigd of verwijderd, kun je tegelijkertijd (-a) toevoegen en vastleggen met een bericht (-m) via:

git commit -a -m "my adjustment message"

Dan kun je eenvoudig een nieuwe branch maken met je huidige status met:

git checkout -b new_branch_name

Je hebt een nieuwe branch en al je aanpassingen zullen in die nieuwe branch zitten. Je kunt dan doorgaan naar de afstandsbediening en/of afrekenen/trekken/samenvoegen zoals je wilt.


Antwoord 18

Toen ik me realiseerde dat ik een losstaand hoofd had zonder te weten hoe ik het voor elkaar kreeg (zoals drie commits verwijderd), ontdekte ik ook dat ik probeerde te merge, rebaseof cherry-pickveroorzaakte honderden samenvoegconflicten, dus nam ik een andere benadering:

  1. (Ervan uitgaande dat alles is vastgelegd (werkboom is “schoon”))

  2. Bewaar mijn commit-berichten: git log > /tmp/log

  3. Mijn werkboom opslaan: mkdir /tmp/backup && cp -a all_my files_and_directories /tmp/backup

  4. Terug naar master: git checkout master

  5. Verwijder alle werkbestanden en mappen: rm ...

  6. Gebruik de back-up: cp -a /tmp/backup/. .

  7. git adden git commitmet behulp van berichten van opgeslagen /tmp/log, misschien herhalend met verschillende subsets van bestanden…

Het nadeel is dat je je commit-geschiedenis verliest als een bestand meerdere keren is gewijzigd sinds master, maar uiteindelijk had ik een schone master.


Antwoord 19

Ik wilde mijn wijzigingen behouden, dus ik los dit gewoon op door…

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

die voor mij werken


Antwoord 20

Deze aanpak zal mogelijk een deel van de commit-geschiedenis weggooien, maar het is gemakkelijker als het samenvoegen van de oude master-branch en de huidige status lastig is, of als je het gewoon niet erg vindt om een deel van de commit-geschiedenis.

Om de dingen gewoon te houden zoals ze zijn, zonder samen te voegen, de huidige losgekoppelde HEAD in de master branch veranderen:

  1. Maak handmatig een back-up van de repository, voor het geval er onverhoopt iets misgaat.
  2. Voeg de laatste wijzigingen door die u wilt behouden.
  3. Maak een tijdelijke vertakking (laten we het detached-headnoemen) die de bestanden in hun huidige status zal bevatten:
git checkout -b detached-head
  1. (a) Verwijder de master-branch als je deze niet hoeft te behouden
git branch -D master
  1. (b) OF hernoem als je het wilt behouden
git branch -M master old-master
  1. Hernoem de tijdelijke vertakking naar de nieuwe hoofdvertakking
git branch -M detached-head master

Credit: aangepast van dit Medium-artikeldoor Gary Lai.


Antwoord 21

git pull origin master

werkte voor mij. Het ging gewoon om het expliciet geven van de naam op afstand en filiaal.


Antwoord 22

De vrijstaande HEAD betekent dat u zich momenteel niet op een tak bevindt. Als je je huidige wijzigingen wilt BEHOUDEN en gewoon een nieuwe branch wilt maken, dan is dit wat je doet:

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

Daarna wil je deze nieuwe branch eventueel samenvoegen met andere branches. Altijd handig is het git “a dog”commando:

git log --all --decorate --oneline --graph

Antwoord 23

Dit werkt voor mij, het zal een nieuwe tak toewijzen voor losstaand hoofd:

git checkout new_branch_name detached_head_garbage_name


Antwoord 24

Ik zat in een vergelijkbare situatie.
Om de een of andere reden kreeg ik een losstaand hoofd – ik had commits gemaakt op hetzelfde pad als de branch waar ik dacht dat ik op zat – bijv. HEAD was een kind van de branch-tag maar om de een of andere reden was de branch-tag op een historisch commit… mogelijk omdat ik had gepusht??

Ik kon niet pushen omdat ik niet werd beschouwd als op het filiaal waar ik dacht dat ik was.

Ik wilde niets aan mijn geschiedenis veranderen of cherrypicking doen en ik had net ongeveer 8 weken aan het filiaal gewerkt, dus reset --hardmaakte me een beetje nerveus !

De oplossing was gewoon om het volgende te doen:

git branch -f myStuckBranch HEAD
git checkout myStuckBranch

Je moet afrekenen, ook al wijzen HEAD en myStuckBranch nu naar hetzelfde, omdat je nog steeds wordt beschouwd als een losstaand hoofd (niet op een tak)

Ik ben geen expert met git (ik heb voornamelijk mercurial gebruikt, wat nooit voor deze rare situatie zou zorgen) maar mijn begrip van dit commando is dat het alleen zegt
“verander myStuckBranch om naar HEAD te wijzen”.

Ik merk dat ik regelmatig dit commando gebruik om wijzigingen van master samen te voegen na het ophalen zonder mijn werkdirectory te hoeven verwisselen – anders probeert het de oude (oninteressante) versie van master te gebruiken:

git fetch
git branch -f master origin/master  -- err yeah don't just ignore what's been going on remotely - eg point my master at the real master
git merge master -- merge the changes into my local branch

Het is een beetje vervelend om dat de hele tijd handmatig te moeten doen, maar het is nog steeds beter dan je werkdirectory te moeten wijzigen om alleen maar een andere branch bij te werken om de wijzigingen ervan samen te voegen.


Antwoord 25

Met git rebasekun je je HEAD naar de gewenste commit verplaatsen

Stel dat u uw filiaal in een vrijstaande staat heeft, zoals dit:

* bfcb8f9 Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 (HEAD -> master) Commit 2 --amend
|/
* 1818f91 Commit 1

De ontkoppelde kop is gemaakt door per ongeluk te rebasen, verwijzend naar een ontkoppelde commit, die eerder was gemaakt vanwege een git commit –amendcommando.

Als je je HEAD-ref naar de meest recente commit wilt verplaatsen, pas dan een rebase toe met de gewenste HASH-commit waarnaar je wilt verwijzen. In dit voorbeeld is de hash van de meest recente commit:

git rebase bfcb8f9

en hierdoor blijft je branch met zijn HEAD naar de gewenste commit (de meest recente in dit geval):

* bfcb8f9 (HEAD -> master) Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2 --amend
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 Commit 2
|/
* 1818f91 Commit 1

Antwoord 26

In mijn geval trad de ontkoppelde HEAD-waarschuwing op toen ik dat deed

git checkout origin/some_branch

in plaats van

git checkout some_branch

Dus gewoon git checkout some_branchloste het probleem in mijn geval op.

Other episodes