Skip to content
This page has been auto-translated and may contain errors.View in English

Remotos e GitHub

docs.scrimba.com

Todo repositório neste manual até agora viveu em um único lugar: sua própria máquina. Isso funciona bem até você querer um backup que sobreviva a um laptop morto, querer pegar o projeto de um segundo computador, ou querer que qualquer outra pessoa toque o código. O que você precisa é de uma cópia do repositório em algum lugar que toda máquina envolvida possa alcançar. Essa cópia é chamada de remoto, e o GitHub é onde a maioria dos desenvolvedores a coloca.

O que é um remoto (e onde GitHub se encaixa)

Um remoto é uma cópia do seu repositório hospedada em algum lugar que não seja sua própria máquina, na maioria das vezes no GitHub. Quando você clona um repositório, o Git já configura um para você, chamado origin por padrão. Execute git remote -v (o -v solicita as URLs assim como os nomes) para vê-lo:

bash
$ git remote -v
origin  https://github.com/joão-silva/weather-app.git (fetch)
origin  https://github.com/joão-silva/weather-app.git (push)

Todo remoto que o Git conhece é listado duas vezes, uma para buscar e uma para enviar, porque em teoria os dois poderiam apontar para endereços diferentes. Na prática são quase sempre o mesmo. origin é o apelido que o Git atribui automaticamente ao clonar. Você pode renomeá-lo ou adicionar um segundo remoto apontando para outro lugar, mas quase todo projeto que você tocar chamará seu remoto principal de origin.

Este é um bom momento para reafirmar a distinção que confunde quase todo mundo começando: Git e GitHub não são a mesma coisa. Git é a ferramenta de controle de versão rodando na sua máquina, registrando commits independentemente de você estar conectado a algo. GitHub é um site que hospeda uma cópia do seu repositório e oferece um remoto para enviar e receber. git remote, git push e git pull são os comandos que conectam os dois: é como o Git rodando no seu laptop fala com um repositório sentado nos servidores do GitHub.

Um remoto nada mais é do que um nome mapeado para uma URL, armazenado na configuração do seu repositório. Ao lado dele, o Git mantém uma branch de rastreamento remoto: um marcador local registrando onde uma branch no remoto estava da última vez que sua máquina fez uma verificação. origin/main é exatamente isso. Não é a branch main atual sentada no GitHub. É a memória do seu repositório de onde a main do GitHub estava na hora do seu último fetch ou pull. Liste as branches de rastreamento remoto que o Git atualmente mantém com git branch -r:

bash
$ git branch -r
origin/main

Tudo que um remoto faz passa por aquela entrada de configuração mais esses marcadores de rastreamento. Não há conexão em segundo plano e nada observando mudanças. O Git só atualiza sua visão do remoto quando você manda, com fetch ou pull, que é exatamente o que o resto deste capítulo cobre.

JunoO que é um remoto Um remoto é uma cópia do seu repositório hospedada em outro lugar, normalmente no GitHub, e o Git chama o padrão de origin. Execute git remote -v a qualquer momento para ver quais remotos seu repositório conhece. Git e GitHub não são a mesma coisa: Git é a ferramenta na sua máquina, GitHub é onde seu remoto frequentemente vive. Separar isso cedo economiza muita confusão depois.
JunoO que é um remotoorigin é apenas o nome padrão que o Git dá ao remoto que configura ao clonar, então você pode renomeá-lo ou adicionar mais remotos quando um projeto precisa deles. git remote -v mostra a URL de cada remoto tanto para fetch quanto para push. Mantenha a separação entre Git e GitHub em mente: os comandos que você executa localmente são Git, e GitHub é um destino entre vários que esses comandos podem alcançar.
JunoO que é um remoto Um remoto é um nome mapeado para uma URL na sua configuração, emparelhado com branches de rastreamento remoto como origin/main, a memória da sua máquina de onde aquela branch estava no seu último fetch ou pull. Nada se atualiza sozinho; o Git só verifica o remoto quando perguntado. Essa lacuna entre o que o GitHub realmente tem e o que seu branch de rastreamento remoto lembra está por trás de quase toda surpresa de fetch-versus-pull.

Onde hospedar seu remoto: GitHub e as alternativas

Tudo que um remoto faz é Git puro, e isso tem uma consequência que vale saber cedo: o host no outro fim é intercambiável. Para o Git, todo host é uma URL na sua configuração, e git push, git pull e git fetch se comportam de forma idêntica contra todos eles. O que um host adiciona fica uma camada acima: uma visualização web do seu código, um fluxo de revisão, rastreamento de problemas e controle de acesso. Aqui está o cenário, com as desvantagens explicadas claramente:

  • GitHub é o maior de longe e hospeda a grande maioria do trabalho de código aberto. Sua força é a rede: os projetos que você quer contribuir já estão lá, tutoriais assumem isso, e empregadores procuram seu perfil nele. A desvantagem é que é uma plataforma fechada (de propriedade da Microsoft), e quanto mais você depende de seus extras além de hospedagem Git, mais atado a ela você fica.
  • GitLab é a alternativa mais completa, com os mesmos recursos principais sob nomes ligeiramente diferentes (pull requests são "merge requests" lá). Seu destaque é uma edição auto-gerenciada que você pode executar em seus próprios servidores, que é por isso que empresas que mantêm código internamente frequentemente a escolhem. A desvantagem é que empacota muito, e a plataforma pode parecer mais pesada do que a hospedagem de código que você procurava.
  • Bitbucket é o host da Atlassian, construído para ficar ao lado de suas ferramentas de rastreamento de projetos e documentação, Jira e Confluence. Se seu time já vive nessas ferramentas, ela se encaixa perfeitamente. Fora desse ecossistema tem a menor comunidade dos três grandes e pouca presença de código aberto.
  • Codeberg é um host sem fins lucrativos para projetos de código aberto, executado na plataforma de código aberto Forgejo. O atrativo é que nenhuma empresa possui seu host e a plataforma em si é código aberto. A desvantagem é escala: menos integrações, uma comunidade menor e um foco em código aberto em vez de trabalho em equipe privado.
  • Auto-hospedagem está por baixo de tudo isso: execute Forgejo ou Gitea, ambos livres e de código aberto, ou a edição auto-gerenciada do GitLab em hardware que você controla. Você obtém controle total e privacidade; a desvantagem é que mantê-la funcionando se torna seu trabalho.

Este manual usa GitHub em seus exemplos porque hospeda a maioria do trabalho de código aberto e é onde você provavelmente colaborará primeiro. Todo comando neste capítulo se transfere sem mudanças para qualquer outro host: troque a URL e o loop diário permanece o mesmo. As diferenças vivem uma camada acima, na interface web de cada site para revisar e fazer merge do trabalho, que é onde o fluxo de pull request do próximo capítulo entra.

Quando a escolha é sua para fazer, raramente é sobre recursos de Git, porque o conjunto principal (repositórios hospedados, revisões, problemas, pipelines de CI) existe em todos os lugares. Se resume ao contexto: contribuir para código aberto ou construir um perfil público aponta para GitHub, uma empresa que funciona com ferramentas Atlassian aponta para Bitbucket, código que deve ficar na sua própria infraestrutura aponta para GitLab auto-gerenciado ou Forgejo, e um projeto de código aberto movido por valores pode se sentir mais em casa no Codeberg. A escolha também não é para sempre. Mover o repositório em si entre hosts é um git remote set-url mais um push; a parte cara de uma migração é a camada acima do Git, os problemas, wikis e configuração de CI, que não viajam com os commits.

Auto-hospedagem merece um olhar claro antes de você se comprometer com ela. Forgejo e Gitea rodam confortavelmente em um servidor pequeno, mas a carga operacional é real: atualizações de segurança, backups tanto dos repositórios quanto do banco de dados da plataforma, gerenciamento de conta e chave SSH, e tempo de atividade, porque uma forge desligada bloqueia todo push e pull que seu time faz. Vale a pena quando regras de conformidade mantêm código fora de infraestrutura de terceiros, em ambientes desconectados, ou quando uma organização quer suas ferramentas sob seu próprio controle. Abaixo da camada web nada muda: cada um desses hosts fala o mesmo protocolo Git, que é por isso que seu push e fetch não conseguem diferenciá-los.

JunoOnde hospedar seu remoto GitHub é onde a maioria dos projetos vive e o padrão mais seguro quando você está começando, mas é um host entre vários: GitLab, Bitbucket e o Codeberg sem fins lucrativos todos armazenam os mesmos repositórios Git. Push e pull funcionam igual onde quer que o remoto viva, então nada do que você aprende aqui é desperdiçado se um projeto vive em outro lugar.
JunoOnde hospedar seu remoto Os hosts diferem uma camada acima do Git: GitLab chama pull requests de merge requests e oferece uma edição auto-gerenciada, Bitbucket se conecta às ferramentas de Atlassian, e Codeberg roda no Forgejo de código aberto. Escolha baseado em onde seus colaboradores e ferramentas já estão, e lembre-se que uma migração posterior é barata do lado do Git; são os problemas e CI que não viajam.
JunoOnde hospedar seu remoto Como um remoto é um nome mapeado para uma URL, mover um projeto entre hosts é git remote set-url mais um push. Auto-hospedar Forgejo ou Gitea compra controle e privacidade e custa você patches, backups e tempo de atividade; faça esse trade quando a política exige, não por diversão, diz a pessoa que carregou o pager para um. Tudo específico do host vive na camada web acima do protocolo Git.

Enviando e obtendo seu trabalho: git push e git pull

Com um remoto em lugar, dois comandos cobrem a maioria do trabalho diário. git push envia seus commits locais até o remoto. git pull traz commits feitos em outro lugar e faz merge deles na branch que você está.

bash
$ git push origin main
Enumerating objects: 5, done.
Writing objects: 100% (3/3), 312 bytes | 312.00 KiB/s, done.
To https://github.com/joão-silva/weather-app.git
   9f8e7d6..a1b2c3d  main -> main

origin é o remoto, main é a branch que você está enviando. Aquela última linha é a parte que vale ler: mostra main no remoto se movendo de um commit para o próximo.

Pulling funciona do mesmo jeito, ao contrário:

bash
$ git pull origin main
remote: Enumerating objects: 4, done.
Unpacking objects: 100% (4/4), done.
Updating a1b2c3d..b7c9e21
Fast-forward
 src/index.js | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Esse é todo o loop para trabalhar junto com outras pessoas em um projeto: puxe o que mudou antes de começar, faça seu próprio trabalho e faça commit dele, empurre de volta. Puxe antes de você enviar sempre que você compartilhar uma branch com qualquer outra pessoa. Pule o pull e seu push pode pousar em cima de commits que você nunca viu, que o Git recusará em vez de arriscar perder o trabalho de alguém.

A primeira vez que você envia uma nova branch, adicione -u (abreviação de --set-upstream):

bash
$ git push -u origin feature/add-forecast-icons
Enumerating objects: 5, done.
Writing objects: 100% (5/5), 412 bytes | 412.00 KiB/s, done.
To https://github.com/joão-silva/weather-app.git
 * [new branch]      feature/add-forecast-icons -> feature/add-forecast-icons
branch 'feature/add-forecast-icons' set up to track 'origin/feature/add-forecast-icons'.

Isso registra feature/add-forecast-icons como rastreando origin/feature/add-forecast-icons, um link chamado de upstream. Uma vez definido, todo push e pull depois disso pode descartar o nome do remoto e da branch e executar simples git push ou git pull na branch. Se uma branch ainda não tem upstream configurado, o Git avisa e imprime o comando exato para corrigir, então você raramente precisa lembrar da flag, apenas reconhecer a mensagem quando ela aparecer.

Esse link upstream vive como duas linhas simples escritas na configuração do seu repositório no momento que -u roda: branch.feature/add-forecast-icons.remote nomeia o remoto, branch.feature/add-forecast-icons.merge nomeia a branch nele. Execute git config --get branch.main.remote em uma branch que você enviou antes e você verá exatamente esse valor voltar. Essas duas linhas são também o que git status lê para te contar que sua branch está dois commits à frente de origin/main, ou que os dois se afastaram: a comparação roda inteiramente contra seu branch de rastreamento remoto, uma verificação local sem nada buscado do GitHub. Defina o upstream uma vez, e todo contagem ahead-behind que o Git mostra para você depois está lendo desse mesmo par de linhas de configuração.

JunoEnviando e obtendo seu trabalhogit push envia seus commits até o remoto, e git pull traz commits feitos em outro lugar e faz merge deles na sua branch. Puxe antes de começar a trabalhar e envie quando terminar, e você fica sincronizado com qualquer outra pessoa tocando o projeto. Pular o pull é a razão mais comum para um push ser rejeitado.
JunoEnviando e obtendo seu trabalhogit push origin main envia commits, git pull origin main busca e faz merge deles, e uma vez que uma branch tem um upstream definido com git push -u, ambos os comandos funcionam sem nomear o remoto ou branch novamente. Puxe antes de você enviar em uma branch compartilhada, ou seu push é rejeitado porque o remoto já se moveu além de seu histórico local.
JunoEnviando e obtendo seu trabalho O upstream que você define com git push -u se resume a duas linhas de configuração, branch.<name>.remote e branch.<name>.merge, escritas no momento que a flag roda. git status lê esse mesmo par para te contar quão longe à frente ou atrás de origin/main sua branch está, uma comparação que ela faz inteiramente contra seu branch de rastreamento remoto local. Defina-o uma vez por branch e todo push ou pull abreviado, e toda contagem ahead-behind, é de graça.

git fetch vs git pull

git pull faz duas coisas em um passo: baixa o que mudou no remoto, então imediatamente faz merge dessas mudanças na branch que você está. git fetch faz apenas a primeira metade. Baixa novos commits mas nunca faz merge deles na sua branch. Sua branch atual, e seus arquivos de trabalho, ficam exatamente onde estavam até você contar ao Git para fazer merge ou pull.

Este é o tropeço que quase todo mundo acerta pelo menos uma vez: execute git fetch, não veja mudança visível em lugar nenhum, e assuma que nada aconteceu no remoto. Algo aconteceu: fetch não tocou sua branch de trabalho ainda. Para ver o que desceu, olhe para o branch de rastreamento remoto do início deste capítulo: git log origin/main mostra commits sentados no remoto que não chegaram na sua main local. Quando você está pronto para trazê-los, git merge origin/main faz, ou git pull roda fetch e esse merge para você em um comando.

Recorra a fetch por conta própria quando você quer olhar antes de fazer merge. Diga que um colega de trabalho, Carlos, menciona que enviou algo para main: git fetch seguido de git log origin/main ou git diff main origin/main deixa você ler exatamente o que mudou antes de pousar na sua branch de trabalho. Uma vez satisfeito, git merge origin/main traz. Dia a dia, a maioria das pessoas vai direto para git pull, porque ver e fazer merge em um passo é o que eles querem de qualquer forma. Fetch ganha sua manutenção em uma branch compartilhada onde você preferiria ler o trabalho de entrada primeiro, ou antes de decidir se agora é um bom momento para fazer merge.

O que fetch atualmente atualiza é governado por um refspec: um mapeamento, armazenado na configuração do seu remoto, que diz ao Git quais branches no remoto trazer e quais nomes locais armazenar sob. O refspec padrão em um clone normal lê aproximadamente como +refs/heads/*:refs/remotes/origin/*, significa "pegue cada branch sob os heads do remoto e espelhe em meus branches de rastreamento remoto, movendo-os para combinar mesmo se isso sobrescrever aonde eles costumavam apontar." Esse é o mecanismo inteiro por trás de origin/main ficar atual: fetch lê as branches do remoto e reescreve seus branches de rastreamento remoto para combinar, então para. Nada sobre seu próprio main muda até um merge separado, rebase ou pull agir sobre o que fetch trouxe.

Junogit fetch vs git pullgit pull baixa novos commits e faz merge deles na sua branch em um passo. git fetch apenas os baixa e atualiza a memória do Git sobre onde o remoto está; sua branch fica em paz até você fazer merge. Não ver mudança nos seus arquivos logo após um fetch é esperado, os novos commits estão esperando no branch de rastreamento remoto.
Junogit fetch vs git pullgit fetch baixa sem fazer merge, git pull baixa e faz merge em um passo. Recorra a plain fetch quando você quer ler commits de entrada com git log origin/main antes deles pousarem na sua branch, e pull quando você está pronto para fazer merge deles imediatamente. Misturar os dois é um dos mix-ups Git mais comuns em um time.
Junogit fetch vs git pull Um refspec decide exatamente o que fetch puxa e quais branches de rastreamento remoto ele atualiza, origin/main incluído, e o padrão espelha cada branch sob os heads do remoto. Fetch apenas move seus branches de rastreamento remoto, nunca sua branch verificada, então fazer merge ou pull permanece um passo separado e deliberado.

Onde isso o deixa

Push, pull e fetch levam seus commits para um remoto compartilhado e de volta novamente, o que cobre a maioria do que a colaboração do dia a dia em Git requer. Tudo aqui se constrói sobre o loop de commit: você ainda faz stage e commit localmente primeiro, um remoto apenas muda onde esses commits podem viajar. A próxima peça é fazer essa colaboração através do próprio GitHub, propondo uma mudança e tendo-a revisada antes de fazer merge. O fluxo de pull request pega exatamente ali. Se um termo neste capítulo ainda parecer instável, branch de rastreamento remoto, refspec, upstream, o Glossário tem uma definição simples para cada, e O que é Git vale uma segunda olhada para a distinção Git-versus-GitHub por conta própria.