Cosa significa FETCH_HEAD in Git?

git pull --help dice:

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

Che cos’è questo FETCH_HEAD e cosa viene effettivamente unito durante git pull ?

FETCH_HEAD è un riferimento di breve durata, per tenere traccia di ciò che è stato appena recuperato dal repository remoto. git pull richiama prima git fetch , in casi normali recuperando un ramo dal telecomando; FETCH_HEAD punta alla punta di questo ramo (memorizza lo SHA1 del commit, proprio come fanno i rami). git pull richiama quindi git merge , unendo FETCH_HEAD nel ramo corrente.

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

Questo è un po ‘come fare git fetch senza argomenti (o git remote update ), aggiornando tutti i rami remoti, quindi eseguendo git merge origin/ , ma usando FETCH_HEAD internamente invece di fare riferimento a qualunque singolo ref è stato prelevato, invece di aver bisogno per nominare le cose.

FETCH_HEAD è un riferimento al suggerimento dell’ultimo recupero, indipendentemente dal fatto che il recupero sia stato avviato direttamente utilizzando il comando fetch o come parte di un pull. Il valore corrente di FETCH_HEAD è memorizzato nella cartella .git in un file chiamato, FETCH_HEAD .

Quindi se emetto:

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

FETCH_HEAD potrebbe contenere

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

Se ho il repository remoto configurato come un ramo di monitoraggio remoto, posso seguire il mio recupero con un’unione del ramo di monitoraggio. Se non lo faccio posso unire il tip dell’ultimo recupero direttamente usando FETCH_HEAD.

 git merge FETCH_HEAD 

Ho appena scoperto e utilizzato 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, release_1 non è stato trovato da nessuna parte sul mio computer locale. Dovevo digitare

  git tag release_1 FETCH_HEAD 

per completare la copia della catena di commit taggata (release_1) dal repository remoto a quella locale. Fetch aveva trovato il tag remoto, copiato il commit sul mio computer locale, non aveva creato un tag locale, ma aveva impostato FETCH_HEAD sul valore del commit, in modo da poterlo trovare e usarlo. Ho quindi utilizzato FETCH_HEAD per creare un tag locale che corrisponde al tag sul telecomando. Questa è un’illustrazione pratica di cosa è FETCH_HEAD e di come può essere utilizzata, e potrebbe essere utile a qualcun altro che si chiede perché git fetch non faccia ciò che si vorrebbe ingenuamente.

Secondo me è meglio evitare per quello scopo e un modo migliore per ottenere ciò che stavo cercando di fare è

 git fetch gitserver release_1:release_1 

vale a dire recuperare il rilascio_1 e chiamarlo release_1 localmente. (È la fonte: dest, vedi https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; nel caso tu voglia dargli un nome diverso!)

A volte potresti voler usare FETCH_HEAD : –

 git fetch gitserver bugfix1234 git cherry-pick FETCH_HEAD 

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

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

 71f026561ddb57063681109aadd0de5bac26ada9 branch 'some-branch' of  669980e32769626587c5f3c45334fb81e5f44c34 not-for-merge branch 'some-other-branch' of  b858c89278ab1469c71340eef8cf38cc4ef03fed not-for-merge branch 'yet-some-other-branch' of  

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

git pull è la combinazione di un recupero seguito da un’unione. Quando git fetch si verifica, prende nota del commit head di ciò che è stato recuperato in FETCH_HEAD (solo un file con quel nome in .git) e questi commit vengono poi uniti nella directory di lavoro.