Hoe repareer je een “Detached HEAD” in een Git-repository?

0
174

Een van de normale foutmeldingen waarmee u waarschijnlijk te maken krijgt Git is de waarschuwing dat “je bent in ‘detached HEAD’ staat.” Je bent hier misschien per ongeluk tegenaan gelopen, maar maak je geen zorgen, het is een normaal probleem en het kan gemakkelijk worden opgelost als je eenmaal begrijpt wat het betekent.

Wat is de Git HEAD?

“HEAD” is gewoon een alias voor je huidige werkende commit, net zoals je huidige map op een opdrachtregel. In welke staat je Git-repository zich ook bevindt, HEAD verwijst altijd naar iets, en nieuwe commits zullen voor de HEAD worden toegevoegd.

Gewoonlijk verwijst HEAD niet rechtstreeks naar een enkele commit. Het wijst in plaats daarvan naar een branch en verwijst indirect naar de laatste commit in die branch. Telkens wanneer u “afrekent” een nieuwe branch, schakelt Git de HEAD over naar die branch. Hierdoor kun je nieuwe commits maken die aan het einde van die branch worden toegevoegd.

Je kunt echter ook individuele commits bekijken. Wat als u de repository op een bepaald moment wilt onderzoeken? Dat is een van de belangrijkste voordelen van Git, maar het geeft een klein probleem met hoe Git dingen structureert. Aangezien nieuwe commits een branch niet updaten, zullen alle commits die je maakt nadat je de HEAD weg hebt verplaatst, worden losgekoppeld van alle branch-referenties, vandaar, “detached HEAD.”

Dit kan eigenlijk best handig zijn. Stel dat je de HEAD een paar commits hebt teruggezet en vervolgens wat experimentele updates hebt gemaakt. Je maakt eigenlijk een nieuwe branch, die later weer kan worden samengevoegd tot master.

Advertentie

Je moet het officieel integreren in de Git-repo als je besluit om de wijzigingen te behouden, maar als een hulpmiddel voor het doen van back-in-time aanpassingen, is het hebben van een vrijstaande HEAD niet zo eng als het klinkt.

Als je hier per ongeluk bent aangekomen

Het is heel gemakkelijk om hier per ongeluk terecht te komen en in de war te raken over de foutmelding waar Git over klaagt ondanks dat hij niets verkeerd heeft gedaan. Gelukkig is het ongelooflijk eenvoudig op te lossen:

Als je net een commit hebt uitgecheckt en de repository anders niet hebt aangeraakt (er zijn geen nieuwe commits gemaakt), kun je de GA terug naar waar het hoort met git checkout:

git checkout master

Dit is eigenlijk hetzelfde als cd op Linux draaien, behalve dat Git nog steeds commits en wijzigingen in de cache associeert met de oude HEAD, dus je wilt niet uitchecken als je commits of wijzigingen hebt die zouden blijven hangen.

Als je wel wat veranderingen had, en ze gewoon weg wilt gooien, kun je hard reset terug naar master:

git reset –hard origin/master git clean -d –force

Als je wilt sla je commits echter op, je moet ze officieel weer samenvoegen in de tijdlijn van Git.

Als je je wijzigingen wilt opslaan

Het eerste dat je wilt doen als je de wijzigingen die je hebt gemaakt wilt behouden terwijl je in een onthechte HEAD-status bent, is een nieuwe branch maken. Dit komt omdat Git's garbage collector detached commits automatisch opruimt, dus je wilt ze nooit uit het oog verliezen.

git branch detached-branch Advertisement

Dan moet je kan deze branch uitchecken om de HEAD te verplaatsen zodat het niet langer losgekoppeld is, en in plaats daarvan naar deze officiële nieuwe branch wijzen:

git checkout detached-branch

Zodra de wijzigingen zijn vastgelegd, hebt u een van de twee opties. Deze nieuwe branch is in feite een gewone feature branch, dus je kunt git merge of git rebase gebruiken.

Samenvoegen is eenvoudig; checkout master, en merge de detached branch:

git checkout master git merge detached-branch

Dit werkt goed als je integreert in een branch die goedkeuring nodig heeft, zoals het geval is met pull-verzoeken en code beoordelingen. Mogelijk moet u het goedkeuringsproces van uw team doorlopen in plaats van deze opdrachten zelf uit te voeren.

Als je wel toegang hebt, zoals wanneer je weer merged in een feature branch waar je aan werkt, is een betere methode om de losse commits te kiezen. Cherrypicking kopieert in feite een commit en plakt deze op een andere branch. Het wordt meestal gebruikt om specifieke commits uit een feature-branch te halen voordat het hele ding klaar is, maar in dit geval kan cherrypicking de ontkoppelde branch verzoenen zonder een merge.

Advertentie

In dit voorbeeld is de commit hierboven losgekoppeld. In plaats van het samen te voegen, is het geplukt en verplaatst naar de functietak. Dit verplaatst de HEAD en feature branch om te wijzen naar de laatste commit zonder een merge. Dan kan de originele losgemaakte commit worden weggegooid.

Eerst moet je de detached branch maken, en dan de feature branch uitchecken om de HEAD daarheen te verplaatsen:

git branch detached -branch git checkout-functie

Voer vervolgens Git log uit om een ​​lijst met commits te krijgen:

git log –pretty=format:”%h %s” –graph

Vervolgens kun je een commit kiezen op basis van zijn ID:

git cherry -pick 1da76d3

Als je eenmaal hebt bevestigd dat de door kersen uitgekozen commits correct zijn toegepast, kun je de ontkoppelde branch verwijderen, aangezien de commits zijn gekopieerd en niet langer worden gebruikt.

git branch -D detached-branch

Rebasen in plaats van samenvoegen

Je zou ook een rebase kunnen doen. Rebases verschillen van merges doordat ze de geschiedenis van de branch herschrijven, de losgemaakte commits optillen en naar de voorkant van de branch verplaatsen.

Het probleem hiermee is echter dat je nog steeds twee vertakkingen overhoudt, en dat je nog steeds de functie en de losse vertakking moet samenvoegen, waardoor je hoe dan ook een merge-commit krijgt. Maar het laat de repository achter met een meer lineaire Git-geschiedenis, wat de voorkeur verdient boven het uitvoeren van git merge als je de bevoegdheid hebt om dit te doen.