O que significa "ramificação é gratuita" no Git?

27

O que significa "ramificação é gratuita" no Git?

Eu ouço muito isso sempre que o Git é mencionado em comparação com outros sistemas de controle de versão.

Não tive a oportunidade (?) De lidar com outras pessoas ( SVN etc.), então como a ramificação é "cara" nas outras pessoas?

atraso
fonte

Respostas:

28

A alegação de que "ramificação é livre no git" é uma simplificação dos fatos, porque não é "livre" em si. Olhando sob o capô, uma afirmação mais correta seria dizer que a ramificação é redonkulously barata , porque as ramificações são basicamente referências a confirmações . Eu defino "barato" aqui como menos sobrecarga, mais barato.

Vamos descobrir por que o Git é tão "barato" examinando que tipo de sobrecarga ele possui:

Como as ramificações são implementadas no git?

O repositório git .gitconsiste principalmente de diretórios com arquivos que contêm metadados que o git usa. Sempre que você cria uma ramificação no git, por exemplo git branch {name_of_branch}, algumas coisas acontecem:

  • Uma referência é criada para a filial local em: .git/refs/heads/{name_of_branch}
  • Um log de histórico é criado para a filial local em: .git/logs/refs/heads/{name_of_branch}

É basicamente isso, alguns arquivos de texto são criados. Se você abrir a referência como um arquivo de texto, o conteúdo será o id-sha da confirmação para a qual o ramo está apontando. Observe que a ramificação não exige que você faça nenhum commit, pois eles são outro tipo de objeto. Tanto as ramificações quanto as confirmações são "cidadãos de primeira classe" no git e uma maneira é pensar no relacionamento entre ramificações e confirmação como uma agregação e não uma composição. Se você remover uma ramificação, as confirmações ainda existirão como "pendentes". Se você removeu acidentalmente um ramo, você sempre pode tentar encontrar o commit com git-lost-foundou git-fsck --lost-founde criar um ramo no sha-id que você encontra pendurado (e enquanto o git ainda não fez nenhuma coleta de lixo).

Então, como o git monitora em qual ramo você está trabalhando? A resposta está no .git/HEADarquivo, que se parece com isso se você estiver no masterramo.

ref: refs/heads/master

A alternância de ramificações simplesmente altera a referência no .git/HEADarquivo e depois altera o conteúdo da sua área de trabalho com as definidas na confirmação.

Como isso se compara em outros sistemas de controle de versão?

No Subversion , as ramificações são diretórios virtuais no repositório . Portanto, a maneira mais fácil de ramificar é fazer remotamente, com uma única linha svn copy {trunk-url} {branch-url} -m "Branched it!". O que o SVN fará é o seguinte:

  • Copie o diretório de origem, por exemplo trunk, para um diretório de destino,
  • Confirme as alterações para finalizar a ação de cópia.

Você desejará executar esta ação remotamente no servidor, porque fazer essa cópia localmente é uma operação de tempo linear, com arquivos sendo copiados e vinculados. Esta é uma operação muito lenta , enquanto fazê-lo no servidor é uma operação de tempo constante. Note que, mesmo ao executar a ramificação no servidor, o subversion requer uma consolidação ao ramificar enquanto o git não, o que é uma diferença importante. Esse é um tipo de sobrecarga que torna o SVN marginalmente menos barato que o Git.

O comando para alternar ramificações no SVN , ou seja svn switch, é realmente o svn updatedisfarçado. Graças ao conceito de diretório virtual, o comando é um pouco mais flexível no svn do que no git. Os subdiretórios em sua área de trabalho podem ser alternados para espelhar outro URL do repositório. O mais próximo seria usar, git-submodulemas usá-lo é semanticamente bem diferente de ramificação. Infelizmente, essa também é uma decisão de design que torna a alternância um pouco mais lenta no SVN do que no Git, pois ele deve verificar todos os diretórios da área de trabalho com o URL remoto que está espelhando. Na minha experiência, o Git é mais rápido para alternar ramificações que o SVN.

A ramificação do SVN tem um custo, pois copia arquivos e sempre precisa ser disponibilizada ao público. No git, como explicado acima, as ramificações são "apenas referências" e podem ser mantidas em seu repositório local e publicadas à sua discrição. Na minha experiência, porém, o SVN ainda é notavelmente mais barato e com melhor desempenho do que, por exemplo, o ClearCase.

É apenas uma chatice que o SVN não seja descentralizado. Você pode ter vários repositórios espelhados em alguns repositórios de origem, mas sincronizar alterações diferentes de vários repositórios SVN não é possível, pois o SVN não possui identificadores exclusivos para confirmações (o git possui identificadores de hash com base no conteúdo da confirmação). A razão pela qual eu pessoalmente comecei a usar o git sobre o SVN é porque iniciar um repositório é notavelmente mais fácil e barato no git . Conceitualmente, em termos de gerenciamento de configuração de software, cada cópia divergente de um projeto (clone, fork, espaço de trabalho ou o que for) é uma "ramificação" e, dada essa terminologia, a criação de uma nova cópia no SVN não é tão barata quanto o Git, onde este último ramos "embutidos".

Como outro exemplo, no Mercurial , a ramificação começou um pouco diferente como um DVCS e a criação / destruição de ramificações nomeadas exigiu confirmações separadas. Os desenvolvedores do Mercurial implementados posteriormente nos indicadores de desenvolvimento para imitar o mesmo modelo de ramificação do git, embora headssejam chamados tipse branchesestão bookmarksna terminologia do mercurial.

Spoike
fonte
Uau. Muito obrigado pela explicação "cara".
laggingreflex
2
Da sua própria fonte: This command causes a near-instantaneous commit in the repository, creating a new directory in revision 341. The new directory is a copy of /calc/trunk.- Criar a ramificação é trivial no SVN, a menos que você esteja explicitamente fazendo uma cópia de cada arquivo.
Bobson 9/07/2013
@Bobson Eu estava pensando em reescrever os bits da ramificação, já que estou fazendo muita atenção com relação a isso, mas meu argumento ainda é que é necessário um commit para criar uma ramificação enquanto no Git não é. Na minha humilde experiência, ainda acho que a alternância de ramificações no SVN é mais lenta que no Git, mas não posso apontar nenhuma razão específica para isso.
Spoike
2
@ Spike - Switching, certamente. E um commit é definitivamente necessário. Fiz uma edição para esclarecer a parte com a qual tive um problema. Sinta-se livre para revertê-lo, se preferir.
22413 Bobson
20

O custo real de uma filial está mesclando-o. O Git torna isso mais fácil do que alguns outros sistemas de controle de origem. Consulte a pergunta Estouro de pilha Como e / ou por que a fusão no Git é melhor que no SVN? .

dan_waterworth
fonte
5
Estritamente, o Git apenas torna mais fácil do que alguns outros SCMs.
Donal Fellows
10

No Git, um branch é apenas uma referência a um commit no repositório local. Criá-lo é muito barato, sem rede. Não é totalmente gratuito (você precisa digitar um comando), mas muito perto.

A ramificação não é particularmente cara no SVN - é apenas uma cópia, que é um commit muito barato. O SVN tem um modelo de repositório central, portanto, é um acesso à rede, mas não é horrível.

No venerável CVS, por outro lado, a ramificação é MUITO cara. Basicamente, as ramificações do CVS envolvem a adição de uma tag, mas no CVS isso significa que TODOS OS ARQUIVOS AFETADOS devem ser modificados. Cada arquivo é reescrito para incluir a nova tag. Isso é terrivelmente caro. E se o seu repositório é grande, também é terrivelmente lento. De fato, se você estiver em um grande projeto, é lento o suficiente para que algumas pessoas evitem fazer filiais, se puderem.

Michael Kohne
fonte
4
Com o Git, é ainda menos que um commit - um ramo é apenas um rótulo. E o SVN parece tão caro quanto o CVS, pois ambos copiam todos os arquivos.
Izkata
8
@ Izkata: se vemos do ponto de vista do usuário - sim, todos os arquivos são copiados, do ponto de vista da implementação (e desempenho) - não, apenas um registro sobre a cópia é adicionado.
maxim1000
@ Izkata demais para comentar - veja minha resposta.
Gbjbaanb
6
O @Izkata SVN cria ponteiros e referências, não copia tudo.
Aaron McIver
2
Um ramo Git não é um commit, é apenas uma referência a um commit que pode ser movido livremente para outros commit. Pense em um repositório Git como apenas uma árvore de confirmações e ramificações como notas autoadesivas que podem ser movidas livremente para diferentes confirmações nessa árvore.
precisa saber é o seguinte
5

A ramificação do SVN é tão livre quanto a do Git. São apenas alguns dados de limpeza que indicam onde a ramificação é iniciada, sem alterações nos arquivos armazenados. Uma 'cópia' no SVN é como adicionar um link simbólico a um diretório Unix. Observe que a ramificação SVN não exigirá uma viagem de rede até você confirmar suas alterações na cópia de trabalho (mas não faz muito sentido ter um SCM se você não confirmar fora do local em algum momento).

Observe que uma ramificação do Git também envolverá algumas tarefas domésticas - como adicionar essa tag internamente - que precisarão ser armazenadas em algum lugar quando você confirmar. Não é nada demais, e é por isso que é chamado de 'grátis'.

gbjbaanb
fonte
5

É 'free' (nesse contexto, 'free' significa realmente rápido, fácil e sem ocupar espaço), porque em alguns sistemas de controle de versão mais antigos, uma ramificação era uma cópia completa do código naquele momento; portanto, as ramificações ocupavam muito espaço e era fácil acabar com várias versões completamente completas do software, que então assumiam o gerenciamento. Em outros, não era uma cópia completa do código, mas todos os arquivos ainda precisavam ser modificados para uma tag, por isso era lento e doloroso ('caro').

As ramificações do git são essencialmente rótulos apontando para um commit e, assim, evitam os problemas acima.

Michael Durrant
fonte
1

Outro aspecto de "grátis / barato / caro" diz respeito a quanto custa em termos de recursos do desenvolvedor para lidar com as conseqüências posteriores da ramificação; ou seja, o processo de mesclar as alterações dos ramos.

E aqui, mesclar filiais em sistemas DVCS como Git e Mercurial é mais fácil do que em sistemas antigos ... porque os sistemas DVCS fazem um trabalho muito melhor ao rastrear o histórico das versões no gráfico; ou seja, onde ocorreu uma ramificação anterior. Isso torna as mesclas mais precisas, reduz conflitos desnecessários e ... torna a fusão subjetivamente "mais fácil" ou "menos assustadora" para os desenvolvedores envolvidos.

Stephen C
fonte