Warum ist mein Git-Repo in einen getrennten HEAD-Status eingetreten?

387

Ich hatte heute einen abgetrennten Kopf, das gleiche Problem wie in: Git Push sagt alles auf dem neuesten Stand, obwohl ich lokale Änderungen habe

Soweit ich weiß, habe ich nichts Außergewöhnliches getan, sondern nur mein lokales Repo festgelegt und gepusht.

Wie bin ich zu einem gekommen detached HEAD?

Adam Bergmark
quelle
18
Das Auschecken eines Remote-Zweigs scheint der häufigste Weg zu sein, dies versehentlich zu tun. Ein anderer üblicher Weg ist das Auschecken branch-name@{n}der n-ten vorherigen Position von branch-name. Aber egal was passiert, irgendwann muss es eine gegeben haben git checkout <rev>. Wenn das nicht klingelt, haben Sie wahrscheinlich das getan, was Will erwähnt hat - versucht git checkout <file>und versehentlich eine Revision angegeben.
Cascabel
3
Informationen zum Rückgängigmachen eines abgetrennten HEAD-Status finden Sie unter Fixieren eines abgetrennten Git-Kopfes? .
Mein Repo landete in diesem Zustand, als beim Umbasieren Konflikte auftraten. Zum Glück hat Git mir gesagt, was ich tun soll, wenn ich renne git status:all conflicts fixed: run "git rebase --continue"
Paul
2
Kommt auch vor, wenn Sie versehentlich git checkout remotes/origin/my-branchanstelle von git checkout my-branchoder tippen git checkout origin/my-branch.
Adam Libuša
@adam Libusa, Danke, es hat bei mir funktioniert. Was ist der Unterschied zwischen git checkout remotes / origin / my-branch und git checkout my-branch? Ist es nicht dasselbe? aber was du gesagt hast, hat bei mir funktioniert. Aus Neugier frage ich.
Karunakar Bhogyari

Antworten:

281

Wenn Sie ein Commit auschecken, das nicht der Name eines Ihrer Zweige ist, erhalten Sie einen getrennten HEAD. Ein SHA1, der die Spitze eines Zweigs darstellt, ergibt immer noch einen abgetrennten KOPF. Nur eine Kasse eines lokalen Zweignamen vermeidet diesen Modus.

Siehe Festschreiben mit einem abgetrennten KOPF

Wenn HEAD getrennt ist, funktionieren Commits wie gewohnt, außer dass kein benannter Zweig aktualisiert wird. (Sie können sich dies als anonymen Zweig vorstellen.)

Alt-Text

Wenn Sie beispielsweise einen "Remote-Zweig" auschecken, ohne ihn zuerst zu verfolgen, erhalten Sie möglicherweise einen abgetrennten HEAD.

Siehe git: Zweig wechseln, ohne den Kopf abzunehmen


Mit Git 2.23 (August 2019) müssen Sie den verwirrenden git checkoutBefehl nicht mehr verwenden.

git switch Sie können auch einen Zweig auschecken und einen abgetrennten KOPF erhalten, außer:

  • Es gibt eine explizite --detachOption

So überprüfen Sie das Commit HEAD~3für eine vorübergehende Überprüfung oder ein Experiment, ohne einen neuen Zweig zu erstellen:

git switch --detach HEAD~3
HEAD is now at 9fc9555312 Merge branch 'cc/shared-index-permbits'
  • Ein Remote-Tracking-Zweig kann nicht versehentlich getrennt werden

Sehen:

C:\Users\vonc\arepo>git checkout origin/master
Note: switching to 'origin/master'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

Vs. mit dem neuen git switchBefehl:

C:\Users\vonc\arepo>git switch origin/master
fatal: a branch is expected, got remote branch 'origin/master'

Wenn Sie einen neuen lokalen Zweig erstellen möchten, der einen Remote-Zweig verfolgt:

git switch <branch> 

Wenn <branch>nicht gefunden wird, aber in genau einer Fernbedienung ein Tracking-Zweig <remote>mit einem übereinstimmenden Namen vorhanden ist (nennen Sie ihn ), behandeln Sie ihn als äquivalent zu

git switch -c <branch> --track <remote>/<branch>

Kein Fehler mehr!
Kein unerwünschter losgelöster KOPF mehr!

VonC
quelle
12
Eine andere Möglichkeit, in den Status eines getrennten Kopfes zu wechseln, besteht darin, dass Sie sich mitten in einer interaktiven Rebase befinden und einen der Commits bearbeiten möchten. Wenn Git Sie beim Festschreiben zum Bearbeiten fallen lässt, befinden Sie sich in einem getrennten Kopfzustand, bis Sie die Rebase abgeschlossen haben.
In dieser visuellen Anleitung gibt es folgende Erklärung: git commit files creates a new commit containing the contents of the latest commit, plus a snapshot of files taken from the working directory. Additionally, files are copied to the stage.Was bedeutet "Dateien werden auf die Bühne kopiert"? Ich dachte, die Dateien sind festgeschrieben, was bedeutet, dass die Bühne gelöscht ist?
Max
16
Tatsächlich erhalten Sie einen abgetrennten HEAD, wenn Sie ein Commit von SHA1 auschecken, unabhängig davon , ob es sich an der Spitze eines Zweigs befindet oder nicht . Die einzige Art von Dingen, die Sie auschecken können, ohne einen abgetrennten HEAD zu erhalten, ist ein Filialname. Zum Beispiel, obwohl masteres in ed489der Abbildung oben ist git checkout ed489, erhalten Sie einen abgetrennten KOPF, während dies git checkout masternicht der Fall ist .
Musiphil
8
"You can think of this as an anonymous branch":) Ich mag die Analogie
Adrien Be
117

Ich habe das gerade zufällig reproduziert:

  1. listet die entfernten Zweige auf

    git branch -r
          origin/Feature/f1234
          origin/master
    
  2. Ich möchte eine lokal auschecken, also schneide ich Paste aus:

    git checkout origin/Feature/f1234
    
  3. Presto! Freistehender HEAD-Zustand

    You are in 'detached HEAD' state. [...])
    

Lösung 1:

origin/Fügen Sie beim Auschecken nicht die Vorderseite meiner Filialspezifikation ein:

git checkout Feature/f1234

Lösung 2:

Fügen Sie einen -bParameter hinzu, der einen lokalen Zweig von der Fernbedienung erstellt

git checkout -b origin/Feature/f1234 oder

git checkout -b Feature/f1234 Es wird automatisch auf den Ursprung zurückgesetzt

Owen
quelle
14
Dies ist fast eine gute Antwort, kann aber nicht erklären, warum Sie in einen Zustand mit losgelöstem Kopf geraten sind.
Gans
5
Ich stimme zu, aber es bietet die Lösung, nach der ich gesucht habe. Vielen Dank!!
Kilmazing
Ich habe in dieser anderen Antwort gesehen, dass git checkout -b Feature/f1234<=> git branch Feature/f1234und git checkout Feature/f1234.
Armfoot
1
Standardmäßig wird der Ursprung angezeigt. Wenn Sie also angeben origin/branchname, wird darauf hingewiesen origin/origin/branchname, dass der erste Name der von Ihnen verwendete Remote-Name -bist. Wenn dies nicht der Fall ist, wird ein anonymousZweig erstellt, der getrennt ist. In ähnlicher Weise müssten Sie beim Auschecken von einer anderen Fernbedienung -bParameter angeben, da git sonst nicht erkennen kann, dass es sich um eine neue Fernbedienung handelt origin/remote/branchname.
Garg10Mai
Du bist ein Heiliger!
Harvey Lin
12

Versuchen

git reflog 

Auf diese Weise erhalten Sie einen Verlauf darüber, wie Ihre HEAD- und Zweigzeiger in der Vergangenheit verschoben wurden.

z.B :

88ea06b HEAD @ {0}: Kasse: Übergang von ENTWICKLUNG zu Fernbedienungen / Ursprung / SomeNiceFeature e47bf80 HEAD @ {1}: Ursprung ziehen ENTWICKLUNG: Schnellvorlauf

Der Anfang dieser Liste ist ein Grund, warum Sie möglicherweise auf den Status DETACHED HEAD stoßen ... und einen Remote-Tracking-Zweig auschecken.

André R.
quelle
7

Dies kann leicht passieren, wenn Sie versuchen, vorgenommene Änderungen rückgängig zu machen, indem Sie Dateien erneut auschecken und die Syntax nicht ganz richtig einstellen.

Sie können sich die Ausgabe von ansehen git log- Sie können hier das Ende des Protokolls seit dem letzten erfolgreichen Commit einfügen, und wir können alle sehen, was Sie getan haben. Oder Sie können es einfügen und im #gitFreenode-IRC nachfragen .

Wille
quelle
5

Dies kann passieren, wenn Sie ein Tag mit dem gleichen Namen wie ein Zweig haben.

Beispiel: Wenn "release / 0.1" der Tag-Name ist, dann

git checkout release/0.1

erzeugt bei "release / 0.1" abgelösten HEAD. Wenn Sie erwarten, dass Release / 0.1 ein Filialname ist, werden Sie verwirrt.

Radzimir
quelle
1
Ja. Aber wie können Sie das beheben? Wie machst du eine Kasse in der Filiale?
Martin
5

Detached HEAD bedeutet, dass das, was derzeit ausgecheckt ist, keine lokale Niederlassung ist.

Einige Szenarien, die zu einem Detached HEADStatus führen:

  • Wenn Sie einen Remote-Zweig auschecken , sagen wir origin/master. Dies ist ein schreibgeschützter Zweig. Wenn Sie also ein Commit daraus erstellen, ist origin/masteres frei schwebend , dh nicht mit einem Zweig verbunden.

  • Wenn Sie ein bestimmtes Tag auschecken oder festschreiben . Wenn Sie von hier aus ein neues Commit ausführen, ist es wieder frei schwebend , dh nicht mit einem Zweig verbunden. Beachten Sie, dass beim Auschecken eines Zweigs neue Commits immer automatisch an der Spitze platziert werden.

    Wenn Sie zurückgehen und ein bestimmtes Commit oder Tag auschecken möchten, um von dort aus zu arbeiten, können Sie einen neuen Zweig erstellen, der von diesem Commit ausgeht, und von zu diesem wechseln git checkout -b new_branch_name. Dies verhindert den Detached HEADStatus, da Sie jetzt einen Zweig ausgecheckt und kein Commit mehr haben.

Tim Skov Jacobsen
quelle
3

Ein einfacher zufälliger Weg ist es, git checkout headeinen Tippfehler zu machen HEAD.

Versuche dies:

git init
touch Readme.md
git add Readme.md
git commit
git checkout head

was gibt

Note: checking out 'head'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 9354043... Readme
Thomas Weller
quelle
Auch erwähnt in longair.net/blog/2012/05/07/the-most-confusing-git-terminology (suchen Sie nach "" HEAD "und" head "")
VonC
@VonC: Danke für diesen Link. Ich bereite ein Git-Training vor und möchte auch darauf hinweisen, warum es manchmal so verwirrend ist. Ich habe bereits viele Beispiele ( checkout -bdie wie eine Kasse aussehen, aber tatsächlich verzweigen), aber eine andere Liste ist nur willkommen.
Thomas Weller
2

Die andere Möglichkeit, in einen git-getrennten Kopfzustand zu gelangen, besteht darin, zu versuchen, einen Commit für einen Remote-Zweig durchzuführen. Etwas wie:

git fetch
git checkout origin/foo
vi bar
git commit -a -m 'changed bar'

Beachten Sie, dass Sie bei jedem weiteren Versuch, origin / foo auszuchecken, wieder in einen Zustand mit losgelöstem Kopf versetzt werden!

Die Lösung besteht darin, einen eigenen lokalen foo-Zweig zu erstellen, der origin / foo verfolgt, und dann optional zu pushen.

Dies hat wahrscheinlich nichts mit Ihrem ursprünglichen Problem zu tun, aber diese Seite enthält viele Google-Treffer für "Git Detached Head" und dieses Szenario ist stark unterdokumentiert.

dspeyer
quelle
Über diese Situation scheint Owens Antwort oben zu sprechen - wo das Ausschneiden und Einfügen von "origin / foo" Git dazu bringt, es als "origin / origin / foo" zu betrachten.
mvanle
1

Wenn Sie zu einem Commit auschecken git checkout <commit-hash> oder zu einem Remote-Zweig auschecken, wird Ihr HEAD getrennt und versucht, ein neues Commit darauf zu erstellen.

Commits, die von keinem Zweig oder Tag erreicht werden können, werden nach 30 Tagen gesammelt und aus dem Repository entfernt.

Eine andere Möglichkeit, dies zu lösen, besteht darin, einen neuen Zweig für das neu erstellte Commit zu erstellen und ihn zu überprüfen. git checkout -b <branch-name> <commit-hash>

Dieser Artikel zeigt, wie Sie zum getrennten HEAD- Status gelangen können.

Nesha Zoric
quelle