Einen abgetrennten Git-Kopf reparieren?

1454

Ich habe in meinem Repository gearbeitet und festgestellt, dass eine Datei lokale Änderungen aufweist. Ich wollte sie nicht mehr, also löschte ich die Datei und dachte, ich könnte einfach eine neue Kopie auschecken. Ich wollte das Git-Äquivalent von machen

svn up .

Verwenden git pullschien nicht zu funktionieren. Eine zufällige Suche führte mich zu einer Seite, die jemand empfohlen hatte

git checkout HEAD^ src/

( srcist das Verzeichnis, das die gelöschte Datei enthält).

Jetzt finde ich heraus, dass ich einen abgetrennten Kopf habe. Ich habe keine Ahnung was das ist. Wie kann ich rückgängig machen?

Daniel
quelle
69
git checkout masterSie gelangen zurück in die Hauptniederlassung. Wenn Sie Änderungen an der Arbeitskopie löschen wollten, wollten Sie dies wahrscheinlich tun git reset --hard.
Abe Voelker
Wenn Sie sich nicht verpflichtet haben, hätten Sie es tun könnengit checkout -- src/
Summersign
Versuchen Sie dies: Link . Kurz gesagtcreate temp branch - checkout temp branch - checkout master - delete temp branch
Fidev
@AbeVoelker Was hast du in den Kommentaren von gemeint working copy changes? Beziehen Sie sich auf die Änderungen, die Sie an Dateien vorgenommen haben, nachdem Sie ein anderes Commit ausgecheckt haben (dh auf die Änderungen, die Sie in einem Status mit getrenntem Kopf vorgenommen haben)?
Minh Tran

Antworten:

2147

Abgelöster Kopf bedeutet, dass Sie sich nicht mehr in einem Zweig befinden. Sie haben ein einzelnes Commit in der Historie ausgecheckt (in diesem Fall das Commit vor HEAD, dh HEAD ^).

Wenn Sie löschen möchten Ihre Änderungen die mit dem abgetrennten HEAD verknüpft sind

Sie müssen nur den Zweig auschecken, in dem Sie sich befanden, z

git checkout master

Wenn Sie das nächste Mal eine Datei geändert haben und den Status im Index wiederherstellen möchten, löschen Sie die Datei nicht zuerst, sondern tun Sie dies einfach

git checkout -- path/to/foo

Dadurch wird die Datei foo auf den Status im Index zurückgesetzt.

Wenn Sie möchten , halten Sie die Änderungen mit dem abgelösten HEAD zugeordnet

  1. Ausführen git branch tmp- Hiermit werden Ihre Änderungen in einem neuen Zweig namens gespeichert tmp.
  2. Lauf git checkout master
  3. Wenn Sie die vorgenommenen Änderungen übernehmen möchten master, führen Sie sie in git merge tmpder masterVerzweigung aus. Sie sollten sich masternach dem Ausführen auf dem Zweig befinden git checkout master.
ralphtheninja
quelle
6
"Dadurch wird die Datei foo in dem Zustand wiederhergestellt, in dem sie war, bevor Sie Änderungen daran vorgenommen haben." -> es wird es in dem Zustand wiederherstellen, in dem es im Index ist - bitte bearbeiten
Mr_and_Mrs_D
88
Warum tritt dieser Fehler überhaupt auf? Dies ist eines der Dinge, für die ich Git hasse - manchmal völlig zufälliges Verhalten. Hatte noch nie solche Probleme mit Mercurial.
Violette Giraffe
97
@VioletGiraffe Es ist weder ein Fehler noch etwas Zufälliges - es ist einfach der Status, in den Ihr Repository geht, wenn Sie ein vorheriges Commit auschecken. Der "Abgelöste Kopf" dient als Warnung, dass Sie möglicherweise auch einen Zweig erstellen oder darauf verweisen möchten, wenn Sie von diesem Punkt aus arbeiten möchten. Wenn Sie dieses Tag oder Commit einfach anzeigen möchten, ist es nichts Falsches, wenn Sie sich in einem Zustand mit losgelöstem Kopf befinden.
Neil Neyman
22
Tun Sie dies nicht, wenn Sie sich dem abgetrennten Kopf verschrieben haben, siehe andere Antworten. Wenn ja, können Sie die vorherigen Head-Git-Erwähnungen inPrevious HEAD position was 7426948...
KCD
9
@VioletGiraffe: Sie haben ein mentales Modell dessen, was basierend auf Mercurial passiert, aber Sie verwenden Git. Wenn Sie nicht bereit sind, Ihr mentales Modell an das Git-Modell anzupassen, werden die Dinge weiterhin zufällig angezeigt. Es ist, als würden Sie draußen mit einer VR-Brille herumlaufen und denken, Sie fliegen ein Flugzeug, aber Sie überqueren wirklich die Straße. Du wirst von Autos angefahren.
Bilderstürmer
477

Wenn Sie Dateien geändert haben, die Sie nicht verlieren möchten, können Sie sie pushen. Ich habe sie im getrennten Modus festgeschrieben und danach können Sie zu einem temporären Zweig wechseln, um sie später in den Master zu integrieren.

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

Extrahiert aus:

Was tun mit Commit in einem abgetrennten Kopf?

Toni Gamez
quelle
27
Ich finde, dass dies die bevorzugte Lösung ist - insbesondere, wenn Sie die Änderungen beibehalten möchten, die Sie beim Auschecken der einzelnen Version vorgenommen haben.
adswebwork
10
@adswebwork: Ich stimme zu. Alle anderen Antworten deuten darauf hin, dass Sie zu einem vorherigen Zustand zurückkehren und Änderungen verlieren, die lokal im Zustand des getrennten Kopfes vorgenommen wurden.
Sk8erPeter
6
warum nicht git stash? Da ist das das erste, was mir in den Sinn kommt. Das Erstellen eines neuen Zweigs ist ein Overkill.
Sommerzeichen
2
Sie können git rebase my-temporary-workden Zweig auch löschen und dann löschen, git branch -d my-temporary-worksodass es so aussieht, als hätten Sie sich zunächst für den richtigen Zweig entschieden.
Zoltán
@geekay git stashklingt wie das perfekte Werkzeug für diesen Fall. Könnten Sie bitte eine Antwort mit den vorgeschlagenen Schritten schreiben, um dies zu erreichen?
Zoltán
156

Eine Lösung ohne temporären Zweig.

So beenden Sie den getrennten HEAD-Status („fix“), wenn Sie in diesem Modus bereits etwas geändert haben und optional Ihre Änderungen speichern möchten:

  1. Übernehmen Sie die Änderungen, die Sie behalten möchten. Wenn Sie eine der Änderungen übernehmen möchten, die Sie im getrennten HEAD-Status vorgenommen haben, schreiben Sie sie fest. Mögen:

    git commit -a -m "your commit message"
    
  2. Verwerfen Sie Änderungen, die Sie nicht behalten möchten. Beim Hard-Reset werden alle nicht festgeschriebenen Änderungen verworfen, die Sie im getrennten HEAD-Status vorgenommen haben:

    git reset --hard
    

    (Ohne dies würde Schritt 3 fehlschlagen und sich über geänderte nicht festgeschriebene Dateien im abgetrennten HEAD beschweren.)

  3. Überprüfen Sie Ihre Filiale. Beenden Sie den Status "Getrennter HEAD", indem Sie den Zweig überprüfen, an dem Sie zuvor gearbeitet haben. Beispiel:

    git checkout master
    
  4. Übernehmen Sie Ihre Verpflichtungen. Sie können jetzt die Commits übernehmen, die Sie im freistehenden HEAD-Zustand durch Kirschernte vorgenommen haben, wie in meiner Antwort auf eine andere Frage gezeigt .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
Tanius
quelle
Das git reset --hardwar genau das, was ich brauchte, weil ich möchte, dass der Upstream die Quelle ist und die lokalen Änderungen entfernt werden sollten.
Markus Zeller
Tolle Antwort, das hat bei mir
funktioniert
130

Abgenommener Kopf bedeutet:

  1. Sie sind nicht mehr in einer Filiale,
  2. Sie haben ein einzelnes Commit im Verlauf ausgecheckt

Wenn Sie keine Änderungen vorgenommen haben: Sie können mit dem folgenden Befehl zum Master wechseln

  git checkout master

Wenn Sie Änderungen haben, die Sie behalten möchten:

Bei einem abgetrennten HEAD funktionieren die Commits wie gewohnt, außer dass kein benannter Zweig aktualisiert wird. Um den Hauptzweig mit Ihren festgeschriebenen Änderungen zu aktualisieren, erstellen Sie einen temporären Zweig an Ihrer Position (auf diese Weise enthält der temporäre Zweig alle festgeschriebenen Änderungen, die Sie im getrennten HEAD vorgenommen haben). Wechseln Sie dann zum Hauptzweig und führen Sie den temporären Zweig mit zusammen der Meister.

git branch  temp
git checkout master
git merge temp
Razan Paul
quelle
2
Perfekt, dann nach dem Entfernen der Verzweigungstemperatur
Davi Menezes
64

Folgendes habe ich gerade getan, nachdem mir klar wurde, dass ich auf einem abgetrennten Kopf war und bereits einige Änderungen vorgenommen hatte.

Ich habe die Änderungen übernommen.

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

Ich erinnerte mich an den Hash (1fe56ad) des Commits. Dann habe ich mir die Filiale angesehen, in der ich hätte sein sollen.

$ git checkout master
Switched to branch 'master'

Schließlich habe ich die Änderungen des Commits auf den Zweig angewendet.

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

Ich denke, das ist ein bisschen einfacher als das Erstellen eines temporären Zweigs.

Philippe Gerber
quelle
2
Dies sollte die Antwort sein. Es erhält Ihre Nuked-Dateien zurück.
BlindWanderer
2
Ja, das ist wirklich das Einfachste - einfach genug, um sich zu erinnern, ohne das nächste Mal im Internet zu suchen. Festschreiben, Hash notieren, zu Zweig zurückkehren, für den Sie sich verpflichten wollten, und git cherry-pick <hash>.
Mason
Danke für die Lösung. Das hat geholfen. Darf ich auch hinzufügen, dass ich einen "Git Push Origin Master" machen musste, damit mein Master und Origin / Master auf dasselbe Commit zeigten.
Rübe 424
1
Dies ist im Wesentlichen die Antwort von Tanius (veröffentlicht mehr als ein Jahr zuvor).
Peter Mortensen
Dank dieser fröhlichen Auswahl kehren Sie die letzten Kopfwechsel zurück
Omega Cube
54

Wenn Sie einige Änderungen vorgenommen haben und dann festgestellt haben, dass Sie sich auf einem abgetrennten Kopf befinden, gibt es dafür eine einfache Lösung: 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'

Sie haben Ihre nicht festgeschriebenen Änderungen und den normalen "angehängten" KOPF, als wäre nichts passiert.

Mojuba
quelle
2
Habe diesen bösen Jungen mit einem Lesezeichen versehen - spart das Erstellen eines temporären Zweigs. Arbeitete eine Belohnung.
Tim Tyler
1
Ich lande oft in einem getrennten HEAD-Zustand, nachdem ich ein Git-Submodul ausgecheckt und dann Änderungen daran vorgenommen habe. Ich finde, dass dies die beste und einfachste Lösung ist, um Probleme zu beheben, damit ich meine Änderungen beibehalten kann.
user5359531
1
Dies funktioniert nicht, wenn Sie bereits Änderungen in einem getrennten Zustand festgeschrieben haben?
Danijel
40

Wenn Sie ein bestimmtes Commit auschecken git, landen Sie in einem abgetrennten Kopf Status mit Das heißt, Ihre Arbeitskopie spiegelt nicht mehr den Status einer benannten Referenz wider (wie "Master"). Dies ist nützlich, um den früheren Status des Repositorys zu untersuchen, aber nicht, was Sie möchten, wenn Sie tatsächlich versuchen, Änderungen rückgängig zu machen.

Wenn Sie Änderungen an einer bestimmten Datei vorgenommen haben und diese einfach verwerfen möchten, können Sie den folgenden checkoutBefehl verwenden:

git checkout myfile

Dadurch werden nicht festgeschriebene Änderungen verworfen und die Datei auf den Status im Kopf Ihres aktuellen Zweigs zurückgesetzt. Wenn Sie bereits festgeschriebene Änderungen verwerfen möchten, können Sie den resetBefehl verwenden. Dadurch wird das Repository beispielsweise auf den Status des vorherigen Commits zurückgesetzt, und alle nachfolgenden Änderungen werden verworfen:

git reset --hard HEAD^

Wenn Sie das Repository jedoch für andere Personen git resetfreigeben , kann a störend sein (da dadurch ein Teil des Repository-Verlaufs gelöscht wird). Wenn Sie bereits Änderungen mit anderen Personen geteilt haben, möchten Sie diese im Allgemeinen anzeigengit revert stattdessen betrachten, wodurch ein "Anticommit" generiert wird. Das heißt, es wird ein neues Commit erstellt, das die fraglichen Änderungen "rückgängig macht".

Das Git-Buch enthält weitere Details.

Larsks
quelle
1
Wie ich in der Antwort von @ ralphtheninja sagte, git checkout path/to/fookönnte es zu Konflikten kommen git checkout some-branch, daher wäre es besser, git checkout -- path/to/foodiese Konflikte zu vermeiden.
Diego Lago
30

HEAD befindet sich in einem Zeiger und zeigt daher direkt oder indirekt auf ein bestimmtes Commit:

Befestigt   Kopfmittel , dass es bis zu einem gewissen angebracht ist Zweig (dh er weist auf einen Zweig).
Freistehendes HEAD bedeutet , dass es nicht an einem Zweig befestigt, dh er weist direkt auf einige begehen.

Geben Sie hier die Bildbeschreibung ein

Mit anderen Worten:

  • Wenn es direkt auf ein Commit verweist , wird der HEAD getrennt .
  • Wenn es indirekt auf ein Commit verweist (dh auf einen Zweig zeigt, der wiederum auf ein Commit verweist), wird der HEAD angehängt .

Um Situationen mit angeschlossenem / abgenommenem KOPF besser zu verstehen, zeigen wir die Schritte, die zum Vierfachen der obigen Bilder führen.

Wir beginnen mit demselben Status des Repositorys (Bilder in allen Quadranten sind gleich):

Geben Sie hier die Bildbeschreibung ein


Jetzt wollen wir durchführen git checkout- mit verschiedenen Zielen in den einzelnen Bildern (Befehle auf ihnen sind abgeblendet zu betonen , dass wir nur zu gehen , diese Befehle gelten):

Geben Sie hier die Bildbeschreibung ein


Dies ist die Situation nach dem Ausführen dieser Befehle:

Geben Sie hier die Bildbeschreibung ein

Wie Sie sehen können, zeigt der HEAD auf das Ziel des git checkoutBefehls - auf einen Zweig (die ersten 3 Bilder des Quadruplets) oder (direkt) auf ein Commit (das letzte Bild des Quadrupletts).

Der Inhalt des Arbeitsverzeichnisses wird ebenfalls so geändert, dass er dem entsprechenden Commit (Snapshot) entspricht, dh dem Commit, auf das der HEAD (direkt oder indirekt) hinweist.


Wir befinden uns jetzt in der gleichen Situation wie zu Beginn dieser Antwort:

Geben Sie hier die Bildbeschreibung ein

MarianD
quelle
6
Ich habe es nicht gelesen, aber für die hübschen Bilder gestimmt, die du gemacht hast;).
Carlo Wood
@ Carlo, danke!
MarianD
22

Da Sie sich im Status "Abgelöster Kopf" in einem temporären Zweig befinden, verwenden git checkout -Sie einfach den Zweig, in dem Sie sich zuletzt befanden.

Mike
quelle
1
Seien Sie vorsichtig, Sie verlieren alle Verpflichtungen, die Sie eingegangen sind, als Sie sich in einem Zustand mit losgelöstem Kopf befanden.
Ajak6
@ Ajak6 Du verlierst diese Commits nicht wirklich. Sie sind weiterhin über verfügbar git reflogund können in eine neue Niederlassung oder über git cherry-pickeine bestehende Niederlassung übernommen werden. Siehe diese Frage .
Tanius
7

Um die Antwort von @Philippe Gerber weiter zu verdeutlichen, hier:

Git Cherry-Pick

Vorher ist in diesem Fall cherry-pickein git checkout masternotwendig. Darüber hinaus wird es nur mit einem commitin benötigt detached head.

Timo
quelle
6

Nachtrag

Wenn der Zweig, zu dem Sie zurückkehren möchten, der letzte Checkout war, den Sie durchgeführt haben, können Sie ihn einfach verwenden checkout @{-1}. Dadurch kehren Sie zu Ihrer vorherigen Kaufabwicklung zurück.

Außerdem können Sie diesen Befehl beispielsweise mit einem Alias ​​versehen, git global --config alias.prevsodass Sie nur eingeben müssen, git prevum zur vorherigen Kasse zurückzukehren.

David Brower
quelle
4

In "losgelöstem Kopf" zu sein bedeutet, dass sich HEAD auf ein bestimmtes unbenanntes Commit bezieht (im Gegensatz zu einem benannten Zweig) (vgl.: Https://git-scm.com/docs/git-checkout Abschnitt Losgelöster Kopf )

Um das Problem zu beheben, müssen Sie nur den Zweig auswählen, der zuvor von ausgewählt wurde

git checkout @{-1}

Klopfen. ANDRIA
quelle
2

Wenn Sie sich in einer Situation mit getrenntem Kopf befinden und neue Dateien erstellt haben, stellen Sie zunächst sicher, dass diese neuen Dateien zum Index hinzugefügt werden, z. B.:

git add .

Wenn Sie jedoch nur vorhandene Dateien geändert oder gelöscht haben, können Sie gleichzeitig (-a) hinzufügen und mit einer Nachricht (-m) festschreiben über:

git commit -a -m "my adjustment message"

Dann können Sie einfach einen neuen Zweig mit Ihrem aktuellen Status erstellen mit:

git checkout -b new_branch_name

Sie haben einen neuen Zweig und alle Ihre Anpassungen werden in diesem neuen Zweig vorhanden sein. Sie können dann weiter auf die Fernbedienung drücken und / oder nach Belieben auschecken / ziehen / zusammenführen.

DZet
quelle
1

Git hat mir gesagt, wie es geht.

wenn Sie getippt haben:

git checkout <some-commit_number>

Speichern Sie den Status

git add .
git commit -m "some message"

Dann:

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

Ich wollte meine Änderungen behalten, also behebe ich das einfach ...

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

diese Arbeit für mich

CRLZXO
quelle
1

Zeigt normalerweise HEADauf einen Zweig. Wenn es nicht auf einen Zweig zeigt, sondern auf einen Commit-Hash 69e51, bedeutet dies, dass Sie einen getrennten HEAD haben. Sie müssen auf zwei Zweige zeigen, um das Problem zu beheben. Sie können zwei Dinge tun, um das Problem zu beheben.

  1. git checkout other_branch // Nicht möglich, wenn Sie den Code in diesem Commit benötigen hash
  2. Erstellen Sie einen neuen Zweig und verweisen Sie den Commit-Hash auf den neu erstellten Zweig.

HEAD muss auf einen Zweig zeigen, kein Commit-Hash ist die goldene Regel.

Krishnadas PC
quelle
Deshalb hatte ich genau diesen Fehler. Ich habe zu einer Revision ausgecheckt und dann wieder zur aktuellen / neuesten Revision ausgecheckt, anstatt zum Zweig auszuchecken, der den Kopf richtig befestigt hätte. Danke für die Hilfe.
Rahul Thakur
1

Abgelöster Kopf bedeutet, dass Sie Ihren Zweig nicht richtig ausgecheckt haben oder nur ein einzelnes Commit ausgecheckt haben.

Wenn Sie auf ein solches Problem stoßen, bewahren Sie zuerst Ihre lokalen Änderungen auf, damit Sie Ihre Änderungen nicht verlieren.

Danach ... checken Sie Ihren gewünschten Zweig mit dem folgenden Befehl aus:

Angenommen, Sie möchten den Zweig MyOriginalBranch:

git checkout -b someName origin / MyOriginalBranch

Dhirendra Gautam
quelle
1

du hast es wahrscheinlich getan git reset --hard origin/your-branch.

Versuche es einfach git checkout your-branch

Johnny Cage
quelle
0
git pull origin master

arbeitete für mich. Es ging nur darum, den Namen von Remote und Zweig explizit anzugeben.

Amjedonline
quelle
0

In meinem Fall habe ich ausgeführt git statusund festgestellt, dass sich in meinem Arbeitsverzeichnis einige nicht verfolgte Dateien befinden.

Ich musste sie nur reinigen (da ich sie nicht brauchte), um die Rebase auszuführen, die ich ausführen wollte.

Falsarella
quelle
0

Dies funktioniert bei mir. Es wird ein neuer Zweig für den abgetrennten Kopf zugewiesen:

git checkout neuer_zweig_name losgelöster_kopf_garbage_name

Alok Gupta
quelle
0

Der abgetrennte KOPF bedeutet, dass Sie sich derzeit in keinem Zweig befinden. Wenn Sie Ihre aktuellen Änderungen beibehalten und einfach einen neuen Zweig erstellen möchten, gehen Sie wie folgt vor:

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

Anschließend möchten Sie diesen neuen Zweig möglicherweise mit anderen Zweigen zusammenführen. Immer hilfreich ist der Befehl git "a dog" :

git log --all --decorate --oneline --graph
gebbissimo
quelle