ti-enxame.com

git fetch, FETCH_HEAD e Origin / master

Eu sou muito novo no git e estou tendo problemas com uma operação simples fetch.

Estou tentando buscar o progresso de um colega de trabalho em seu repositório. No começo eu fiz git fetch HEAD que levou o git a baixar cerca de 350 MB de dados, então eu tinha certeza de que havia feito algo. Contudo, Origin/master acabou apontando para o mesmo commit antigo (na verdade, está sob o nome dev, mas eu vou chamá-lo master - ele não tem um master).

Depois disso eu tentei git fetch Origin master mas parece que não fez nada, apenas atualizou FETCH_HEAD. Eu marquei o FETCH_HEAD commit para que eu não o perca, mas eu ainda gostaria de ter uma ramificação remota atualizada.

O que deu errado? Eu não tenho acesso ao repositório remoto. Ainda posso consertá-lo em casa?

14
DanielF

Estou um pouco confuso com os comandos que você usa. HEAD geralmente é um rótulo que o git usa para rastrear a confirmação que está atualmente no diretório de trabalho. O git fetch O comando espera que uma configuração remota ou confirmação remota saiba o que você deseja buscar. Usando git fetch HEAD indicaria HEAD é um controle remoto em seu repositório. Que o comando funcionou sem erro é curioso.

Por exemplo: git fetch HEAD no repositório no momento estou trabalhando resulta no seguinte erro

fatal: 'HEAD' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

O comando git remote listará todos os controles remotos, enquanto git remote --verbose incluirá o endereço do controle remoto. Você poderia usar isso para ver se você tem um controle remoto definido como HEAD e qual controle remoto endereça o repositório de seus amigos?

No entanto, deixo minhas perguntas de lado e para ajudar a esclarecer sua confusão. O git fetch ... comando atualiza apenas referências remotas - não as locais.

Para deixar isso claro, procure dentro da pasta .git no seu repositório (ela está oculta por padrão, portanto, pode ser necessário exibi-la). Você encontrará uma estrutura de pastas semelhante à seguinte

working directory
|=>.git
|  |=>objects           <= contains data for each commit
|  |=>refs
|     |=>heads
|        |-master       <= file containing current commit of local master branch
|     |=>remotes
|        |=>Origin
|           |-master    <= file containing current commit of remote Origin's master branch
|-FETCH_HEAD            <= file updated by `git fetch`, contains info of what was fetched

Digamos que você fez o checkout do ramo principal, git checkout master - O git alterará seu diretório de trabalho para corresponder aos dados de confirmação na pasta 'objects' que correspondem ao valor de confirmação no arquivo '.git/refs/heads/master'.

Se você então git fetch Origin master, o arquivo '.git/refs/remotes/Origin/master' é atualizado para o commit da ramificação master no Origin remoto - e todos os dados de commit necessários para esse commit são baixados e colocados na pasta 'objects' .

O ponto importante aqui é git fetch não atualiza seu diretório de trabalho reflete a ramificação local com check-out e git fetch nunca atualiza uma filial local.

Usando git merge ... ou git rebase ... é necessário para atualizar a filial local master com as alterações em Origin/master. git pull ... faz os dois git fetch ... e também git merge ... ou git rebase ..., dependendo das opções e configuração (git merge ... é o padrão).

Depois de toda essa explicação, você deseja poder ver o que foi buscado no repositório de seus amigos, se é que houve alguma coisa. O git branch -avv comando listará todas as ramificações locais e remotas, com números de confirmação e, no caso de ramificações locais, qual ramificação remota ele está rastreando.

Para ver como as ramificações se relacionam, acho útil usar uma ferramenta para representar graficamente a árvore do repositório. Existem vários para escolher, mas acho que o git log comando suficiente; tal como git log --all --graph --oneline --decorate. Aviso justo, isso pode ser bastante longo e complicado para um grande repositório. É possível obter uma saída mais curta adicionando o --simplify-by-decoration argumento.

Resumindo: se você pode corrigi-lo em casa, depende das informações em seu repositório. Os comandos acima mencionados; git remote --verbose, git branch -avv e git log ... deve fornecer uma compreensão do estado atual do seu repositório. A partir daí, você pode determinar se precisa fazer algo mais para obter os dados em suas filiais locais usando git merge ou git rebase.

Como sempre, se você tiver problemas, poste de volta com o que aprendeu.

16
David Culp

Desde o git 1.8.4 (agosto de 2013), git fetch atualiza o ramo de rastreamento remoto! Não apenas FETCH_HEAD.

Veja confirmar f269048 de Jeff King (peff) :

Quando executamos um "git fetch" Regular sem argumentos, atualizamos as referências de rastreamento de acordo com o refspec configurado.
No entanto, quando executamos "git fetch Origin master" (Ou "git pull Origin master"), Não analisamos os refspecs configurados e apenas atualizamos FETCH_HEAD .

Perdemos a oportunidade de atualizar "refs/remotes/Origin/master" (Ou o que o usuário tiver configurado). Alguns usuários acham isso confuso, porque gostariam de fazer comparações adicionais com o antigo estado do mestre remoto, como:

$ git pull Origin master
$ git log HEAD...Origin/master

Mas isso supõe que você configurou seu repositório para buscar ramos:

git config remote.Origin.fetch

Se vazio:

git config remote.Origin.fetch '+refs/heads/*:refs/remotes/Origin/*'
9
VonC

git fetch na verdade não toca no seu diretório de trabalho. Ele busca apenas as alterações mais recentes dos controles remotos. Para realmente atualizar seu estado atual, use git merge ou git rebase . Além disso, você pode usar git pull que funciona como atalho para git fetch + git merge.

A principal diferença entre mesclagem e rebase é que, em alguns casos, a mesclagem criará uma nova confirmação, com estado acumulado (mesclagem sem avanço rápido). IMHO isso é ruim, como me lembra os tempos que eu usei SVN. Rebase apenas repete suas alterações na parte superior da confirmação especificada, para que seu histórico seja sempre linear. Apenas certifique-se de usar o mesmo fluxo que seus colegas.

Eu sugiro que você leia algumas coisas sobre o git em geral e git flow : a livro de leitura obrigatória e a bom artigo .

4
madhead

O que você quer fazer é:

  • Adicione um controle remoto para seu colega de trabalho
  • Busque as alterações em seu repositório
  • Crie uma filial local que se refere à filial remota

Presumivelmente, você já fez o passo 1. Mas, para ser completo, é:

git remote add coworker git://path/to/coworkers/repo.git

onde o URL pode ser qualquer formato de URL compatível com o git.

Agora que você adicionou o controle remoto, deseja buscar as alterações dele:

git fetch coworker

Isso fornece ramificações remotas para cada uma das ramificações dele. Digamos que o ramo dele seja chamado de "hamster". Agora, para fazer o trabalho, você cria sua própria cópia local da filial remota

git checkout -b hamster coworker/hamster

Isso cria e alterna você para um ramo chamado hamster.

A partir desse ponto, você pode trabalhar no hamster e empurrá-lo para ele com

git Push coworker hamster

pela primeira vez e depois apenas git Push depois disso.

Sempre que você desejar baixar e mesclar as alterações dele, você pode:

git pull

1
wadesworld