Ich bin neu in der Verzweigungskomplexität von Git. Ich arbeite immer an einem einzelnen Zweig und schreibe Änderungen fest und drücke dann regelmäßig auf meinen entfernten Ursprung.
Vor kurzem habe ich einige Dateien zurückgesetzt, um sie aus dem Commit-Staging herauszuholen, und später rebase -i
einige lokale Commits entfernt. Jetzt bin ich in einem Zustand, den ich nicht ganz verstehe.
git log
Zeigt in meinem Arbeitsbereich genau, was ich erwarten würde - ich bin im richtigen Zug mit den Verpflichtungen, die ich nicht wollte, und neuen dort usw.
Aber ich habe nur in das Remote-Repository gepusht, und was da ist, ist anders - ein paar der Commits, die ich in der Rebase getötet hatte, wurden gepusht, und die neuen Commits, die lokal festgeschrieben wurden, sind nicht da.
Ich denke, "master / origin" ist von HEAD getrennt, aber ich bin nicht 100% klar, was das bedeutet, wie man es mit den Kommandozeilen-Tools visualisiert und wie man es behebt.
I did a reset of some files to get them out of commit staging
? Entschuldigung für die Fragen :)Antworten:
Lassen Sie uns zunächst klären, was HEAD ist und was es bedeutet, wenn es abgenommen wird.
HEAD ist der symbolische Name für das aktuell ausgecheckte Commit. Wenn HEAD nicht getrennt ist (die „normale“ Situation 1 : Sie haben einen Zweig ausgecheckt), zeigt HEAD tatsächlich auf den „ref“ eines Zweigs und der Zweig zeigt auf das Commit. HEAD ist somit an einen Zweig „gebunden“. Wenn Sie ein neues Commit durchführen, wird der Zweig, auf den HEAD zeigt, aktualisiert, um auf das neue Commit zu verweisen. HEAD folgt automatisch, da es nur auf den Zweig zeigt.
git symbolic-ref HEAD
Ausbeutenrefs/heads/master
Der Zweig mit dem Namen "master" wird ausgecheckt.
git rev-parse refs/heads/master
Yield17a02998078923f2d62811326d130de991d1a95a
Dieses Commit ist der aktuelle Tipp oder „Kopf“ des Hauptzweigs.
git rev-parse HEAD
ergibt auch17a02998078923f2d62811326d130de991d1a95a
Dies ist, was es bedeutet, ein "symbolischer Verweis" zu sein. Es zeigt durch eine andere Referenz auf ein Objekt.
(Symbolische Verweise wurden ursprünglich als symbolische Links implementiert, später jedoch in einfache Dateien mit zusätzlicher Interpretation geändert, damit sie auf Plattformen ohne Symlinks verwendet werden können.)
Wir haben
HEAD
→refs/heads/master
→17a02998078923f2d62811326d130de991d1a95a
Wenn HEAD getrennt ist, zeigt es direkt auf ein Commit - anstatt indirekt über einen Zweig auf eines zu verweisen. Sie können sich einen abgetrennten KOPF als einen unbenannten Zweig vorstellen.
git symbolic-ref HEAD
scheitert mitfatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
Renditen17a02998078923f2d62811326d130de991d1a95a
Da es sich nicht um einen symbolischen Verweis handelt, muss er direkt auf das Commit selbst verweisen.
Wir haben
HEAD
→17a02998078923f2d62811326d130de991d1a95a
Das Wichtigste, an das Sie sich bei einem abgetrennten HEAD erinnern sollten, ist, dass wenn das Commit, auf das es zeigt, ansonsten nicht referenziert ist (kein anderer Ref kann es erreichen), es beim Auschecken eines anderen Commits „baumelt“. Letztendlich werden solche baumelnden Commits durch den Garbage Collection-Prozess zurückgeschnitten (standardmäßig werden sie mindestens 2 Wochen lang aufbewahrt und können länger aufbewahrt werden, indem auf HEADs Reflog verwiesen wird).
1 Es ist vollkommen in Ordnung, „normale“ Arbeiten mit einem abgetrennten KOPF auszuführen. Sie müssen nur nachverfolgen, was Sie tun, um zu vermeiden, dass Sie die abgelaufene Geschichte aus dem Reflog heraus fischen müssen.
Die Zwischenschritte einer interaktiven Rebase werden mit einem abgetrennten HEAD ausgeführt (teilweise, um eine Verschmutzung des Reflogs des aktiven Zweigs zu vermeiden). Wenn Sie den vollständigen Rebase-Vorgang abgeschlossen haben, wird Ihr ursprünglicher Zweig mit dem kumulativen Ergebnis des Rebase-Vorgangs aktualisiert und HEAD erneut an den ursprünglichen Zweig angehängt. Ich vermute, dass Sie den Rebase-Prozess nie vollständig abgeschlossen haben. Dadurch erhalten Sie einen getrennten HEAD, der auf das Commit verweist, das zuletzt von der Rebase-Operation verarbeitet wurde.
Um sich von Ihrer Situation zu erholen, sollten Sie einen Zweig erstellen, der auf das Commit verweist, auf das Ihr losgelöster HEAD derzeit zeigt:
(Diese beiden Befehle können als abgekürzt werden.
git checkout -b temp
)Dadurch wird Ihr HEAD wieder mit dem neuen
temp
Zweig verbunden.Als Nächstes sollten Sie das aktuelle Commit (und seinen Verlauf) mit dem normalen Zweig vergleichen, an dem Sie voraussichtlich arbeiten werden:
(Sie möchten wahrscheinlich mit den Protokolloptionen experimentieren: Hinzufügen
-p
, weglassen--pretty=…
, um die gesamte Protokollnachricht anzuzeigen usw.)Wenn Ihr neuer
temp
Zweig gut aussieht, möchten Sie ihn möglicherweise aktualisieren (z. B.),master
um darauf zu verweisen:(Diese beiden Befehle können als abgekürzt werden.
git checkout -B master temp
)Sie können dann den temporären Zweig löschen:
Schließlich möchten Sie wahrscheinlich die wiederhergestellte Geschichte vorantreiben:
Möglicherweise müssen Sie
--force
am Ende dieses Befehls einen Push hinzufügen , wenn der Remote-Zweig nicht schnell zum neuen Commit weitergeleitet werden kann (dh Sie haben ein vorhandenes Commit gelöscht oder neu geschrieben oder auf andere Weise einen Teil des Verlaufs neu geschrieben).Wenn Sie sich mitten in einer Rebase-Operation befanden, sollten Sie diese wahrscheinlich bereinigen. Sie können überprüfen, ob eine Rebase ausgeführt wurde, indem Sie nach dem Verzeichnis suchen
.git/rebase-merge/
. 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 verwendengit rebase --abort
, aber das führt zu einem zusätzlichen Zurücksetzen, das Sie wahrscheinlich vermeiden möchten (es verschiebt HEAD zurück zum ursprünglichen Zweig und setzt es zurück zum ursprünglichen Commit, wodurch einige der oben geleisteten Arbeiten rückgängig gemacht werden).quelle
man git-symbolic-ref
: "In der Vergangenheit gab.git/HEAD
es einen symbolischen Link, auf den verwiesen wurderefs/heads/master
. Als wir zu einem anderen Zweig wechseln wollten, haben wir dies getanln -sf refs/heads/newbranch .git/HEAD
, und als wir herausfinden wollten, in welchem Zweig wir uns befinden, haben wir dies getanreadlink .git/HEAD
. Aber symbolische Links sind nicht vollständig portabel Daher sind sie jetzt veraltet und symbolische Verweise (wie oben beschrieben) werden standardmäßig verwendet. "git branch -f master HEAD && git checkout master
ist genug - vorausgesetzt, Ihr Ziel ist es, Ihren aktuellen Kopf zu behalten, ihn aber als zu bezeichnenmaster
. Andere Ziele sind ebenfalls sinnvoll und erfordern andere Rezepte.Mach das einfach:
Wenn Sie Änderungen haben, die Sie beibehalten möchten, gehen Sie folgendermaßen vor:
quelle
git reset
sollte mit einer Warnung kommen "Wenn Sie keine Ahnung haben, was Sie tun, hören Sie auf". Ich habe mich gerade von einer Stunde des Terrors erholt und gedacht, ich hätte die letzte Arbeitswoche verloren. Vielen Dank!Ich bin auf dieses Problem gestoßen und als ich die am besten gewählte Antwort gelesen habe:
Ich dachte: Ah-ha! Wenn
HEAD
der symbolische Name für das aktuelle Checkout-Commit lautet, kann ich ihnmaster
abgleichen, indem ich ihn gegen Folgendes umbasieremaster
:Dieser Befehl:
master
HEAD
back bis zu dem Punkt, von demHEAD
abgewichen wirdmaster
master
Das Endergebnis ist, dass alle Commits, die in waren,
HEAD
aber nicht,master
dann auch in sindmaster
.master
bleibt ausgecheckt.In Bezug auf die Fernbedienung:
Der Remote-Verlauf kann nicht mehr mithilfe Ihres lokalen Verlaufs vorgespult werden. Sie müssen push (
git push -f
) erzwingen, um den Remote-Verlauf zu überschreiben. Wenn Sie Mitarbeiter haben, ist es normalerweise sinnvoll, dies mit ihnen zu koordinieren, damit alle auf derselben Seite sind.Nachdem Sie
master
auf Remote gedrückt habenorigin
, wird Ihr Remote-Tracking-Zweigorigin/master
so aktualisiert, dass er auf dasselbe Commit wie verweistmaster
.quelle
Hier finden Sie eine grundlegende Erklärung für den abgetrennten Kopf:
http://git-scm.com/docs/git-checkout
Befehlszeile zur Visualisierung:
oder
Sie erhalten die Ausgabe wie folgt:
Die
* (no branch)
zeigt, dass Sie in losgelöstem Kopf sind.Sie hätten durch ein
git checkout somecommit
usw. in diesen Zustand gelangen können, und es hätte Sie mit folgenden Warnungen gewarnt:Nun, um sie auf den Meister zu bringen:
Machen Sie ein
git reflog
oder auch nurgit log
und notieren Sie Ihre Commits. Nungit checkout master
undgit merge
die Commits.Bearbeiten:
Verwenden Sie zum Hinzufügen
git rebase -i
nicht nur das Löschen / Beenden von nicht benötigten Commits, sondern auch das Bearbeiten. Erwähnen Sie einfach "Bearbeiten" in der Festschreibungsliste, und Sie können Ihr Festschreiben ändern und dann ein "Weiter" ausstellengit rebase --continue
. Dies hätte sichergestellt, dass Sie nie zu einem freistehenden KOPF gekommen sind.quelle
Holen Sie sich Ihr freistehendes Commit in einen eigenen Zweig
Einfach laufen
git checkout -b mynewbranch
.Führen
git log
Sie dann aus , und Sie werden sehen, dass sich das Commit jetztHEAD
in diesem neuen Zweig befindet.quelle
mynewbranch
an irgendetwas?Wenn Sie nur einen Hauptzweig haben und zurück zum "Entwickeln" oder einer Funktion möchten, gehen Sie wie folgt vor:
Hinweis: Herkunft / Entwicklung auschecken .
Sie befinden sich im getrennten HEAD- Zustand. Sie können sich umschauen, experimentelle Änderungen vornehmen und diese festschreiben, und Sie können alle in diesem Zustand vorgenommenen Festschreibungen verwerfen, ohne Auswirkungen auf Zweige zu haben, indem Sie eine weitere Prüfung durchführen ...
dann
Es klappt :)
quelle
Wenn Sie Ihren aktuellen abgetrennten KOPF drücken möchten (
git log
vorher prüfen ), versuchen Sie:um Ihren abgetrennten HEAD am Ursprung in die Hauptniederlassung zu senden. Wenn Ihr Push abgelehnt wird, versuchen Sie
git pull origin master
zuerst, die Änderungen vom Ursprung zu erhalten. Wenn Sie sich nicht um die Änderungen vom Ursprung kümmern und diese abgelehnt werden, weil Sie eine absichtliche Neugründung vorgenommen haben und Ursprung / Master durch Ihren derzeit getrennten Zweig ersetzen möchten, können Sie dies erzwingen (-f
). Falls Sie den Zugriff auf frühere Commits verloren haben, können Sie jederzeitgit reflog
den Verlauf aller Zweige anzeigen.Führen Sie die folgenden Befehle aus, um unter Beibehaltung der Änderungen zu einem Hauptzweig zurückzukehren:
Siehe: Git: "Derzeit in keinem Zweig." Gibt es eine einfache Möglichkeit, zu einem Zweig zurückzukehren, während die Änderungen beibehalten werden?
quelle
Ich habe diese Frage bei der Suche gefunden
You are in 'detached HEAD' state.
Nachdem ich analysiert hatte, was ich getan hatte, um hierher zu kommen, stellte ich im Vergleich zu dem, was ich in der Vergangenheit getan hatte, fest, dass ich einen Fehler gemacht hatte.
Mein normaler Fluss ist:
Diesmal habe ich:
Das Problem ist, dass ich versehentlich getan habe:
Eher, als:
Die Lösung (in meiner Situation) bestand einfach darin, den obigen Befehl auszuführen und dann den Ablauf fortzusetzen:
quelle
Folgendes hat bei mir funktioniert (nur mit Zweigstellenmaster):
Der erste schiebt den abgetrennten KOPF zum entfernten Ursprung.
Der zweite wechselt zum Zweigmaster.
Der dritte stellt den HEAD wieder her, der an den Zweigstellenmaster angehängt wird.
Beim ersten Befehl können Probleme auftreten, wenn der Push abgelehnt wird. Dies wäre jedoch kein Problem mehr mit abgenommenem Kopf, sondern mit der Tatsache, dass dem abgetrennten KOPF einige entfernte Änderungen nicht bekannt sind.
quelle
Ich bin heute auf dieses Problem gestoßen und bin mir ziemlich sicher, dass ich es folgendermaßen gelöst habe:
Ich war auf meinem Arbeitscomputer, als ich herausfand, wie das geht, und jetzt stoße ich auf meinem PC auf dasselbe Problem. Ich muss also bis Montag warten, bis ich wieder am Arbeitscomputer bin, um genau zu sehen, wie ich es gemacht habe.
quelle
Wenn Sie ganz sicher sind, dass HEAD der gute Zustand ist:
Sie können wahrscheinlich nicht zum Ursprung drängen, da Ihr Meister vom Ursprung abgewichen ist. Wenn Sie sicher sind, dass niemand anderes das Repo verwendet, können Sie Folgendes erzwingen:
Am nützlichsten, wenn Sie sich in einem Feature-Zweig befinden, den sonst niemand verwendet.
quelle
Alles, was Sie tun müssen, ist 'git checkout [Filialname]', wobei [Filialname] der Name des ursprünglichen Zweigs ist, von dem Sie in einen getrennten Kopfzustand geraten sind. Das (von asdfasdf getrennt) verschwindet.
In der Verzweigung 'dev' checken Sie beispielsweise das Commit asdfasd14314 -> aus
Sie befinden sich jetzt in einem Zustand mit losgelöstem Kopf
'git branch' listet so etwas wie -> auf
aber um aus dem losgelösten Kopfzustand herauszukommen und zurück zu dev ->
und dann wird 'git branch' aufgelistet ->
Aber das ist natürlich so, wenn Sie nicht beabsichtigen, Änderungen aus dem Zustand des abgetrennten Kopfes beizubehalten, aber ich tue dies häufig, ohne Änderungen vorzunehmen, sondern nur, um mir ein vorheriges Commit anzusehen
quelle
Wie Chris sagte, hatte ich folgende Situation
git symbolic-ref HEAD
scheitert mitfatal: ref HEAD is not a symbolic ref
Es wurde jedoch
git rev-parse refs/heads/master
auf ein gutes Commit hingewiesen, von dem ich mich erholen konnte (in meinem Fall das letzte Commit, und Sie können dieses Commit mithilfe von sehengit show [SHA]
Danach habe ich viele unordentliche Dinge getan, aber was behoben zu sein scheint, ist nur,
git symbolic-ref HEAD refs/heads/master
Und der Kopf ist wieder angebracht!
quelle
Anstatt zu tun
git checkout origin/master
mach einfach
git checkout master
Dann
git branch
wird Ihre Filiale bestätigt.quelle
Ich hatte heute dieses Problem, bei dem ich ein Submodul aktualisiert hatte, aber in keinem Zweig war. Ich hatte mich bereits verpflichtet, also würde das Verstauen, Auschecken und Entstauen nicht funktionieren. Am Ende pflückte ich das Commit des abgetrennten Kopfes. Unmittelbar nach dem Festschreiben (als der Push fehlschlug) tat ich Folgendes:
Mein Gedanke war: Ich bin auf einem distanzierten Kopf, aber ich möchte Meister werden. Angenommen, mein losgelöster Zustand unterscheidet sich nicht sehr vom Master. Wenn ich mein Commit auf den Master anwenden könnte, wäre ich festgelegt. Genau das macht Cherry-Pick.
quelle
Wenn Sie haben einige Commits auf dem Master und wollen einfach nur „rückwärts merge“
master
dort (dh wollen Siemaster
zu PunktHEAD
), die Einzeiler sein würden:master
, auch wenn er bereits vorhanden ist (was wie ein Umzug istmaster
und das wollen wir).HEAD
, wo Sie sich befinden.master
danach eingeschaltet sind.Ich fand dies besonders nützlich bei Unter-Repositorys, die sich auch ziemlich oft in einem getrennten Zustand befinden.
quelle
Ich hatte das gleiche Problem und habe es durch die folgenden Schritte gelöst.
Wenn Sie Ihre Änderungen behalten müssen
git checkout master
Befehl ausführen , um zum Hauptzweig zurückzukehren.git checkout -b changes
und ausgit checkout -B master changes
Wenn Sie Ihre Änderungen nicht benötigen
So entfernen Sie alle nicht verfolgten Dateien aus Ihrem Zweiglauf
git clean -df
.Dann müssen Sie alle nicht bereitgestellten Änderungen in Ihrem Repository löschen. Dazu muss man laufen
git checkout --
Schließlich müssen Sie Ihren Zweig mit dem
git checkout master
Befehl wieder in den Hauptzweig zurückversetzen .quelle
Für mich war es so einfach wie das erneute Löschen der lokalen Niederlassung, da ich keine lokalen Commits hatte, die ich pushen wollte:
So tat ich:
Und dann nochmal die Filiale auschecken:
quelle
Wenn ich mich persönlich in einer Situation befinde, in der sich herausstellt, dass ich einige Änderungen vorgenommen habe, während ich nicht in der Lage bin
master
(dhHEAD
direkt über dermaster
Position abgesetzt bin und dazwischen keine Commits liegen), kann das Verstauen helfen:quelle
In einfachen Worten bedeutet der getrennte HEAD-Status, dass Sie nicht zum HEAD (oder zur Spitze) eines Zweigs ausgecheckt sind .
Mit einem Beispiel verstehen
Ein Zweig ist in den meisten Fällen eine Folge mehrerer Commits wie:
Commit 1: master -> branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)
Commit 2: master -> 123be6a76168aca712aea16076e971c23835f8ca -> branch_HEAD (100644a76168aca712aea16076e971c23835f8ca)
Wie Sie oben bei einer Abfolge von Festschreibungen sehen können, verweist Ihre Verzweigung auf Ihre letzte Festschreibung. Wenn Sie also in diesem Fall auschecken , um 123be6a76168aca712aea16076e971c23835f8ca festzuschreiben , befinden Sie sich in einem getrennten Kopfzustand, da HEAD Ihrer Verzweigung auf 100644a76168aca712aea16076e971c23835f8ca verweist und Sie technisch an HEAD of no branch ausgecheckt sind. Sie befinden sich also im getrennten HEAD-Zustand.
Theoretische Erklärung
In diesem Blog heißt es eindeutig, dass ein Git-Repository ein Commit-Baum ist, wobei jedes Commit auf seinen Vorfahren verweist, wobei jeder Commit-Zeiger aktualisiert wird und diese Zeiger auf jeden Zweig in den Unterverzeichnissen .git / refs gespeichert werden. Tags werden in .git / refs / tags und Zweige in .git / refs / Heads gespeichert. Wenn Sie sich eine der Dateien ansehen, werden Sie feststellen, dass jedes Tag einer einzelnen Datei mit einem 40-stelligen Commit-Hash entspricht. Wie oben von @Chris Johnsen und @Yaroslav Nikitenko erläutert, können Sie diese Referenzen überprüfen.
quelle
Ich bin in einen wirklich dummen Zustand geraten, ich bezweifle, dass irgendjemand dies nützlich finden wird ... aber nur für den Fall
was ich schließlich mit behoben habe
quelle
Das hat bei mir perfekt funktioniert:
1.
git stash
um Ihre lokalen Änderungen zu speichernWenn Sie Änderungen verwerfen möchten,
git clean -df
git checkout -- .
entfernt git clean alle nicht verfolgten Dateien (Warnung: Ignorierte Dateien, die direkt in .gitignore erwähnt werden, werden möglicherweise nicht gelöscht, ignorierte Dateien in Ordnern werden möglicherweise gelöscht) und git checkout löscht alle nicht bereitgestellten Änderungen.
2.
git checkout master
zum Hauptzweig wechseln (vorausgesetzt, Sie möchten Master verwenden)3. Das
git pull
letzte Commit aus dem Hauptzweig ziehen4.
git status
um zu überprüfen, ob alles gut aussiehtquelle
In meinem Fall lief ich
git status
und sah, dass ich einige nicht verfolgte Dateien in meinem Arbeitsverzeichnis hatte.Damit die Rebase funktioniert, musste ich sie nur reinigen (da ich sie nicht brauchte).
quelle
Wenn Sie EGit in Eclipse verwenden: Nehmen Sie an, Ihr Master ist Ihr Hauptentwicklungszweig
Danach sollten Sie wieder mit dem Ursprungsmaster verbunden werden können.
quelle
Ich hatte das gleiche Problem. Ich habe meine Änderungen mit gespeichert
git stash
und den Zweig in local auf ein vorheriges Commit zurückgesetzt (ich dachte, das hat das verursacht), dann habegit pull
ich ein und ich bekomme diesen Kopf jetzt nicht losgelöst. Vergessen Sie nichtgit stash apply
, Ihre Änderungen erneut vorzunehmen.quelle
quelle