Ao trabalhar com o git em uma equipe usando ramificações de recursos, muitas vezes acho difícil entender a estrutura da ramificação no histórico.
Exemplo:
Digamos que havia um recurso de ramificação de recurso / café , e a correção de erros continuou no mestre em paralelo ao ramo de recurso.
A história pode ficar assim:
* merge feature/make-coffee
|\
| * small bugfix
| |
* | fix bug #1234
| |
| * add milk and sugar
| |
* | improve comments
| |
* | fix bug #9434
| |
| * make coffe (without milk or sugar)
| |
* | improve comments
|/
*
Problema
À primeira vista, acho difícil dizer de que lado é o ramo do recurso. Normalmente, preciso procurar vários comentários de ambos os lados para ter uma idéia de qual é qual. Isso fica mais complicado se houver várias ramificações de recurso em paralelo (principalmente se forem para recursos intimamente relacionados) ou se houver uma fusão nas duas direções entre a ramificação de característica e o mestre.
Por outro lado, no Subversion, isso é significativamente mais fácil, porque o nome do ramo faz parte da história - para que eu possa dizer imediatamente que um commit foi originalmente feito em "feature / make-coffee".
O Git pode facilitar isso ao incluir o nome da ramificação atual nos metadados de confirmação ao criar uma confirmação (junto com autor, data etc.). No entanto, o git não faz isso.
Existe alguma razão fundamental para que isso não seja feito? Ou será que ninguém queria o recurso? Se for o último, existem outras maneiras de entender o propósito dos ramos históricos sem ver o nome?
Respostas:
Provavelmente porque os nomes das ramificações são significativos apenas em um repositório. Se eu estiver na
make-coffee
equipe e enviar todas as minhas alterações por meio de um gatekeeper, meumaster
ramo poderá ser puxado para omake-coffee-gui
ramo do gatekeeper , que ele mesclará com omake-coffee-backend
ramo, antes de mudar para ummake-coffee
ramo que será mesclado nomaster
ramo central .Mesmo em um repositório, os nomes das filiais podem mudar e mudar à medida que seu fluxo de trabalho evolui.
master
pode mudar mais tarde para ser chamadodevelopment
, por exemplo.Como o CodeGnome aludiu, o git tem uma forte filosofia de design de não inserir algo nos dados, se não for necessário. Espera-se que os usuários usem opções
git log
egit diff
produzam os dados ao seu gosto após o fato. Eu recomendo experimentar alguns até encontrar um formato que funcione melhor para você.git log --first-parent
, por exemplo, não mostrará as confirmações de uma filial que está sendo mesclada.fonte
Acompanhe o histórico de filiais com
--no-ff
No Git, um commit tem ancestrais, mas um "branch" é realmente apenas o chefe atual de alguma linha de desenvolvimento. Em outras palavras, uma confirmação é uma captura instantânea da árvore de trabalho em algum momento e pode pertencer a qualquer número de ramificações de uma só vez. Isso faz parte do que torna a ramificação do Git tão leve quando comparada a outros DVCSes.
As confirmações do Git não carregam informações de ramificação porque não são necessárias para o histórico do Git. No entanto, mesclagens que não são de avanço rápido certamente podem levar informações adicionais sobre qual ramificação foi mesclada. Você pode garantir que seu histórico contenha essas informações sempre passando o
--no-ff
sinalizador para suas mesclagens. O git-merge (1) diz:Isso geralmente criará uma mensagem de mesclagem semelhante a
Merge branch 'foo'
, para que você possa normalmente encontrar informações sobre "ramificações ancestrais" com uma linha semelhante à seguinte:fonte
git log --merges
.A resposta mais simples é que os nomes dos ramos são efêmeros. E se você fosse, digamos, renomear um ramo (
git branch -m <oldname> <newname>
)? O que aconteceria com todos os commits contra esse ramo? Ou, se duas pessoas tiverem ramificações com o mesmo nome em repositórios locais diferentes?A única coisa que tem significado no git é a soma de verificação do próprio commit. Esta é a unidade básica de rastreamento.
A informação está lá, você simplesmente não está pedindo, e não está exatamente lá.
O Git armazena a soma de verificação da cabeça de cada ramificação em
.git/refs/heads
. Por exemplo:(sim, estou usando minhas somas de verificação git, não é especial, mas são repositórios particulares que estou vendo no momento em que não precisam ter nada acidentalmente vazado).
Observando isso e rastreando todos os commit que têm isso como pai, ou os pais pai ou pai pais ... você pode descobrir em quais ramos um determinado commit está. É apenas um grande gráfico para renderizar.
Armazenar onde especificamente o nome de uma ramificação (que pode ser alterada conforme mencionado acima) uma confirmação está no próprio envio é uma sobrecarga extra na confirmação que não ajuda. Armazene o (s) pai (s) da confirmação e seu bem.
Você pode ver as ramificações executando o comando git log com o sinalizador apropriado.
Existem muitas maneiras diferentes de escolher o que você deseja para isso - veja a documentação do log do git - a
-all
seção e as poucas opções a seguir.Esse 'teste', 'teste1' e 'teste2' são os ramos com os quais eles foram comprometidos.
Observe que a documentação do git log é enorme e é possível obter quase tudo o que você deseja.
fonte
Por que as confirmações do git não contêm o nome da ramificação em que foram criadas?
Apenas uma decisão de design. Se você precisar dessas informações, adicione um gancho prepare-commit-msg ou commit-msg para aplicá-lo em um único repositório.
Após o desastre do BitKeeper, Linus Torvalds desenvolveu o git para corresponder ao processo de desenvolvimento do kernel do Linux. Lá, até que um patch seja aceito, ele é revisado, editado, polido várias vezes (por todo o Mail), desconectado (= editando um commit), escolhido pela cereja, vagando pelos ramos do tenente, talvez muitas vezes reformulado, mais edições, cereja -picaretas e assim por diante até que finalmente sejam fundidas a montante por Linus.
Nesse fluxo de trabalho, pode não haver origem específica de uma confirmação, e geralmente uma confirmação é criada em alguma ramificação de depuração temporária em algum repositório aleatório privado sem importância com nomes de ramificações engraçados, à medida que o git é distribuído.
Talvez essa decisão de design tenha acontecido por coincidência, mas corresponde exatamente ao processo de desenvolvimento do kernel Linux.
fonte
Como no Git, os commit como "fazer café" são considerados parte de ambos os ramos quando o ramo do recurso é mesclado. Existe até um comando para verificar isso:
Além disso, os ramos são baratos, locais e etéreos; eles podem ser facilmente adicionados, removidos, renomeados, enviados por push e excluídos do servidor.
O Git segue o princípio de que tudo pode ser feito, motivo pelo qual você pode remover facilmente uma ramificação de um servidor remoto e reescrever o histórico com facilidade.
Digamos que eu estava no ramo 'mestre' e fiz dois commits: 'faça café' e 'adicione leite e açúcar'; então, decido usar um novo ramo para isso, então redefini 'mestre' de volta para 'origem /mestre'. Não é um problema, toda a história ainda está limpa: 'fazer café' e 'adicionar leite e açúcar' não fazem parte do mestre, apenas recurso / fazer café.
Mercurial é o oposto; não quer mudar as coisas. As ramificações são permanentes, o histórico de reescritas é desaprovado, você não pode simplesmente excluir uma ramificação do servidor.
Resumindo: o Git permite que você faça tudo, o Mercurial quer facilitar as coisas (e torna realmente difícil deixá-lo fazer o que deseja).
fonte