O que exatamente queremos dizer com “ramo”?

Longa história curta…

Tanto quanto eu posso dizer, o termo “branch” (no jargão do Git) pode se referir a coisas relacionadas, mas diferentes:

  1. uma referência / ponteiro não simbólico para um commit,
  2. o nome de tal referência (por exemplo, “mestre”),
  3. o subgrafo do commit do repository DAG composto de todos os commits alcançáveis ​​do commit apontado por tal referência.

No entanto, eu vi o termo usado para se referir a algo diferente daqueles três possíveis usos (mais detalhes abaixo). Em um contexto Git, existem outros usos válidos e não ambíguos do termo “branch” que minha lista acima está faltando?

Mais detalhes

Depois de usar o Git por cerca de um ano, estou preparando um breve tutorial para os alunos do CS. Eu realmente quero descobrir a terminologia do Git, para evitar qualquer confusão.

Claro, eu tenho usado os ramos do Git por um tempo agora; Estou confortável em usá-los e acho o modelo de ramificação do Git incrível. No entanto, eu ainda acho o termo “branch” problemático e ambíguo, porque parece se referir a pelo menos duas coisas diferentes, dependendo do contexto em que é usado … às vezes até no mesmo tutorial / manual.

Uso 1: branch = ponteiro / referência a um commit

O livro Pro Git (em 3.1 – O que é um ramo ), depois de mostrar o diagrama a seguir,

insira a descrição da imagem aqui

continua a definir um ramo como

simplesmente um ponteiro móvel leve para um desses commits.

Tanto quanto eu posso dizer, este é também o significado de “branch” nas páginas de manual do Git.

Estou perfeitamente confortável com essa definição. Penso em uma ramificação como apenas uma referência que aponta para uma confirmação específica no DAG, e a “tip commit” de uma ramificação é a confirmação apontada por essa referência. Por enquanto, tudo bem. Mas espere…

Uso 2: branch = um subgrafo do DAG

O tutorial do Atlassian Git apresenta ramificações da seguinte forma:

Um ramo representa uma linha independente de desenvolvimento.

O que eles querem dizer com isso, eu acho, é uma sequência de commits. Deixe-me refinar esse pensamento … A única interpretação que faz sentido para mim é que o termo “branch” também pode se referir ao subgráfico do commit do repository DAG composto por todos os commits alcançáveis ​​a partir do commit tip considerado .

No entanto, o livro Pro Git, por exemplo, também contém o diagrama a seguir (consulte 3.4 – Fluxos de trabalho ramificados ),

insira a descrição da imagem aqui

o que parece contradizer minha interpretação, porque parece implicar que somente commites C2C5 (não C1 ) pertencem ao ramo de develop , e que somente commites C6C7 (não C1C5 ) pertencem ao ramo de topic .

Acho esse uso ambíguo e vago porque, se eu fosse desenhar o DAG nesse estágio, sem saber onde as referências de ramificação apontavam no passado, e sem qualquer suposição de hierarquia entre os três ramos, tudo que eu obteria seria

insira a descrição da imagem aqui

Eu também acho alguns diagramas em outros resources de aprendizado do Git confusos. Considere, em particular, o seguinte (tirado do vídeo de introdução do Lynda.com – Git Essential Training ):

insira a descrição da imagem aqui

Aqui, a ponta do master é na verdade 534de (e HEAD aponta para master ), mas a posição do label “master” no diagrama é muito enganosa. O que esse label deve descrever neste caso não está claro para mim …

Edit : Eu já encontrei este excelente post no blog de Marc ; a seção de Ramos ecoa minhas observações acima.

Você está certo.

Podemos dividir ainda mais seu item 1 separando os labels de ramificação “local” e “remoto”: ramificações locais (labels locais) são nomes que iniciam (internamente – muitos comandos front-end ocultam isso) com refs/heads/ , enquanto “ramificações remotas “- que também são chamados de” ramificações de rastreamento remoto “- inicie com refs/remotes/ e, em seguida, tenha um componente de caminho a mais nomeando o remoto específico antes da parte nomear o ramo. ( Edit, April 2018: Eu não gosto da frase “remote branch” ou “remote-tracking branch”; acho melhor apenas chamar esses nomes de controle remoto . Mas há muita documentação existente que usa as outras duas frases, por isso precisamos estar cientes desse uso.)

Por exemplo, você está sem dúvida familiarizado com refs/remotes/origin/master , mas se você tiver um controle remoto chamado bob você também pode ter refs/remotes/bob/hacks/feep que rastreiam o hacks/feep Bob.

Um nome de ramificação local refs/heads/ branch tem o recurso de distinção que o git checkout colocará “on” nessa ramificação por padrão, escrevendo esse nome na referência HEAD especial; e uma vez que você está configurado desta forma, novos commits (criados por git commit , git merge , git cherry-pick , etc.) fazem com que o novo SHA-1 do commit seja gravado no branch-file. (O novo commit tem como pai, ou um de seus pais, a velha ponta da ramificação.)

Eu tentei usar termos como “branch tip” para denotar especificamente o commit para o qual um nome de ramificação como refs/heads/master aponta, “branch name” ou “local branch name” para se referir ao próprio nome (prefixado por refs/heads/ or not), e – acho que é o menos bem-sucedido – “estrutura de ramificação” para se referir ao subconjunto do DAG. No entanto, dado um DAG com um fork-and-merge como este:

  o--o / \ ...-o--o o--o-... \ / o--o 

Eu às vezes quero me referir a uma ou outra metade do pequeno object de anel de benzeno como “um ramo” também, e não tenho um termo realmente bom para isso.

(Incidentalmente, se você fosse um topologista, o fato de que o diagrama Atlassiano também pode ser desenhado linearmente não o incomodaria. Entretanto, como diz a velha piada, os topologistas continuam tentando beber de seus donuts e comer suas canecas de café desde que cada um é apenas um toro.)

No segundo caso, queremos dizer “os commits que são alcançáveis ​​a partir do commit apontado pelo branch”.

No exemplo Pro Git, assumindo os pontos de ramificação de topic para confirmar C7 , esse ramo contém confirmações C7 , C6 , C5 , C4 , C3 , C2 e C1 . Não há nenhuma outra noção de um commit sendo “on” em um branch do que isso no Git, e você está correto que você poderia redesenhar o DAG linearmente.

O diagrama do Lynda.com é terrivelmente incerto, e eu suspeito que você esteja certo de que é enganoso.