Respostas:
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:
O repositório git .git
consiste 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:
.git/refs/heads/{name_of_branch}
.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-found
ou git-fsck --lost-found
e 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/HEAD
arquivo, que se parece com isso se você estiver no master
ramo.
ref: refs/heads/master
A alternância de ramificações simplesmente altera a referência no .git/HEAD
arquivo e depois altera o conteúdo da sua área de trabalho com as definidas na confirmaçã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:
trunk
, para um diretório de destino,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 update
disfarç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-submodule
mas 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 heads
sejam chamados tips
e branches
estão bookmarks
na terminologia do mercurial.
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.
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? .
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.
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'.
É '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').
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.