O que significa FETCH_HEAD no Git?

220

git pull --help diz:

No modo padrão, git pullé uma abreviação para git fetchseguido por git merge FETCH_HEAD.

O que é isso FETCH_HEADe o que é realmente mesclado durante git pull?

Misha Moroshko
fonte
3
Nota: desde o git 1.8.4 (agosto de 2013), ele git fetch origin masterserá atualizado origin/master, não apenas FETCH_HEAD. Veja stackoverflow.com/a/20967347/6309
VonC
Para obter mais informações git merge FETCH_HEAD(desde Git 2.5, Q2 2015), consulte stackoverflow.com/a/30425991/6309
VonC

Respostas:

218

FETCH_HEADé uma referência de curta duração, para acompanhar o que acabou de ser buscado no repositório remoto. git pullinvoca primeiro git fetch, em casos normais, buscando uma ramificação do controle remoto; FETCH_HEADaponta para a ponta deste ramo (ele armazena o SHA1 do commit, assim como os ramos fazem). git pullentão chama git merge, mesclando FETCH_HEADna ramificação atual.

O resultado é exatamente o que você esperaria: a confirmação na ponta da ramificação remota apropriada é mesclada na confirmação na ponta da sua ramificação atual.

É como fazer git fetchsem argumentos (ou git remote update), atualizar todas as ramificações remotas e depois executar git merge origin/<branch>, mas usando FETCH_HEADinternamente para se referir a qualquer referência única buscada, em vez de precisar nomear as coisas.

Cascabel
fonte
9
@ Jeffromi: desculpe, acho que você está errado: até onde eu entendi, git fetchatualiza (mescla) todos os dados do objeto do armazenamento remoto, não apenas um brunch. Portanto, não entendo pela sua resposta como o git decide a ponta de qual ramo apontar FETCH_HEAD. Também não consigo encontrar FETCH_HEADna documentação do git (a definição, não exemplos). A existência de FETCH_HEADme parece mais uma solução alternativa, para fazer git pullfuncionar de alguma forma .
Alexey
14
Alexey: FETCH_HEADcorresponde à ponta da ramificação remota especificada branch.<BRANCH>.mergena configuração do repositório local. Portanto, embora fetchrealmente busque todos os dados do objeto do armazenamento remoto, FETCH_HEADé usado para indicar para onde a filial remota rastreada pela filial local avançou. Portanto, se você estiver na masterramificação local e executar git fetch, e branch.master.mergeapontar para refs/heads/master, FETCH_HEADterá o mesmo valor origin/masterimediatamente após a operação de busca.
larsks
4
@alexy FETCH_HEAD é descrito no segundo parágrafo da descrição do git fetch em sua página de manual. Minha resposta está correta. E o git fetch sem argumentos atualiza todas as ramificações remotas para o controle remoto padrão ... mas isso definitivamente não é o mesmo que mesclar.
Cascabel
4
E FETCH_HEADse você buscar todas as ramificações remotas via git fetch -a?
10131
2
@stigi A ponta do ramo de rastreamento remoto que seu ramo atualmente está com checkout está apontando na configuração do git. Por favor, veja a resposta de larsks no comentário acima.
Ankur Agarwal
19

O FETCH_HEAD é uma referência à ponta da última busca, se essa busca foi iniciada diretamente usando o comando buscar ou como parte de uma atração. O valor atual de FETCH_HEAD é armazenado na .gitpasta em um arquivo chamado, você adivinhou FETCH_HEAD.

Então, se eu emitir:

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

FETCH_HEAD pode conter

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

Se eu tiver o repositório remoto configurado como uma filial de rastreamento remoto, posso seguir minha busca com uma mesclagem da filial de rastreamento. Caso contrário, posso mesclar diretamente a ponta da última busca usando FETCH_HEAD.

git merge FETCH_HEAD
Jonathan Mitchell
fonte
1
Para adicionar meus 5 centavos. O que me confundiu é que meu FETCH_HEAD estava por trás das confirmações mais recentes, mesmo que estivesse fazendo uma nova busca que retornasse "sem alterações" (no eclipse). Acho que o motivo é que todas as alterações desde a minha última busca são minhas e foram enviadas ao servidor por mim. Portanto, uma busca subsequente não teve nada a ver e nem atualizou o FETCH_HEAD. Não tenho certeza se isso é uma falha na implementação do GIT ou Eclipse Git.
Torge
11

Como mencionado na resposta de Jonathan , FETCH_HEAD corresponde ao arquivo .git/FETCH_HEAD. Normalmente, o arquivo ficará assim:

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>

Observe como todas as ramificações, exceto uma, são marcadas not-for-merge. O mais estranho é o ramo que foi retirado antes da busca. Em resumo: FETCH_HEAD corresponde essencialmente à versão remota da filial que está com check-out no momento.

Carsten Führmann
fonte
9

Acabei de descobrir e usar FETCH_HEAD. Eu queria uma cópia local de algum software de um servidor e fiz

git fetch gitserver release_1

gitserveré o nome da minha máquina que armazena repositórios git. release_1é uma tag para uma versão do software. Para minha surpresa, não release_1havia nenhum lugar na minha máquina local. Eu tive que digitar

 git tag release_1 FETCH_HEAD 

para concluir a cópia da cadeia de confirmações marcadas (release_1) do repositório remoto para o local. A busca encontrou a tag remota, copiou a confirmação na minha máquina local, não criou uma tag local, mas definiu FETCH_HEADo valor da confirmação, para que eu pudesse encontrá-la e usá-la. Depois, FETCH_HEADcriei uma marca local que correspondia à marca no controle remoto. Essa é uma ilustração prática do que FETCH_HEADé e como ele pode ser usado, e pode ser útil para alguém se perguntar por que o git fetch não faz o que você esperaria ingenuamente.

Na minha opinião, é melhor evitar isso para esse fim, e a melhor maneira de conseguir o que eu estava tentando fazer é

git fetch gitserver release_1:release_1

ou seja, buscar release_1 e chamá-lo release_1 localmente. (É fonte: dest, consulte https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; apenas no caso de você desejar atribuir um nome diferente!)

Você pode querer usar FETCH_HEADalgumas vezes: -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

pode ser uma boa maneira de usar a correção de bug número 1234 do seu servidor Git e deixar a coleta de lixo do Git para descartar a cópia do servidor depois que a correção for selecionada em sua ramificação atual. (Estou supondo que exista um commit limpo e marcado, contendo toda a correção de bugs no servidor!)

Ivan
fonte
Feedback interessante. 1
VonC 26/0118
Obrigado. Editei minha postagem original, escrita quando descobri o FETCH_HEAD há alguns anos, pois parecia encorajar a cópia de uma tag usando o FETCH_HEAD em vez da fonte: sintaxe dest para refspecs. Espero que agora eu tenha dado um exemplo melhor de como FETCH_HEAD poderia ser usado.
Ivan
3

git pull é a combinação de uma busca seguida por uma mesclagem. Quando o git fetch acontece, ele observa o commit principal do que foi buscado em FETCH_HEAD (apenas um arquivo com esse nome em .git). E esses commits são mesclados no diretório de trabalho.

manojlds
fonte
3
@manjolds, o que você quer dizer com " head commit do que foi buscado"? Git busca tudo com busca.
Alexey
@Alexey de git manual: git-scm.com/docs/git-fetch : Os nomes dos árbitros que são buscados, juntamente com os nomes de objetos que apontam para, são gravados em .git / FETCH_HEAD
PJ_Finnegan