Was bedeutet FETCH_HEAD in Git?

220

git pull --help sagt:

Im Standardmodus git pullwird die Abkürzung für git fetchgefolgt von git merge FETCH_HEAD.

Was ist das FETCH_HEADund was wird tatsächlich zusammengeführt git pull?

Mischa Moroshko
quelle
3
Hinweis: Seit Git 1.8.4 (August 2013) git fetch origin masterwird tatsächlich origin/masternicht nur aktualisiert FETCH_HEAD. Siehe stackoverflow.com/a/20967347/6309
VonC
Weitere Informationengit merge FETCH_HEAD (seit Git 2.5, 2. Quartal 2015) finden Sie unter stackoverflow.com/a/30425991/6309
VonC

Antworten:

218

FETCH_HEADist eine kurzlebige Referenz, um zu verfolgen, was gerade aus dem Remote-Repository abgerufen wurde. git pullruft zuerst auf git fetch, in normalen Fällen einen Zweig von der Fernbedienung abrufend; FETCH_HEADzeigt auf die Spitze dieses Zweigs (es speichert den SHA1 des Commits, genau wie Zweige). git pullruft dann auf git mergeund verschmilzt FETCH_HEADmit dem aktuellen Zweig.

Das Ergebnis ist genau das, was Sie erwarten würden: Das Commit an der Spitze des entsprechenden Remote-Zweigs wird mit dem Commit an der Spitze Ihres aktuellen Zweigs zusammengeführt.

Dies ist ein bisschen so, als würden Sie git fetchauf Argumente (oder git remote update) verzichten, alle Ihre Remote-Zweige aktualisieren und dann ausführen git merge origin/<branch>, aber stattdessen FETCH_HEADintern verwenden, um auf die abgerufene einzelne Referenz zu verweisen, anstatt Dinge benennen zu müssen.

Cascabel
quelle
9
@Jefromi: Entschuldigung, ich denke, Sie liegen falsch: Soweit ich weiß, werden git fetchalle Objektdaten aus dem Remotespeicher aktualisiert (zusammengeführt), nicht nur ein Brunch. Daher verstehe ich aus Ihrer Antwort nicht, wie Git entscheidet, auf welche Spitze der Zweig zeigen soll FETCH_HEAD. Ich kann auch nicht FETCH_HEADin der Git-Dokumentation finden (die Definition, keine Beispiele). Die Existenz von FETCH_HEADsieht für mich eher nach einer Problemumgehung aus, um irgendwiegit pull Arbeit zu machen .
Alexey
14
Alexey: FETCH_HEADEntspricht der Spitze des Remote-Zweigs, die branch.<BRANCH>.mergein der lokalen Repository-Konfiguration angegeben ist. Während fetchalso tatsächlich alle Objektdaten vom Remotespeicher abgerufen werden, FETCH_HEADwird verwendet, um anzugeben, wohin der von der lokalen Filiale verfolgte Remote-Zweig vorgerückt ist. Wenn Sie sich also in der lokalen masterVerzweigung befinden und ausführen git fetchund branch.master.mergeauf zeigen refs/heads/master, hat FETCH_HEADdies denselben Wert wie origin/masterunmittelbar nach dem Abrufvorgang.
Larsks
4
@alexy FETCH_HEAD wird im zweiten Absatz der Beschreibung von git fetch in seiner Manpage beschrieben. Meine Antwort ist richtig. Und Git Fetch ohne Argumente aktualisiert alle Remote-Zweige für die Standard-Remote ... aber dies ist definitiv nicht dasselbe wie Zusammenführen.
Cascabel
4
Was ist, FETCH_HEADwenn Sie alle Remote-Zweige über abrufen git fetch -a?
Stigi
2
@stigi Der Tipp des Remote-Tracking-Zweigs, auf den Ihr aktuell ausgecheckter Zweig in der Git-Konfiguration zeigt. Die Antwort der Larsks finden Sie im obigen Kommentar.
Ankur Agarwal
19

Der FETCH_HEAD ist eine Referenz auf die Spitze des letzten Abrufs, unabhängig davon, ob dieser Abruf direkt mit dem Abrufbefehl oder als Teil eines Pulls initiiert wurde. Der aktuelle Wert von FETCH_HEAD wird im .gitOrdner in einer Datei mit dem Namen gespeichert FETCH_HEAD.

Also, wenn ich herausgebe:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD kann enthalten

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

Wenn ich das Remote-Repo als Remote-Tracking-Zweig konfiguriert habe, kann ich nach meinem Abruf den Tracking-Zweig zusammenführen. Wenn nicht, kann ich die Spitze des letzten Abrufs direkt mit FETCH_HEAD zusammenführen.

git merge FETCH_HEAD
Jonathan Mitchell
quelle
1
Um meine 5 Cent hinzuzufügen. Was mich verwirrt hat, ist, dass mein FETCH_HEAD hinter den letzten Commits steckt, selbst wenn ich einen neuen Abruf mache, der "keine Änderungen" zurückgibt (in Eclipse). Ich denke, der Grund dafür ist, dass alle Änderungen seit meinem letzten Abruf von mir selbst stammen und von mir auf den Server übertragen wurden. Ein nachfolgender Abruf hatte also nichts zu tun und aktualisierte nicht einmal den FETCH_HEAD. Ich bin mir nicht sicher, ob dies ein Mangel der Implementierung von GIT oder Eclipse Git ist.
Torge
11

Wie in Jonathans Antwort erwähnt , entspricht FETCH_HEAD der Datei .git/FETCH_HEAD. Normalerweise sieht die Datei folgendermaßen aus:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Beachten Sie, wie alle Zweige bis auf einen markiert sind not-for-merge. Der ungerade ist der Zweig, der vor dem Abruf ausgecheckt wurde. Zusammenfassend: FETCH_HEAD entspricht im Wesentlichen der Remote-Version des Zweigs, der gerade ausgecheckt ist.

Carsten Führmann
quelle
9

Ich habe gerade entdeckt und verwendet FETCH_HEAD. Ich wollte eine lokale Kopie einer Software von einem Server und ich tat es

git fetch gitserver release_1

gitserverist der Name meines Computers, auf dem Git-Repositorys gespeichert sind. release_1ist ein Tag für eine Version der Software. Zu meiner Überraschung release_1war dann nirgends auf meinem lokalen Computer zu finden. Ich musste tippen

 git tag release_1 FETCH_HEAD 

um die Kopie der markierten Commit-Kette (release_1) vom Remote-Repository in das lokale Repository zu vervollständigen . Fetch hatte das Remote-Tag gefunden, das Commit auf meinen lokalen Computer kopiert, kein lokales Tag erstellt, sondern FETCH_HEADden Wert des Commits festgelegt, damit ich es finden und verwenden konnte. Ich habe dann FETCH_HEADein lokales Tag erstellt, das mit dem Tag auf der Fernbedienung übereinstimmt. Dies ist eine praktische Illustration dessen, was FETCH_HEADist und wie es verwendet werden kann, und kann für andere nützlich sein, die sich fragen, warum Git Fetch nicht das tut, was Sie naiv erwarten würden.

Meiner Meinung nach wird es zu diesem Zweck am besten vermieden, und ein besserer Weg, um das zu erreichen, was ich versucht habe, ist

git fetch gitserver release_1:release_1

dh Release_1 abrufen und lokal Release_1 nennen. (Es ist Quelle: dest, siehe https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; nur für den Fall, dass Sie ihm einen anderen Namen geben möchten!)

Möglicherweise möchten Sie jedoch FETCH_HEADmanchmal Folgendes verwenden: -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

Dies ist möglicherweise eine gute Möglichkeit, die Fehlerbehebungsnummer 1234 von Ihrem Git-Server zu verwenden und die Garbage Collection von Git zu verlassen, um die Kopie vom Server zu entsorgen, sobald der Fix in Ihrem aktuellen Zweig ausgewählt wurde. (Ich gehe davon aus, dass es ein schönes Commit mit sauberen Tags gibt, das die gesamte Fehlerbehebung auf dem Server enthält!)

Ivan
quelle
Interessantes Feedback. +1
VonC
Vielen Dank. Ich habe meinen ursprünglichen Beitrag bearbeitet, der geschrieben wurde, als ich FETCH_HEAD vor ein paar Jahren zum ersten Mal entdeckte, da er das Kopieren eines Tags mit FETCH_HEAD anstelle der Syntax source: dest für refspecs zu fördern schien. Hoffentlich habe ich jetzt ein besseres Beispiel gegeben, wie FETCH_HEAD verwendet werden könnte.
Ivan
3

Git Pull ist eine Kombination aus einem Abruf und einer Zusammenführung. Wenn der Git-Abruf erfolgt, wird das Head-Commit von dem notiert, was in FETCH_HEAD abgerufen wurde (nur eine Datei mit diesem Namen in .git). Diese Commits werden dann in Ihrem Arbeitsverzeichnis zusammengeführt.

Manojlds
quelle
3
@manjolds, was meinst du mit " Head Commit von dem, was es geholt hat"? Git holt alles mit fetch.
Alexey
@Alexey aus dem Git-Handbuch: git-scm.com/docs/git-fetch : Die Namen der abgerufenen Refs werden zusammen mit den Objektnamen, auf die sie zeigen,
.git