Cosa significa FETCH_HEAD in Git?


221

git pull --help dice:

Nella sua modalità predefinita, git pullè una scorciatoia per git fetchseguita da git merge FETCH_HEAD.

Cos'è questo FETCH_HEADe cosa viene effettivamente unito durante git pull?


3
Nota: da git 1.8.4 (agosto 2013), git fetch origin masterverrà effettivamente aggiornato origin/master, non solo FETCH_HEAD. Vedere stackoverflow.com/a/20967347/6309
VonC

Per ulteriori informazioni su git merge FETCH_HEAD(dal Git 2.5, Q2 2015), vedi stackoverflow.com/a/30425991/6309
VonC

Risposte:


218

FETCH_HEADè un riferimento di breve durata, per tenere traccia di ciò che è appena stato recuperato dal repository remoto. git pullprima invoca git fetch, in casi normali il recupero di un ramo dal telecomando; FETCH_HEADpunta alla punta di questo ramo (memorizza lo SHA1 del commit, proprio come fanno i rami). git pullquindi invoca git merge, fondendosi FETCH_HEADnel ramo corrente.

Il risultato è esattamente quello che ti aspetteresti: il commit sulla punta del ramo remoto appropriato viene unito al commit sulla punta del ramo corrente.

È un po 'come fare git fetchsenza argomenti (o git remote update), aggiornare tutti i tuoi rami remoti, quindi eseguirli git merge origin/<branch>, ma usare FETCH_HEADinternamente invece per fare riferimento a qualsiasi riferimento singolo recuperato, invece di dover nominare le cose.


9
@Jefromi: scusa, penso che ti sbagli: per quanto ho capito, git fetchaggiorna (unisce) tutti i dati degli oggetti dalla memoria remota, non solo un brunch. Quindi non capisco dalla tua risposta come git decide alla punta di quale ramo puntare FETCH_HEAD. Inoltre non riesco a trovare FETCH_HEADnella documentazione di Git (la definizione, non gli esempi). L'esistenza di FETCH_HEADmi sembra più una soluzione alternativa, per rendere il git pulllavoro in qualche modo .
Alexey,

14
Alexey: FETCH_HEADcorrisponde alla punta del ramo remoto specificato da branch.<BRANCH>.mergenella configurazione del repository locale. Quindi mentre fetcheffettivamente recupera tutti i dati degli oggetti dalla memoria remota,FETCH_HEAD viene utilizzato per indicare dove è avanzato il ramo remoto tracciato dal ramo locale. Quindi, se ti trovi sul masterramo locale ed esegui git fetch, e branch.master.mergepunta a refs/heads/master, allora FETCH_HEADavrà lo stesso valore di origin/masterimmediatamente dopo l'operazione di recupero.
Larsks,

4
@alexy FETCH_HEAD è descritto nel secondo paragrafo della descrizione di git fetch nella sua pagina man. La mia risposta è corretta E git fetch senza argomenti aggiorna tutti i rami remoti per il telecomando predefinito ... ma questo non è sicuramente lo stesso della fusione.
Cascabel,

4
Cosa succede FETCH_HEADse recuperi tutti i rami remoti tramite git fetch -a?
stigi,

2
@stigi La punta del ramo di tracciamento remoto a cui punta il ramo attualmente estratto nella configurazione git. Si prega di vedere la risposta di Larsks nel commento sopra.
Ankur Agarwal,

19

FETCH_HEAD è un riferimento alla punta dell'ultimo recupero, indipendentemente dal fatto che quel recupero sia stato avviato direttamente utilizzando il comando fetch o come parte di un pull. Il valore corrente di FETCH_HEAD viene memorizzato nella .gitcartella in un file chiamato, avete indovinato, FETCH_HEAD.

Quindi se emetto:

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

FETCH_HEAD può contenere

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

Se il repository remoto è configurato come ramo di tracciamento remoto, posso seguire il mio recupero con un'unione del ramo di rilevamento. In caso contrario, posso unire la punta dell'ultimo recupero direttamente utilizzando FETCH_HEAD.

git merge FETCH_HEAD

1
Per aggiungere i miei 5 centesimi. Ciò che mi ha confuso è che il mio FETCH_HEAD era dietro gli ultimi commit, anche se stava facendo un nuovo recupero che ha restituito "nessuna modifica" (in eclissi). Penso che il motivo sia che tutte le modifiche dall'ultimo recupero sono state eseguite da me e sono state inviate al server da me. Quindi un successivo recupero non ha avuto nulla da fare e non ha nemmeno aggiornato FETCH_HEAD. Non sono sicuro se questo sia un difetto dell'implementazione di GIT o Eclipse Git.
Torge il

11

Come menzionato nella risposta di Jonathan , FETCH_HEAD corrisponde al file .git/FETCH_HEAD. In genere, il file sarà simile al seguente:

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>

Nota come sono contrassegnati tutti i rami tranne uno not-for-merge. Quello dispari è il ramo che è stato estratto prima del recupero. In sintesi: FETCH_HEAD corrisponde essenzialmente alla versione remota del ramo attualmente estratto.


9

Ho appena scoperto e usato FETCH_HEAD. Volevo una copia locale di alcuni software da un server e l'ho fatto

git fetch gitserver release_1

gitserverè il nome della mia macchina che memorizza i repository git. release_1è un tag per una versione del software. Con mia sorpresa, non è release_1stato possibile trovare da nessuna parte sulla mia macchina locale. Ho dovuto scrivere

 git tag release_1 FETCH_HEAD 

per completare la copia della catena di commit contrassegnata (release_1) dal repository remoto a quello locale. Fetch aveva trovato il tag remoto, copiato il commit sul mio computer locale, non aveva creato un tag locale, ma aveva impostato FETCH_HEADil valore del commit, in modo che potessi trovarlo e usarlo. Ho quindi usato FETCH_HEADper creare un tag locale che corrispondeva al tag sul telecomando. Questa è una illustrazione pratica di ciò che FETCH_HEADè e come può essere usato, e potrebbe essere utile a qualcun altro che si chiede perché Git Fetch non faccia ciò che ci si aspetterebbe ingenuamente.

A mio avviso, è meglio evitarlo a tale scopo e un modo migliore per raggiungere quello che stavo cercando di fare è

git fetch gitserver release_1:release_1

cioè per scaricare release_1 e chiamarla release_1 localmente. (È fonte: dest, vedi https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; nel caso in cui desideri dargli un nome diverso!)

A volte potresti voler usare FETCH_HEAD: -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

potrebbe essere un buon modo di usare la correzione bug numero 1234 dal tuo server Git e di lasciare la garbage collection di Git per smaltire la copia dal server una volta che la correzione è stata selezionata sul tuo ramo corrente. (Suppongo che ci sia un bel commit con tag pulito che contiene l'intera correzione del bug sul server!)


Feedback interessante. +1
VonC,

Grazie. Ho modificato il mio post originale, scritto quando ho scoperto FETCH_HEAD per la prima volta un paio di anni fa, poiché sembrava incoraggiare la copia di un tag usando FETCH_HEAD piuttosto che l'origine: sintassi dest per refspecs. Spero di aver dato un esempio migliore di come FETCH_HEAD potrebbe essere usato.
Ivan,

3

git pull è una combinazione di un recupero seguito da un'unione. Quando si verifica git fetch, rileva il commit principale di ciò che ha recuperato in FETCH_HEAD (solo un file con quel nome in .git) e questi commit vengono quindi uniti nella directory di lavoro.


3
@manjolds, cosa intendi con " head commit di ciò che ha recuperato"? Git recupera tutto con fetch.
Alexey,

@Alexey dal manuale di git: git-scm.com/docs/git-fetch : i nomi degli ref che vengono recuperati, insieme ai nomi degli oggetti a cui puntano, vengono scritti in .git / FETCH_HEAD
PJ_Finnegan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.