git - update - Wie kann ich losgelöste HEAD mit Master/Herkunft abgleichen?




update git windows (16)

Ich bin neu in den verzweigten Komplexitäten von Git. Ich arbeite immer an einem einzelnen Zweig und begehe Änderungen und drehe dann regelmäßig zu meinem entfernten Ursprung.

Irgendwann habe ich einige Dateien zurückgesetzt, um sie aus dem Commit-Staging zu rebase -i , und später habe rebase -i eine rebase -i , um ein paar kürzlich durchgeführte lokale Commits loszuwerden. Jetzt bin ich in einem Zustand, den ich nicht ganz verstehe.

In meinem Arbeitsbereich zeigt git log genau das, was ich erwarten würde-- Ich bin auf dem richtigen Zug mit den Commits, die ich nicht wollte, und neuen da, etc.

Aber ich schob mich einfach zum Remote-Repository, und was dort ist, ist anders - ein paar der Commits, die ich in der Rebase getötet hatte, wurden gedrängt, und die neuen, die lokal begangen wurden, sind nicht da.

Ich denke, dass "Master / Ursprung" von HEAD getrennt ist, aber ich weiß nicht 100%, was das bedeutet, wie man es mit den Befehlszeilenwerkzeugen visualisiert und wie man es repariert.


Bringen Sie Ihr detachiertes Commit in eine eigene Verzweigung

Führen Sie einfach git checkout -b mynewbranch .

Führen Sie dann git log , und Sie werden sehen, dass das Commit jetzt HEAD in diesem neuen Zweig ist.


Alles, was Sie tun müssen, ist 'git checkout [branch-name]', wobei [branch-name] der Name des ursprünglichen Zweiges ist, von dem Sie in einen losgelösten Kopfstatus gelangt sind. Das (von asdfasdf losgelöste) wird verschwinden.

So, zum Beispiel, im Zweig 'dev' checkst du das Commit asdfasd14314 ->

'git checkout asdfasd14314'

Sie sind jetzt in einem losgelösten Kopfzustand

'Git Branch' wird etwas wie -> auflisten

* (detached from asdfasdf)
  dev
  prod
  stage

aber um aus dem losgelösten Kopfzustand zu kommen und zurück zu dev ->

'git checkout dev'

und dann 'git branch' wird Liste ->

* dev
  prod
  stage

aber das ist natürlich, wenn du nicht vorhast, irgendwelche Veränderungen aus dem losgelösten Kopfzustand zu halten, aber ich merke, dass ich das viel mache, nicht vorhabe, irgendwelche Änderungen vorzunehmen, sondern nur ein vorheriges Commit zu betrachten


Das hat für mich perfekt funktioniert:

1. git stash , um Ihre lokalen Änderungen zu speichern

Wenn Sie Änderungen verwerfen möchten
git clean -df
git checkout -- .
git clean entfernt alle nicht verfolgten Dateien (Warnung: Während ignorierte Dateien, die direkt in .gitignore erwähnt werden, nicht gelöscht werden, können ignorierte Dateien in Ordnern gelöscht werden) und git checkout löscht alle nicht gespeicherten Änderungen.

2. git checkout master , um zum Hauptzweig zu wechseln (Angenommen, Sie möchten den Master verwenden)
3. git pull , um den letzten Commit vom Master-Zweig zu ziehen
4. git status , um alles gut aussehen zu überprüfen

On branch master
Your branch is up-to-date with 'origin/master'.

Für mich war es so einfach, den lokalen Zweig wieder zu löschen, da ich keine lokalen Commits hatte, die ich pushen wollte:

Also habe ich: git Branch -d Branchname

und dann den Zweig erneut prüfen

git Kasse Branchname


Ich bin auf dieses Problem gestoßen und als ich in der obersten Antwort die Antwort gelesen habe:

HEAD ist der symbolische Name für das aktuell ausgecheckte Commit.

Ich dachte: Ah-ha! Wenn HEAD der symbolische Name für den aktuellen Checkout-Commit ist, kann ich ihn mit dem master abgleichen, indem ich ihn gegen den master reverse:

git rebase HEAD master

Dieser Befehl:

  1. überprüft master
  2. identifiziert die Eltern-Commits von HEAD zurück bis zu dem Punkt, wo HEAD vom master abweicht
  3. spielt diese Commits auf master

Das Endergebnis ist, dass alle Commits, die in HEAD aber nicht master dann auch in master . master bleibt ausgecheckt.

Bezüglich der Fernbedienung:

ein paar der Commits, die ich in der Rebase getötet hatte, wurden gedrängt, und die Neuen, die ich vor Ort engagiert habe, sind nicht da.

Die Remote-Historie kann nicht mehr mit Ihrer lokalen Historie weitergeleitet werden. Sie müssen force-push ( git push -f ) drücken, git push -f zu überschreiben. Wenn Sie Kollaborateure haben, ist es normalerweise sinnvoll, dies mit ihnen zu koordinieren, damit alle auf derselben Seite sind.

Nachdem Sie den master an den Remote- origin verschoben haben, wird Ihr Remote-Tracking-Zweig- origin/master so aktualisiert, dass er auf denselben Commit wie der master .


Ich bin heute auf dieses Problem gestoßen. Ziemlich sicher, dass ich es gelöst habe, indem ich Folgendes gemacht habe:

git branch temp
git checkout master
git merge temp

Ich war auf meinem Arbeitscomputer, als ich herausgefunden habe, wie das geht, und jetzt stoße ich auf das gleiche Problem bei meinem persönlichen Computer. Also werde ich bis Montag warten müssen, wenn ich wieder bei der Arbeit bin, um genau zu sehen, wie ich es gemacht habe.


Ich hatte das gleiche Problem und habe es gelöst, indem ich die folgenden Schritte durchführte.

Wenn Sie Ihre Änderungen beibehalten müssen

  1. Zuerst müssen Sie den Befehl git checkout master ausführen, um Sie zurück in den Master-Zweig zu versetzen.
  2. Wenn Sie Ihre Änderungen git checkout -b changes müssen, führen Sie einfach gut git checkout -b changes und git checkout -B master changes

Wenn Sie Ihre Änderungen nicht benötigen

  1. Um alle nicht verfolgten Dateien aus Ihrem Zweig zu entfernen, führen Sie git clean -df .

  2. Dann müssen Sie alle nicht geänderten Änderungen in Ihrem Repository löschen. Um das zu tun, musst du git checkout -- ausführen git checkout --

  3. Schließlich müssen Sie Ihren Zweig mit dem Befehl git checkout master in den Master-Zweig zurückversetzen.


Ich hatte dieses Problem heute, wo ich ein Submodul aktualisiert hatte, aber in keinem Zweig war. Ich hatte bereits zugesagt, also Versteckt, Kasse, Entladen würde nicht funktionieren. Ich endete damit, dass ich den Commit des abgetrennten Kopfs herauspickte. Also sofort nachdem ich festgenommen hatte (als der Push fehlschlug), tat ich:

git checkout master
git cherry-pick 99fe23ab

Mein Denken ging: Ich bin auf einem distanzierten Kopf, aber ich möchte auf Meister sein. Angenommen, mein losgelöster Zustand unterscheidet sich nicht wesentlich vom Master, wenn ich meinen Commit auf Master anwenden könnte, wäre ich eingestellt. Genau das macht Cherry-Pick.


Lasst uns zuerst klären, was HEAD ist und was es bedeutet, wenn es losgelöst ist.

HEAD ist der symbolische Name für das aktuell ausgecheckte Commit. Wenn HEAD nicht losgelöst ist (die "normale" 1- Situation: Sie haben einen Zweig ausgecheckt), zeigt HEAD tatsächlich auf einen Zweig "ref" und der Zweig zeigt auf den Commit. HEAD wird also an einen Zweig "angehängt". Wenn Sie ein neues Commit durchführen, wird der Zweig, auf den HEAD zeigt, aktualisiert, um auf das neue Commit zu zeigen. HEAD folgt automatisch, da es nur auf den Zweig zeigt.

  • git symbolic-ref HEAD liefert refs/heads/master
    Der Zweig namens "Master" ist ausgecheckt.
  • git rev-parse refs/heads/master Ausbeute 17a02998078923f2d62811326d130de991d1a95a
    Dieser Commit ist der aktuelle Tipp oder "Kopf" des Master-Zweiges.
  • git rev-parse HEAD 17a02998078923f2d62811326d130de991d1a95a git rev-parse HEAD liefert auch 17a02998078923f2d62811326d130de991d1a95a
    Dies ist es, was es bedeutet, ein "symbolischer Verweis" zu sein. Es zeigt auf ein Objekt durch eine andere Referenz.
    (Symbolische Referenzen wurden ursprünglich als symbolische Links implementiert, später aber in einfache Dateien mit zusätzlicher Interpretation umgewandelt, so dass sie auf Plattformen ohne symbolische Links verwendet werden konnten.)

Wir haben HEADrefs/heads/master17a02998078923f2d62811326d130de991d1a95a

Wenn HEAD losgelöst ist, zeigt es direkt auf einen Commit - anstatt indirekt über einen Zweig auf einen zu zeigen. Du kannst dir einen abgetrennten HEAD als einen unbenannten Ast vorstellen.

  • git symbolic-ref HEAD schlägt mit fatal: ref HEAD is not a symbolic ref fehl fatal: ref HEAD is not a symbolic ref
  • git rev-parse HEAD 17a02998078923f2d62811326d130de991d1a95a git rev-parse HEAD ergibt 17a02998078923f2d62811326d130de991d1a95a
    Da es kein symbolischer Verweis ist, muss es direkt auf das Commit selbst verweisen.

Wir haben 17a02998078923f2d62811326d130de991d1a95a17a02998078923f2d62811326d130de991d1a95a

Die wichtige Sache, die man sich bei einem abgetrennten HEAD merken sollte, ist, dass, wenn das Commit, auf das es zeigt, ansonsten nicht referenziert wird (kein anderer Ref kann es erreichen), wird es "baumeln", wenn man einen anderen Commit auscheckt. Eventuell werden solche dangling commits durch den Garbage-Collection-Prozess bereinigt (standardmäßig werden sie für mindestens 2 Wochen aufbewahrt und können länger aufbewahrt werden, indem sie vom HEAD-Reflog referenziert werden).

1 Es ist vollkommen in Ordnung, "normale" Arbeit mit einem abgetrennten HEAD zu machen, du musst nur den Überblick behalten, was du machst, um zu vermeiden, dass vergangene Geschichte aus dem Reflog gefischt werden muss.

Die Zwischenschritte einer interaktiven Rebase werden mit einem abgetrennten HEAD durchgeführt (teilweise, um den Reflog des aktiven Zweiges nicht zu verschmutzen). Wenn Sie die vollständige Umbuchen-Operation abgeschlossen haben, wird Ihre ursprüngliche Verzweigung mit dem kumulativen Ergebnis der Umbuchen-Operation aktualisiert und HEAD an die ursprüngliche Verzweigung wieder angehängt. Meine Vermutung ist, dass Sie den Rebase-Prozess nie vollständig abgeschlossen haben; Dies wird Sie mit einem abgetrennten HEAD verlassen, der auf das Commit zeigt, das zuletzt von der Rebase-Operation verarbeitet wurde.

Um Ihre Situation wiederherzustellen, sollten Sie einen Zweig erstellen, der auf den Commit verweist, auf den Ihr abgetrennter HEAD momentan zeigt:

git branch temp
git checkout temp

(Diese beiden Befehle können abgekürzt werden als git checkout -b temp )

Dadurch wird Ihr HEAD an den neuen temp Zweig angeschlossen.

Als Nächstes sollten Sie das aktuelle Commit (und dessen Verlauf) mit dem normalen Zweig vergleichen, für den Sie erwartet haben zu arbeiten:

git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp

(Wahrscheinlich möchten Sie mit den Protokolloptionen experimentieren: add -p , --pretty=… , um die gesamte Protokollnachricht usw. zu sehen.)

Wenn Ihr neuer temp Zweig gut aussieht, möchten Sie vielleicht (zB) den master aktualisieren, um auf ihn zu zeigen:

git branch -f master temp
git checkout master

(Diese beiden Befehle können abgekürzt werden als git checkout -B master temp )

Sie können dann die temporäre Verzweigung löschen:

git branch -d temp

Schließlich werden Sie wahrscheinlich die wiederhergestellte Geschichte fortsetzen wollen:

git push origin master

Sie müssen möglicherweise --force an das Ende dieses Befehls hinzufügen, um zu --force , die entfernte Verzweigung nicht "schnell" an die neue --force " (d. --force , Sie haben eine bestehende --force gelöscht oder neu geschrieben oder einen anderen Verlauf neu geschrieben ).

Wenn Sie sich gerade in einer Rebase-Operation befinden, sollten Sie diese wahrscheinlich bereinigen. Sie können überprüfen, ob eine Rebase in Bearbeitung war, indem Sie nach dem Verzeichnis .git/rebase-merge/ suchen. Sie können die laufende Rebase manuell bereinigen, indem Sie nur dieses Verzeichnis löschen (z. B. wenn Sie sich nicht mehr an den Zweck und den Kontext der aktiven Rebase-Operation erinnern). Normalerweise würden Sie git rebase --abort , aber das führt zu einem zusätzlichen Zurücksetzen, das Sie wahrscheinlich vermeiden möchten (es verschiebt HEAD zurück in den ursprünglichen Zweig und setzt es zurück auf das ursprüngliche Commit, wodurch einige der oben ausgeführten Arbeiten rückgängig gemacht werden ).


Mach einfach folgendes:

git checkout master

Oder, wenn Sie Änderungen haben, die Sie behalten möchten, tun Sie Folgendes:

git checkout -b temp
git checkout -B master temp

Vereinfacht bedeutet das, dass Sie nicht zum HEAD (oder Tip) eines Zweigs ausgecheckt sind .

Mit Beispiel verstehen

Ein Zweig in den meisten Fällen ist eine Folge von mehreren Commits wie:

commit 1: master -> branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)

commit 2: Master -> 123be6a76168aca712aea160e971c23835f8ca -> branch_HEAD (100644a76168aca712aea16076e971c23835f8ca)

Wie Sie oben sehen können, zeigt Ihre Verzweigung im Falle einer Sequenz von Commits auf Ihre letzte Commit. Also in diesem Fall, wenn Sie auschecken , um 123be6a76168aca712aea16076e971c23835f8ca zu begehen, dann würden Sie in losgelöstem Kopfstatus sein, da HEAD Ihrer Verzweigung auf 100644a76168aca712aea16076e971c23835f8ca zeigt und technisch sind Sie bei HEAD of no branch ausgecheckt. Daher befinden Sie sich in losgelöstem HEAD-Zustand

Theoretische Erklärung

In diesem Blog ist das Git-Repository eindeutig ein Baum von Commits, wobei jedes Commit auf seinen Vorgänger zeigt, wobei jeder Commit-Pointer aktualisiert wird und diese Pointer auf jeden Zweig in den .git / refs-Unterverzeichnissen gespeichert werden. Tags werden in .git / refs / tags gespeichert und Verzweigungen werden in .git / refs / heads gespeichert. Wenn Sie sich die Dateien ansehen, werden Sie feststellen, dass jedes Tag einer einzelnen Datei mit einem 40-stelligen Commit-Hash entspricht und wie oben von @Chris Johnsen und @Yaroslav Nikitenko erklärt, können Sie diese Referenzen lesen


Wenn Sie egit in Eclipse verwenden: Nehmen Sie an, Ihr Master ist Ihr Hauptentwicklungszweig

  • Übernehmen Sie Änderungen an einem Zweig, normalerweise einem neuen Zweig
  • dann ziehe von der Fernbedienung
  • Klicken Sie dann mit der rechten Maustaste auf den Projektknoten, wählen Sie Team und dann Showhistory
  • Klicken Sie dann mit der rechten Maustaste auf den Master, und wählen Sie Auschecken
  • Wenn Eclipse Ihnen sagt, gibt es zwei Master eine lokale Fernbedienung, wählen Sie die Fernbedienung

Danach sollten Sie in der Lage sein, sich wieder an den Ursprungs-Master anzuhängen


Wenn Sie nur den Zweig beherrschen und wieder "entwickeln" wollen oder ein Feature, dann machen Sie das einfach:

git checkout origin/develop

Hinweis: Herkunft prüfen / entwickeln .

Sie befinden sich in einem getrennten HEAD- Zustand. Sie können sich umsehen, experimentelle Änderungen vornehmen und sie festschreiben, und Sie können alle von Ihnen vorgenommenen Commits in diesem Zustand verwerfen, ohne die Zweige zu beeinträchtigen, indem Sie einen weiteren Checkout durchführen ...

dann

git checkout -b develop

Es klappt :)


Wenn du deinen aktuellen, abgekoppelten HEAD drücken willst (prüfe vorher git log ), probiere:

git push origin HEAD:master

um deinen abgetrennten HEAD im Ursprungszweig in den Masterzweig zu senden. Wenn dein Push abgelehnt wird, versuche git pull origin master zu git pull origin master , um die Änderungen vom Ursprung zu erhalten. Wenn Sie sich nicht um die Änderungen aus dem Ursprung kümmern und diese abgelehnt werden, weil Sie eine absichtliche Rebase ausgeführt haben und Sie den Ursprung / Master durch Ihren derzeit getrennten Zweig ersetzen möchten, dann können Sie ihn erzwingen ( -f ). Falls Sie Zugriff auf frühere Commits verloren haben, können Sie git reflog immer git reflog , um den Verlauf aller Zweige zu sehen.

Versuchen Sie die folgenden Befehle, um einen Master-Zweig wiederherzustellen, während Sie die Änderungen beibehalten:

git rebase HEAD master
git checkout master

Siehe: Git: "Derzeit nicht in einem Zweig." Gibt es einen einfachen Weg, um in einen Zweig zurückzukehren, während die Änderungen beibehalten werden?


Wenn ich mich persönlich in einer Situation befinde, in der es sich herausstellt, dass ich einige Veränderungen vorgenommen habe, während ich nicht im master bin (dh HEAD ist direkt über dem master gelöst und es gibt keine Zwischentöne dazwischen), könnte Verstecken helfen:

git stash # HEAD has same content as master, but we are still not in master
git checkout master  # switch to master, okay because no changes and master
git stash apply  # apply changes we had between HEAD and master in the first place

Wie Chris zeigte, hatte ich folgende Situation

git symbolic-ref HEAD schlägt mit fatal: ref HEAD is not a symbolic ref fehl fatal: ref HEAD is not a symbolic ref

Wie auch immer, git rev-parse refs/heads/master zeigte auf einen guten Commit, von dem aus ich wiederherstellen konnte (In meinem Fall letzter Commit und Sie können diesen Commit sehen, indem Sie git show [SHA]

Ich habe danach eine Menge unordentlicher Dinge gemacht, aber was anscheinend behoben ist, ist

git symbolic-ref HEAD refs/heads/master

Und der Kopf ist wieder angebracht!





git