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

O fluxo do pull request ​

docs.scrimba.com

Você está trabalhando em uma funcionalidade na sua própria branch, e ela está pronta. O projeto é compartilhado: outras pessoas também fazem commits nele, então você não dá push direto para a main e espera que dê tudo certo. Você quer que a mudança seja revisada, discutida se for o caso, e integrada de um jeito que o resto do time possa acompanhar. Todo esse caminho, de uma branch na sua máquina até o código chegar na main, é o fluxo de pull request, e é assim que praticamente todo time no GitHub integra mudanças. O lado do Git nisso tudo usa só comandos de capítulos anteriores: uma branch, um commit e um push:

bash
$ git switch -c add-five-day-forecast
Switched to a new branch 'add-five-day-forecast'
$ git add src/forecast.js
$ git commit -m "Add five-day forecast panel"
$ git push -u origin add-five-day-forecast
Branch 'add-five-day-forecast' set up to track 'origin/add-five-day-forecast'.

Esse push envia sua branch para o GitHub. Nada foi mesclado ainda, e nada foi nem sequer proposto para revisão. O próximo passo, abrir o pull request, acontece no site do GitHub.

O que acontece quando você abre um pull request ​

No GitHub, depois de um push como esse, você geralmente vai ver um banner oferecendo comparar sua nova branch com a main. Clique nele, escreva um título e uma descrição curta do que mudou e por quê, e abra a página que ele cria. Essa página é um pull request, muitas vezes abreviado para PR: um pedido para mesclar uma branch em outra, com uma conversa em andamento anexada a ela.

Um pull request propõe um merge e espera aprovação. Alguém, talvez você mesmo, talvez um colega de time, lê a mudança, deixa comentários, e só faz o merge quando tudo estiver certo. Até isso acontecer, sua branch e a main continuam exatamente como estavam antes de você abrir a página.

Você não precisa esperar a funcionalidade estar terminada para abrir o PR. Muitos times abrem um PR bem no início e marcam como rascunho (draft), o que sinaliza "ainda não está pronto para revisão", mas já dá aos revisores um lugar para comentar sobre a direção antes do trabalho estar concluído. Uma boa descrição faz link para qualquer issue relacionada e diz o que você testou, para que o revisor não precise reconstruir isso só a partir do diff.

O GitHub mantém uma ref para cada pull request no remoto, mesmo antes de você adicionar a branch do PR ao seu próprio repositório: refs/pull/<number>/head. Faça o fetch dela diretamente para colocar o PR de um colega de time na sua máquina, sem precisar adicionar o fork dele como remoto primeiro.

bash
$ git fetch origin pull/42/head:pr-42
From github.com:mara-chen/weather-app
 * [new ref]         refs/pull/42/head -> pr-42
$ git switch pr-42
Switched to branch 'pr-42'

Agora pr-42 é uma branch local real, construída a partir do pull request número 42, pronta para você executar e testar antes de deixar um único comentário.

JunoO que acontece quando você abre um pull request Um pull request é um pedido para mesclar sua branch em outra, aberto no GitHub depois que você dá push. Alguém revisa a mudança primeiro, e só então ela é mesclada. O ciclo do dia a dia é: criar branch, dar push, abrir um pull request, passar por revisão, fazer merge.
JunoO que acontece quando você abre um pull request Um PR propõe um merge e concentra a conversa em torno dele, e você pode abrir um PR bem no início, como rascunho, para receber feedback antes do trabalho estar terminado. Escreva a descrição pensando que um revisor realmente vai ler: o que mudou, por quê, e o que você testou.
JunoO que acontece quando você abre um pull request O GitHub mantém uma ref oculta para cada pull request, refs/pull/<number>/head, então você pode buscar o PR de um colega de time direto na sua máquina com git fetch origin pull/42/head:pr-42, em vez de adicionar o fork dele como remoto. Teste a mudança localmente antes de deixar seu primeiro comentário.

Fork ou branch ​

Abrir um pull request a partir de uma branch funciona quando você tem acesso de escrita ao repositório, o que é o caso normal nos projetos do seu próprio time. Contribuir para um projeto ao qual você não tem acesso de escrita exige um passo extra: um fork, sua própria cópia do repositório na sua conta do GitHub.

Você cria branches e commits dentro do seu fork exatamente como faria em um projeto seu, dá push para o seu fork, e então abre o pull request da branch do seu fork de volta para o repositório original. O GitHub compara entre os dois repositórios do mesmo jeito que compara duas branches dentro de um único repositório, então o fluxo de revisão e merge parece idêntico nos dois casos.

Se você planeja enviar mais de um PR para um projeto que você fez fork, vale a pena adicionar o repositório original como um segundo remoto, geralmente chamado upstream, enquanto o origin continua apontando para o seu próprio fork. Execute git fetch upstream e faça o merge de upstream/main na sua branch para se atualizar em relação a um projeto que avançou desde que você o fez fork, usando os mesmos passos que o capítulo Remotos e GitHub cobre para qualquer remoto.

JunoFork ou branch Crie uma branch direto quando você tem acesso de escrita a um repositório, os projetos do seu próprio time. Faça um fork quando não tiver: um fork é sua própria cópia do repositório de outra pessoa, e você cria branches e dá push dentro dessa cópia antes de abrir o pull request de volta para o original.
JunoFork ou branch Um fork é uma cópia completa de um repositório na sua conta, usada para contribuir onde você não tem acesso de escrita. Você cria branches, faz commits e dá push dentro do seu fork normalmente, e o GitHub compara a branch do seu fork com o repositório original do mesmo jeito que compara duas branches dentro de um único projeto.
JunoFork ou branch Mantenha dois remotos em um projeto que você fez fork: origin para o seu próprio fork, upstream para o repositório original, para que você possa buscar e mesclar as mudanças dele conforme avança. O próprio PR continua comparando a branch do seu fork com a branch base do repositório original.

Fazendo seu pull request passar pela revisão ​

Depois que um PR é aberto, ele se torna uma conversa em andamento sobre o diff. Um revisor lê a mudança, deixa comentários em linhas específicas, e aprova ou solicita mudanças. Quando mudanças são solicitadas, continue fazendo commits e dando push para a mesma branch: cada push atualiza o mesmo PR em vez de criar um novo. Depois que um revisor aprova e qualquer verificação obrigatória passa, o PR está pronto para o merge.

O GitHub registra uma revisão em um de três estados: aprovado, mudanças solicitadas, ou comentado (feedback sem veredito definitivo). Responda aos comentários conforme os resolve e marque a conversa como resolvida, para que um revisor consiga ver rapidamente o que ainda falta. Se você fizer push de uma correção para um comentário específico, ajuda dizer isso na sua mensagem de commit ou em uma resposta, já que um revisor lendo um PR longo está justamente procurando por esse tipo de informação.

Quantas aprovações um PR precisa, e se toda thread de comentário precisa estar marcada como resolvida antes de o botão de merge liberar, geralmente é uma regra atrelada à própria branch base em um projeto bem administrado.

JunoFazendo seu pull request passar pela revisão Um revisor comenta no seu pull request e pode pedir mudanças. Faça commit e push de mais trabalho na mesma branch para resolver isso, e o PR se atualiza automaticamente. O merge acontece depois que alguém aprova.
JunoFazendo seu pull request passar pela revisão As revisões chegam em um de três estados: aprovado, mudanças solicitadas, ou comentado. Faça push de correções para a mesma branch para atualizar o PR, responda aos comentários conforme os resolve, e mantenha o revisor orientado em uma thread longa.
JunoFazendo seu pull request passar pela revisão Os estados de revisão determinam se o botão de merge libera, mas o critério exato, quantas aprovações, se toda thread de comentário precisa estar resolvida, geralmente é uma regra atrelada à própria branch base em um projeto bem administrado.

Por que um pull request não faz merge ​

Às vezes o botão de merge de um PR aparece acinzentado, e o GitHub mostra uma mensagem no lugar: "This branch has conflicts that must be resolved" ou "This branch is out of date with the base branch." As duas mensagens descrevem um estado normal e resolvível: a main avançou desde que você criou sua branch, geralmente porque o PR de outra pessoa foi mesclado nesse meio tempo, e sua branch precisa se atualizar antes que o GitHub consiga combinar as duas de forma limpa. Isso acontece em qualquer projeto com mais de um colaborador, então espere por isso em vez de temer.

Resolva isso localmente do mesmo jeito que você juntaria quaisquer duas branches:

bash
$ git switch add-five-day-forecast
$ git fetch origin
From github.com:mara-chen/weather-app
   9f8e7d6..b7c9e21  main       -> origin/main
$ git merge origin/main

Se nada se sobrepõe, o merge se completa sozinho e você dá push, e o PR se atualiza e o botão libera. Se as mesmas linhas mudaram nos dois lados, o Git marca o conflito no arquivo para você resolver exatamente como visto em Merge e conflitos: abra o arquivo, edite os marcadores de conflito até chegar ao resultado que você quer, depois git add e git commit para terminar o merge, e dê push de novo.

Um pull request travado precisa se atualizar ou ter seu conflito resolvido.

Em um PR que fica aberto por mais de um ou dois dias, vale a pena mesclar a main na sua branch de vez em quando, em vez de esperar o botão te bloquear. Uma branch com um dia de atraso geralmente faz merge sem nenhum conflito; uma com três semanas de atraso tem muito mais superfície para duas mudanças colidirem nas mesmas linhas. O próprio botão "Update branch" na página do PR do GitHub faz esse mesmo merge para você quando não há nada para resolver manualmente.

Alguns times fazem rebase de uma branch de funcionalidade sobre a main em vez de mesclá-la, para manter o histórico final linear em vez de mostrar um commit de merge para cada PR. Essa troca é a mesma abordada em Merge e conflitos: o rebase reescreve os commits da sua branch, o que é seguro enquanto você for a única pessoa com cópias deles, então uma branch de funcionalidade solitária, que só existe na sua máquina e no seu PR, é uma candidata razoável. Fazer rebase de uma branch que outras pessoas já puxaram e sobre a qual já construíram trabalho não é seguro, já que isso reescreve um histórico do qual elas dependem.

JunoPor que um pull request não faz merge Um botão de merge acinzentado significa que sua branch está atrás da main ou tem um conflito com ela. Nada está quebrado. Mude para sua branch, faça fetch, e mescle a main, resolvendo qualquer conflito do mesmo jeito que faria em qualquer outro lugar, depois dê push de novo.
JunoPor que um pull request não faz merge Mescle a main em uma branch de longa duração de vez em quando, em vez de esperar o GitHub bloquear o botão de merge. Atualizações menores e mais frequentes significam conflitos menores, e o botão "Update branch" do GitHub pode fazer o caso sem conflito por você.
JunoPor que um pull request não faz merge Tanto mesclar quanto fazer rebase da sua branch sobre a main resolvem um PR travado, e uma branch de funcionalidade solitária é segura para rebase, já que mais ninguém tem uma cópia dos seus commits. Depois que outras pessoas já puxaram uma branch, prefira sempre mesclá-la em vez de fazer rebase.

O que é um pull request, por dentro ​

Um pull request não é um objeto do Git, e não existe nenhum comando git que crie um. Git e GitHub não são a mesma coisa: o Git só conhece commits, branches e outras refs (uma ref é um nome que aponta para um commit). O GitHub constrói toda a página do PR, os comentários e o botão de merge por cima de duas refs que ele compara: sua branch (a head) e a branch para a qual você está mesclando (a base, geralmente a main). Essa comparação é o motivo de você abrir um pull request no site do GitHub (ou pela ferramenta de linha de comando ou API do próprio GitHub), e nunca com um comando git puro.

Como um PR vive no GitHub, separado do histórico do repositório, seus comentários e a conversa de revisão não viajam junto com os commits. Se você algum dia mudar um projeto para outra hospedagem, todo commit vai com você sem alteração, mas os pull requests e suas discussões ficam para trás, no GitHub, já que eles nunca fizeram parte dos dados do Git.

O GitHub calcula o diff de um PR encontrando a base de merge, o commit mais recente que a ref da head e a ref da base têm em comum, e comparando a head com esse ponto em vez de com o que a main está agora. Cada push para a branch adiciona uma nova versão ao mesmo PR, em vez de criar uma nova comparação. Branch protection (proteção de branch) é a camada de política que fica por cima de tudo isso: uma regra que você (ou sua organização) atrela a uma branch, quase sempre a main, que pode exigir a aprovação de verificações de status, exigir um número mínimo de revisões aprovando, e bloquear pushes diretos, forçando toda mudança a passar por um pull request. O Git em si não impõe nada disso. Ele vai deixar você dar push direto para a main a partir do seu terminal até o momento em que a regra do GitHub recusar o pedido.

JunoO que é um pull request, por dentro Um pull request é um recurso do GitHub construído em cima do Git: o Git rastreia commits e branches, e o GitHub adiciona a página do PR e o botão de merge comparando dois deles. Manter Git e GitHub separados na sua cabeça explica boa parte do que, do contrário, pareceria mágica.
JunoO que é um pull request, por dentro Um PR compara sua branch com uma branch base e vive inteiramente no GitHub, então seus comentários e histórico de revisão não se movem se o repositório algum dia mudar de hospedagem. Os commits em si são a única parte que é realmente Git.
JunoO que é um pull request, por dentro Um PR é o GitHub comparando uma ref head com uma ref base a partir da base de merge que elas compartilham, atualizado a cada push. Branch protection é a política aplicada por cima disso, exigindo verificações ou revisões antes do merge. O Git em si não impõe nada disso: ele vai deixar você dar push direto para a main até a regra do GitHub impedir.