HEAD und ORIG_HEAD in Git

252

Worauf beziehen sich diese Symbole und was bedeuten sie?

(Ich kann keine Erklärung in der offiziellen Dokumentation finden)

Collimarco
quelle
4
Hinweis: HEADist jetzt (kommende git1.8.4) ' @'! Siehe meine bearbeitete Antwort unten
VonC
Hinweis-bis: ' @' (für HEAD) kommt noch, aber nicht für 1.8.4 Antwort bearbeitet und geändert .
VonC
1
Hinweis ter: ' @' for HEADist zurück für git 1.8.5 / 1.9. Antwort erneut bearbeitet .
VonC
21
HEADund ORIG_HEADin Git sind wie $PWDund $OLDPWDin Bash. :)
Musiphil

Antworten:

325

HEADist ein (direkter oder indirekter, dh symbolischer) Verweis auf das aktuelle Commit. Es ist ein Commit, das Sie im Arbeitsverzeichnis eingecheckt haben (es sei denn, Sie haben einige oder gleichwertige Änderungen vorgenommen), und es ist ein Commit, über das "git commit" ein neues machen würde. Normalerweise HEADist es ein symbolischer Verweis auf einen anderen benannten Zweig; Dieser Zweig ist derzeit ausgecheckt oder aktueller Zweig. HEADkann auch direkt auf ein Commit verweisen; Dieser Zustand wird als "losgelöster KOPF" bezeichnet und kann als unbenannter, anonymer Zweig verstanden werden.

Und @allein ist eine Abkürzung für HEAD, seit Git 1.8.5

ORIG_HEADist der vorherige Status von HEAD, der durch Befehle festgelegt wird, die möglicherweise ein gefährliches Verhalten aufweisen, damit sie leicht zurückgesetzt werden können. Es ist jetzt weniger nützlich, da Git ein Reflog hat: HEAD@{1}ist ungefähr gleichbedeutend mit ORIG_HEAD( HEAD@{1}ist immer der letzte Wert von HEAD, ORIG_HEADist der letzte Wert von HEADvor einer gefährlichen Operation).

Weitere Informationen finden Sie in der git (1) -Manpage , im Git-Benutzerhandbuch , im Git-Community-Buch und im Git-Glossar

Jakub Narębski
quelle
2
Hallo Jakub. +1 für die Erklärung. Könnten Sie den "ungefähr äquivalenten" Teil von HEAD @ {1} detaillieren? Ich verweise in meiner Antwort auf den Thread thread.gmane.org/gmane.comp.version-control.git/38379 (Sie waren bereits im Februar 2007 dabei), und ich habe die Diskussion, die Sie geführt haben, nicht genau verstanden die @ {...} Syntax.
VonC
19
ORIG_HEAD wird (glaube ich) nur durch 'gefährliche' Befehle gesetzt, die HEAD mehr als ein Commit verschieben. ORIG_HEAD ist also nicht immer gesetzt, während HEAD @ {1} immer gesetzt ist. @ {1} ist $ (git symbolic-ref HEAD) @ {1}, dh es wird Reflog für den aktuellen Zweig verwendet, nicht HEAD Reflog.
Jakub Narębski
Riiight ... ich verstehe es jetzt :) Danke für diese Klarstellung. Für das, was es wert ist, habe ich auch Ihren Kommentar positiv bewertet!
VonC
1
"und HEAD ist ein Commit, über das" git commit "ein neues machen würde." - gut zu merken, danke! Ebenfalls von @VonC: "Es ist das Commit, auf dem" git commit "aufbaut und mit dem" git diff --cached "und" git status "verglichen werden."
Minqi Pan
1
Überarbeitungen der Git-Hilfe rufen git-scm.com/docs/gitrevisions auf , in dem alle Möglichkeiten zum Verweisen auf Commits (einschließlich HEADund ORIG_HEAD) beschrieben werden.
Dahlbyk
104

Vom Git-Reset

"Pull" oder "Merge" belässt immer die ursprüngliche Spitze des aktuellen Zweigs ORIG_HEAD.

git reset --hard ORIG_HEAD

Durch hartes Zurücksetzen werden Ihre Indexdatei und der Arbeitsbaum wieder in diesen Zustand versetzt und die Spitze des Zweigs auf dieses Commit zurückgesetzt.

git reset --merge ORIG_HEAD

Nachdem Sie das Ergebnis der Zusammenführung überprüft haben, stellen Sie möglicherweise fest, dass die Änderung im anderen Zweig nicht zufriedenstellend ist. Wenn Sie " git reset --hard ORIG_HEAD" ausführen, können Sie dorthin zurückkehren, wo Sie waren, aber Ihre lokalen Änderungen werden verworfen, die Sie nicht möchten. " git reset --merge" behält Ihre lokalen Änderungen.


Bevor Patches angewendet werden, wird ORIG_HEAD auf die Spitze des aktuellen Zweigs gesetzt.
Dies ist nützlich, wenn Sie Probleme mit mehreren Commits haben, z. B. das Ausführen von ' git am' im falschen Zweig oder einen Fehler in den Commits, der durch Ändern des Postfachs leichter behoben werden kann (z. B. + Fehler in den Zeilen "Von:").

Außerdem setzt Merge immer ' .git/ORIG_HEAD' auf den ursprünglichen Zustand von HEAD, sodass eine problematische Zusammenführung mit ' git reset ORIG_HEAD' entfernt werden kann.


Hinweis: von hier

HEAD ist ein sich bewegender Zeiger. Manchmal bedeutet es den aktuellen Zweig, manchmal nicht.

HEAD ist also NICHT überall schon ein Synonym für "aktueller Zweig".

HEAD bedeutet "aktuell" überall in Git, aber es bedeutet nicht unbedingt "aktueller Zweig" (dh abgetrennter HEAD).

Aber es bedeutet fast immer das "aktuelle Commit".
Es ist das Commit, das darauf git commitaufbaut und mit dem " git diff --cached" und " git status" verglichen werden.
Dies bedeutet, dass der aktuelle Zweig nur in sehr begrenzten Kontexten verwendet wird (genau dann, wenn ein Zweigname bearbeitet werden soll - Zurücksetzen und Erweitern der Verzweigungsspitze über Commit / Rebase / etc.).

Reflog ist ein Fahrzeug in die Vergangenheit und Zeitmaschinen haben eine interessante Interaktion mit dem Begriff "Strom".

HEAD@{5.minutes.ago}könnte bedeuten "Dereferenzierung HEAD symref, um herauszufinden, auf welchem ​​Zweig wir uns JETZT befinden, und dann herauszufinden, wo sich die Spitze dieses Zweigs vor 5 Minuten befand".
Alternativ könnte es bedeuten, "was ist das Commit, das ich vor 5 Minuten als HEAD bezeichnet hätte, z. B. wenn ich" git show HEAD "damals" gemacht hätte ".


git1.8.4 (Juli 2013) stellt vor hat eine neue Notation eingeführt!
(Eigentlich wird es für 1.8.5 oder 1.9 sein, Q4 2013: wieder eingeführt mit Commit 9ba89f4 )

Anstatt vier Großbuchstaben " HEAD" einzugeben, können Sie @jetzt
" git log @" sagen , z . B. " ".

Siehe Commit cdfd948

Das Tippen von ' HEAD' ist mühsam, besonders wenn wir @stattdessen ' ' verwenden können.

Der Grund für die Wahl von ' @' ist, dass es sich natürlich aus der ref@opSyntax (z. B. HEAD@{u}) ergibt, außer dass wir keine Referenz und keine Operation haben, und wenn wir diese nicht haben, ist es sinnvoll, ' HEAD' anzunehmen .

Jetzt können wir also ' git show @~1' und all diese gute Güte verwenden.

Bis jetzt war ' @' ein gültiger Name, aber er widerspricht dieser Idee. Machen wir ihn also ungültig. Wahrscheinlich haben nur sehr wenige Leute diesen Namen verwendet.


In einem Blogbeitrag während des Zeitraums 1.8.4-rc3 (14. August 2013) wurde angekündigt, dass diese Funktion zurückgesetzt und verzögert wurde (Vielen Dank, Cupcake, für das Heads-up ).
Wieder wird es mit Commit 9ba89f4 (Sept. 2013) wieder eingeführt.

Siehe Commit 2c2b664 :

Zurücksetzen "Neue @Verknüpfung hinzufügen für HEAD"

Dies setzt das Festschreiben von cdfd948 zurück , da es nicht nur für " @" (und Formulare mit Modifikatoren, wie sie darauf @{u}angewendet werden) gilt, sondern auch z. B. " refs/heads/@/foo" betrifft , was nicht der Fall sein sollte.

Die Grundidee, eine kurze Hand zu geben, mag gut sein, und das Thema kann später wiederholt werden. Lassen Sie uns jedoch zurückkehren, um zu vermeiden, dass bestehende Anwendungsfälle für die kommende Version vorerst beeinflusst werden.

VonC
quelle
Nach dem Ausführen von git setzen Sie ORIG_HEAD zurück und schreiben Sie fest. ORIG_HEAD befindet sich noch unter Referenzen neben HEAD. Warum wurde es nicht aus der Ansicht entfernt?
Pulver366
@ Pulver366 aber ein git resetwird ein erzeugen ORIG_HEAD. Sie müssen rmes also manuell tun. Siehe zum Beispiel stackoverflow.com/a/12418078/6309 .
VonC
1
@VonC Der @Alias ​​für HEADwird (vorübergehend?) Für die Version Git 1.8.4 zurückgesetzt ! Es wurde gerade heute angekündigt!
Genossen den "Heads-up" -Kommentar!
Robino
2

Nach meinem Verständnis zeigt HEAD auf den aktuellen Zweig, während ORIG_HEAD zum Speichern des vorherigen HEAD verwendet wird, bevor "gefährliche" Operationen ausgeführt werden.

Zum Beispiel zeichnen git-rebase und git-am die ursprüngliche Spitze des Zweigs auf, bevor sie Änderungen übernehmen.

ynimous
quelle
4
HEAD zeigt nicht immer auf den aktuellen Zweig (er kann abgetrennt werden)
VonC
1
Was ist also der "aktuelle Zweig", wenn HEAD "getrennt" ist?
cjs
@ CurtJ.Sampson Das ist "kein Zweig". Das ist der Grund, warum Sie, wenn Sie in losgelöstem Kopf sind, dies tun git branch foo -b, um einen Zweig für die Waisen zu "erstellen".
Royi Namir
1

Von man 7 gitrevisions:

HEAD nennt das Commit, auf dem Sie die Änderungen im Arbeitsbaum basieren. FETCH_HEAD zeichnet den Zweig auf, den Sie mit Ihrem letzten Aufruf zum Abrufen von Git aus einem Remote-Repository abgerufen haben. ORIG_HEAD wird durch Befehle erstellt, die Ihren HEAD drastisch verschieben, um die Position des HEAD vor dem Betrieb aufzuzeichnen, sodass Sie die Spitze des Zweigs problemlos wieder in den Status zurückversetzen können, bevor Sie sie ausgeführt haben. MERGE_HEAD zeichnet die Commits auf, die Sie in Ihrem Zweig zusammenführen, wenn Sie Git Merge ausführen. CHERRY_PICK_HEAD zeichnet das Commit auf, das Sie beim Ausführen von git cherry-pick ausführen.

Nathan Chappell
quelle