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

Branches no Git

docs.scrimba.com

Você está no meio da construção de weather-app, e quer tentar adicionar um recurso de previsão de cinco dias. Isso pode levar vários commits para acertar, e enquanto não acerta, você não quer que código inacabado fique ao lado do app que já funciona para todos que o usam. Uma branch é como o Git resolve isso: uma linha separada de trabalho onde o experimento fica, enquanto main continua funcionando exatamente como antes de você começar.

O que uma branch realmente é

Aqui está em ação:

bash
$ git branch forecast
$ git switch forecast
Switched to branch 'forecast'

Dois comandos: o primeiro cria uma nova branch chamada forecast, o segundo move você para ela. A partir daqui, todo commit que você fizer vai para forecast enquanto main fica exatamente onde estava.

Uma branch é um rótulo móvel que aponta para um commit. Neste momento, main e forecast apontam para o mesmo commit, aquele em que você estava quando executou git branch forecast. No momento em que você faz um commit enquanto estiver em forecast, esse rótulo avança para o novo commit. main fica exatamente onde estava até você alternar para ele e fazer um commit lá você mesmo.

Você pode ver ambos os rótulos com git branch:

bash
$ git branch
  forecast
* main

O asterisco marca a branch em que você está atualmente. Uma branch é apenas um nome apontando para um commit. Esse é o mecanismo inteiro. Tudo mais neste capítulo é uma variação de mover esses rótulos.

Em um projeto real, nomes de branches carregam informação. Uma convenção comum é um prefixo curto descrevendo o tipo de mudança, seguido por uma descrição: feature/five-day-forecast, fix/broken-date-picker, chore/upgrade-eslint. Alguns times adicionam um número de ticket (feature/wa-142-forecast). Qualquer que seja a convenção que você escolha, mantenha-a consistente no projeto para que qualquer um possa dizer para o que uma branch serve sem abri-la.

O fluxo de trabalho que esses nomes suportam são branches de features de curta duração: crie uma branch para uma peça de trabalho, faça commits para ela, obtenha a mudança revisada e mesclada, depois delete a branch. Uma branch que vive por semanas fica muito diferente de main, e a eventual mesclagem fica mais difícil quanto mais essa diferença continua. As branches mais saudáveis terminam em dias.

Uma branch é pouco mais que um arquivo pequeno contendo um hash de commit, escondido nos próprios registros do Git. Criar um significa escrever essa única linha, é por isso que git branch termina instantaneamente mesmo em um repositório com anos de histórico. Essa mesma economia é por que as convenções de nomes e branches de curta duração importam na prática: deletar uma branch antiga não custa nada ao Git também, então nada impede que as abandonadas se acumulem exceto a disciplina do próprio time.

JunoO que uma branch realmente égit branch forecast cria um novo rótulo apontando para seu commit atual, e git switch forecast move você para ele. Nada sobre seus arquivos muda até você realmente fazer um commit lá. Gosto de pensar em branches como adesivos em um commit: baratos de adicionar, baratos de mover, baratos de remover quando você termina.
JunoO que uma branch realmente é Um nome de branch é um ponteiro, então criar um não custa nada e alternar entre eles é instantâneo. Dê aos branches nomes que descrevam o trabalho, como feature/five-day-forecast, e mantenha-os de curta duração: criar, fazer commit, mesclar, deletar. Branches de longa duração são as que transformam uma mesclagem rotineira em uma dor de cabeça real.
JunoO que uma branch realmente é Uma branch realmente é um arquivo pequeno contendo um hash de commit, é por isso que criar um é uma das operações mais baratas do Git. Convenções de nomes e branches de curta duração são como um time mantém seu trabalho paralelo legível; o Git em si não impõe nada. Limpei branches abandonadas de seis meses atrás o suficiente para ter opiniões fortes sobre isso.

Criando e alternando entre branches

git branch forecast por si só cria o rótulo sem mover você para lá. Na maioria das vezes você quer ambas as coisas de uma vez, então git switch tem um atalho:

bash
$ git switch -c forecast
Switched to a new branch 'forecast'

-c é abreviação para "create". git switch -c tanto cria quanto move você para uma branch. Esse comando único é aquele que você vai usar quase toda vez que começar um novo trabalho.

Alternar branches muda qual snapshot seus arquivos mostram. Tente: a linha echo abaixo é uma maneira de um passo de criar um novo arquivo, src/forecast.js, com uma única linha nele, e tudo o mais são comandos que você já conhece:

bash
$ git switch forecast
$ echo "// five-day forecast logic" > src/forecast.js
$ git add src/forecast.js
$ git commit -m "Start forecast module"
$ ls src
forecast.js  index.js
$ git switch main
Switched to branch 'main'
$ ls src
index.js

O arquivo não desapareceu. Ele vive na branch forecast, e o snapshot da branch main nunca o incluiu. Volte para forecast e ele reaparece exatamente como você o deixou.

Você verá um verbo mais antigo para isso em código existente e tutoriais: git checkout forecast faz o mesmo trabalho que git switch forecast. checkout é mais antigo e faz mais de uma coisa: dependendo do que você passar para ele, pode alternar branches ou restaurar um arquivo para uma versão anterior, e o nome do comando sozinho não diz qual está prestes a acontecer. switch e restore dividem esses dois trabalhos em comandos separados para que o nome diga antecipadamente: switch move você entre branches, restore coloca um arquivo de volta para como parecia em um commit dado. Use os verbos mais novos; reconheça checkout quando encontrá-lo em código existente.

checkout decide o que fazer com base no que você passa para ele: um nome de branch alterna branches, um caminho de arquivo restaura esse arquivo, e se um nome corresponde a ambos, o Git tem que adivinhar qual você quis dizer. Essa adivinhação é exatamente por que o comando foi dividido em dois. switch apenas muda branches e restore apenas muda arquivos, então um caminho digitado errado não pode mais lhe alternar para uma branch por acidente. Espere checkout em scripts e tutoriais mais antigos por anos ainda; escreva switch e restore em qualquer coisa nova.

JunoCriando e alternando entre branchesgit switch -c forecast cria uma branch e move você para ela em um passo, que é o que você usará quase toda vez. Alternar branches troca qual versão de seus arquivos você vê, então um arquivo adicionado em uma branch está ausente em outra até você voltar. Nada é perdido, fica estacionado na outra branch.
JunoCriando e alternando entre branchesgit switch -c name cria e move em um passo. Você encontrará git checkout name fazendo o mesmo trabalho em tutoriais e bases de código mais antigos; é a mesma ideia sob um comando mais antigo e sobrecarregado. Use switch diariamente e leia checkout sem hesitação quando o vir.
JunoCriando e alternando entre branchescheckout lida com alternância de branches e restauração de arquivos dependendo de seus argumentos, que é exatamente a ambiguidade que switch e restore foram divididos para remover. Espere ler checkout em scripts e tutoriais mais antigos por anos ainda; ainda funciona, não é mais o comando padrão para escrever.

HEAD e HEAD desanexado

O Git acompanha onde você está atualmente com um marcador chamado HEAD. Normalmente HEAD aponta para sua branch atual, e essa branch aponta para um commit, então HEAD se move automaticamente toda vez que você alterna ou faz um commit. Se você fazer checkout de um commit específico pelo seu hash, ou uma tag (um rótulo fixo fixado em um commit, frequentemente marcando um lançamento), em vez de um nome de branch, HEAD se anexa diretamente a esse commit em vez de a um rótulo de branch. Esse estado é chamado de HEAD desanexado.

Você pode olhar ao redor livremente lá, e pode até fazer commit, mas nada aponta para esses novos commits por nome. Se você alternar para uma branch sem criar uma primeiro, eles ficam difíceis de encontrar novamente.

bash
$ git switch a1b2c3d
HEAD is now at a1b2c3d Add password strength meter

Essa mensagem, "HEAD is now at", é o Git dizendo a você que você saiu do território das branches e anexou HEAD a um único commit.

No trabalho diário você raramente chega aqui por acidente. Acontece mais frequentemente quando você faz checkout de uma tag antiga ou um commit específico para ver como o código se comportava naquele ponto, ou quando uma ferramenta de build faz checkout de um commit exato para trabalhar com. Se você só quer olhar, está tudo bem: procure nos arquivos, rode o app, então alterne para uma branch quando terminar. Se você fazer uma mudança que vale a pena guardar enquanto desanexado, crie uma branch antes de alternar: git switch -c fix/old-bug desse estado desanexado dá ao commit um rótulo real para que sobreviva à alternância.

Um commit deixado para trás por um HEAD desanexado não é deletado no momento em que você alterna. Fica inacessível: ainda armazenado, sem nenhuma branch, tag, ou HEAD apontando para ele mais. O Git não limpa esses imediatamente também. Mantém um reflog, um registro de todos os lugares para os quais HEAD apontou, e um commit inacessível tipicamente sobrevive por semanas antes do Git realmente deletá-lo para sempre.

Isso lhe dá tempo real para recuperar, embora não dure para sempre. Fazer uma branch antes de alternar mantém o trabalho desanexado seguro. Cavar um commit de volta do reflog funciona hoje, mas a entrada expira eventualmente e um hash de commit sai da sua mente muito antes disso acontecer, então faça do branching um hábito e salve o reflog para a rara vez que você esqueça, coberto em Desfazendo coisas.

JunoHEAD e HEAD desanexado HEAD marca o commit em que você está atualmente, e geralmente viaja com qualquer branch em que você esteja. Se você fizer checkout de um commit específico em vez de uma branch, você fica com um HEAD desanexado, e qualquer novo commit que você faça lá não tem um nome de branch apontando para ele. Se isso acontecer e você quiser guardar o trabalho, faça uma branch no mesmo instante antes de alternar para qualquer outro lugar.
JunoHEAD e HEAD desanexado Você provavelmente conhecerá um HEAD desanexado quando fazer checkout de uma tag ou um commit antigo para olhar ao redor, e é inofensivo enquanto você está apenas lendo. No momento em que você faz commit de algo que vale a pena guardar, execute git switch -c bem ali para dar a ele uma branch antes de você ir para qualquer outro lugar.
JunoHEAD e HEAD desanexado Normalmente HEAD aponta para uma branch, que aponta para um commit. Desanexado, HEAD aponta direto para o commit, então qualquer coisa que você adicione lá não tem um nome de branch segurando quando você alterna. Raramente é ido para sempre já que o reflog mantém uma trilha, mas não conte com lembrar do hash do commit três semanas depois. Faça a branch antes de alternar, sempre.

Para onde isso leva

Você agora criou branches, se moveu entre elas, e viu como main fica intocada enquanto você experimenta em outro lugar. A próxima pergunta é como o trabalho em uma branch volta para main, que é exatamente o que Mesclando e conflitos cobre. Se você quer um refresco em ler histórico de commits antes de continuar, Histórico explora git log, git show, e git diff.