O comando git fetch baixa commits, arquivos e referências de um repositório remoto para seu repositório local. Busca (fetching) é o que você faz quando quer ver em que todos estão trabalhando. É semelhante ao svn update, que permite que você veja como o histórico central tem progredido, mas não obriga a de fato fazer o merge das mudanças em seu repositório. O Git isola o conteúdo buscado do conteúdo local existente e não tem efeito algum no trabalho local de desenvolvimento. O conteúdo buscado tem de ser explicitamente verificado, usando o comando git checkout. Isso faz com que a busca seja uma forma segura de analisar commits antes de serem integrados ao repositório local.

Ao baixar conteúdo de um repositório remoto, os comandos git pull e git fetch ficam disponíveis para realizar a tarefa. Você pode considerar git fetch a versão "segura" desses comandos. Ele vai baixar o conteúdo remoto, mas não vai atualizar o estado de trabalho do repositório local, deixando o trabalho atual intacto. O git pull é a alternativa mais agressiva: ele vai baixar o conteúdo remoto para a ramificação ativa local e vai executar o comando git merge imediatamente para criar um commit de merge para o novo conteúdo remoto. Mudanças pendentes em andamento podem causar conflitos e ativar o fluxo de resolução de conflitos de merge.

Como o git fetch funciona com ramificações remotas

Para entender melhor como o git fetch funciona, vamos discutir como o Git organiza e armazena commits. Nos bastidores, no diretório ./.git/objects do repositório, o Git armazena todos os commits, locais e remotos. O Git mantém os commits de ramificação remotos e locais separados por meio do uso de referências de ramificação. As referências para ramificações locais são armazenadas em ./.git/refs/heads/. Executar o comando git branch vai exibir uma lista das referências da ramificação local. A seguir, um exemplo do resultado de git branch com alguns exemplos de nomes de ramificação.

git branch
master
feature1
debug2

Uma análise dos conteúdos do diretório ./.git/refs/heads/ revelaria um resultado semelhante.

ls ./.git/refs/heads/
master
feature1
debug2

Ramificações remotas são parecidas com as ramificações locais, exceto pelo mapeamento de commits do repositório de outra pessoa. As ramificações remotas recebem o prefixo do remoto ao qual pertencem, para que não sejam confundidas com as ramificações locais. Como no caso das ramificações locais, o Git também tem referências para ramificações remotas, que ficam no diretório ./.git/refs/remotes/. O trecho de código do próximo exemplo mostra as ramificações que você pode ver após buscar um repositório remoto chamado convenientemente de remote-repo:

git branch -r
# origin/master
# origin/feature1
# origin/debug2
# remote-repo/master
# remote-repo/other-feature

Esse resultado exibe as ramificações locais que examinamos antes, mas agora com o prefixo origin/. Além disso, agora vemos as ramificações remotas com o prefixo remote-repo. É possível verificar uma ramificação remota da mesma forma que uma local, mas isso coloca você em um estado HEAD desvinculado (como verificar um commit antigo). Você pode pensar nelas como ramificações apenas para leitura. Para visualizar as ramificações remotas, basta usar o sinalizador -r no comando git branch.

Você pode inspecionar ramificações remotas com os comandos git checkout e git log. Se você aprovar as mudanças que uma ramificação remota contém, é possível fazer o merge com uma ramificação local com o comando git merge. Então, ao contrário do SVN, sincronizar o repositório local com um remoto é, na verdade, um processo em duas etapas: buscar (fetch) e merge. O comando git pull é um atalho útil para esse processo.

Comandos e opções do git fetch

git fetch <remote>

Busque todas as ramificações no repositório. Este comando também baixa todos os commits e arquivos necessários do outros repositórios.

git fetch <remote> <branch>

Igual ao comando anterior, mas só faz a busca em uma ramificação especificada.

git fetch --all

Um comando potente que busca todos os remotos registrados e suas ramificações:

git fetch --dry-run

A opção --dry-run vai executar uma demonstração do comando, trazendo como resultado exemplos de ações que vão acontecer durante a busca, mas não vão ser aplicadas.

Exemplos de git fetch

git fetch em uma ramificação remota

O exemplo a seguir vai demonstrar como buscar uma ramificação remota e atualizar o estado de trabalho local com os conteúdos remotos. Neste exemplo, vamos supor que há um repositório central original de onde o repositório local foi clonado usando o comando git clone. Vamos também supor um repositório remoto adicional chamado coworkers_repo que contém um feature_branch, o qual vamos configurar e buscar. Com essas suposições, vamos continuar o exemplo.

Em primeiro lugar, precisamos configurar o repositório remoto, usando o comando git remote.

git remote add coworkers_repo git@bitbucket.org:coworker/coworkers_repo.git

Aqui, criamos uma referência para o repositório de um colega usando a URL do repositório. Agora, vamos passar esse nome remoto para git fetch para baixar os conteúdos.

git fetch coworkers feature_branch
fetching coworkers/feature_branch

Com os conteúdos de coworkers/feature_branch de que vamos precisar para integrar na cópia de trabalho local, começamos o processo usando o comando git checkout para verificar a ramificação remota recém-baixada.

git checkout coworkers/feature_branch
Note: checking out coworkers/feature_branch'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

O resultado dessa operação de verificação indica que estamos em um estado HEAD desvinculado. Isso é esperado e significa que a referência HEAD está apontando para uma referência que não está em sequência com o histórico local. Como HEAD é apontado na referência coworkers/feature_branch, podemos criar uma nova ramificação local a partir dessa referência. O resultado "HEAD desvinculado" mostra como fazer isso utilizando o comando git checkout:

git checkout -b local_feature_branch

Aqui, criamos uma nova ramificação local chamada local_feature_branch, o que faz com que as atualizações de HEAD indiquem o ponto mais recente, de onde é possível continuar o desenvolvimento.

Sincronize a origem com git fetch

O exemplo a seguir mostra o fluxo de trabalho típico para sincronizar o repositório local com o branch principal do repositório central.

git fetch origin

Esse comando exibe as ramificações que foram baixadas:

a1e8fb5..45e66a4 master -> origin/master
a1e8fb5..9e8ab1c develop -> origin/develop
* [new branch] some-feature -> origin/some-feature

The commits from these new remote branches are shown as squares instead of circles in the diagram below. As you can see, git fetch gives you access to the entire branch structure of another repository.

Para ver quais commits foram adicionados ao mestre da cadeia produtiva, você pode executar um git log usando origin/master como filtro:

git log --oneline master..origin/master

Aprove as mudanças e faça o merge no branch principal local com os seguintes comandos:

git checkout master
git log origin/master

Em seguida, use git merge origin/master:

git merge origin/master

As ramificações origem/mestre e mestre agora apontam para o mesmo commit e você está sincronizado com os desenvolvimentos upstream.

Resumo do git fetch

Revisando: git fetch é um comando básico usado para baixar conteúdos de um repositório remoto. O git fetch é usado em conjunto com git remote, git branch, git checkout e git reset para atualizar um repositório local ao estado de um remoto. O comando git fetch é parte crucial dos fluxos de trabalho colaborativo git. O git fetch tem comportamento semelhante ao git pull, mas o git fetch pode ser considerado uma versão mais segura e não destrutiva.