Práticas recomendadas de estratégia de ramificação do Subversion
Há muitos usos diferentes para ramificação e svn merge, e esta seção descreve os mais comuns.
O controle de versão é mais frequentemente usado para desenvolvimento de software, então aqui está uma rápida olhada em dois dos padrões mais comuns de ramificação / fusão usados por equipes de programadores. Se você não estiver usando o Subversion para desenvolvimento de software, fique à vontade para pular esta seção. Se você é um desenvolvedor de software que usa o controle de versão pela primeira vez, preste muita atenção, pois esses padrões geralmente são considerados práticas recomendadas por pessoas experientes. Esses processos não são específicos do Subversion; eles são aplicáveis a qualquer sistema de controle de versão. Ainda assim, pode ser útil vê-los descritos em termos do Subversion.
Liberar filiais.
A maioria dos softwares tem um ciclo de vida típico: codificar, testar, liberar, repetir. Existem dois problemas com este processo. Primeiro, os desenvolvedores precisam continuar criando novos recursos, enquanto as equipes de garantia de qualidade levam tempo para testar versões supostamente estáveis do software. Novo trabalho não pode parar enquanto o software é testado. Em segundo lugar, a equipe quase sempre precisa suportar versões mais antigas do software; Se um bug for descoberto no código mais recente, é mais provável que exista também nas versões lançadas, e os clientes desejarão obter essa correção de bug sem ter que esperar por uma nova versão importante.
Aqui é onde o controle de versão pode ajudar. O procedimento típico é assim:
Os desenvolvedores cometem todo o novo trabalho no tronco. As alterações do dia a dia são confirmadas no / trunk: novos recursos, correções de erros e assim por diante.
O tronco é copiado para uma ramificação "release". Quando a equipe acha que o software está pronto para ser lançado (digamos, uma versão 1.0), o / trunk pode ser copiado para /branches/1.0.
As equipes continuam a trabalhar em paralelo. Uma equipe inicia testes rigorosos do ramo de lançamento, enquanto outra equipe continua um novo trabalho (digamos, para a versão 2.0) em / trunk. Se os bugs forem descobertos em qualquer local, as correções serão transportadas para frente e para trás conforme necessário. Em algum momento, no entanto, até esse processo é interrompido. A ramificação está congelada para testes finais antes de uma liberação.
O ramo é marcado e liberado. Quando o teste estiver concluído, /branches/1.0 é copiado para /tags/1.0.0 como um instantâneo de referência. A tag é empacotada e liberada para os clientes.
A filial é mantida ao longo do tempo. Enquanto o trabalho continua em / trunk para a versão 2.0, correções de bugs continuam sendo portadas de / trunk para /branches/1.0. Quando consertos de bugs suficientes se acumulam, o gerenciamento pode decidir fazer uma versão 1.0.1: /branches/1.0 é copiado para /tags/1.0.1, e a tag é empacotada e liberada.
Todo esse processo é repetido à medida que o software amadurece: quando o trabalho do 2.0 é concluído, um novo branch de release 2.0 é criado, testado, marcado e, eventualmente, liberado. Depois de alguns anos, o repositório acaba com um número de ramificações de liberação em "manutenção" e um número de tags representando as versões finais enviadas.
Ramos de recursos.
Um branch de recursos é o tipo de branch que tem sido o exemplo dominante neste capítulo (aquele em que você está trabalhando enquanto Sally continua trabalhando / trunk). É uma ramificação temporária criada para trabalhar em uma alteração complexa sem interferir na estabilidade de / trunk. Ao contrário das ramificações do release (que talvez precisem ser suportadas para sempre), filiais de recursos nascem, são usadas por um tempo, mescladas de volta ao tronco e, finalmente, excluídas. Eles têm uma extensão finita de utilidade.
Mais uma vez, as políticas do projeto variam muito no que diz respeito exatamente quando é apropriado criar um ramo de recursos. Alguns projetos nunca usam ramificações de recursos: os commits para / trunk são gratuitos. A vantagem deste sistema é que é simples: ninguém precisa aprender sobre ramificação ou fusão. A desvantagem é que o código de tronco é muitas vezes instável ou inutilizável. Outros projetos usam ramificações ao extremo: nenhuma alteração é confirmada diretamente no tronco. Até mesmo as mudanças mais triviais são criadas em uma ramificação de curta duração, cuidadosamente revisadas e mescladas ao tronco. Em seguida, a ramificação é excluída. Este sistema garante um tronco excepcionalmente estável e utilizável em todos os momentos, mas ao custo de sobrecarga de processo tremenda.
A maioria dos projetos usa uma abordagem intermediária. Eles geralmente insistem que / trunk compile e passem os testes de regressão a todo momento. Um ramo de recurso é necessário apenas quando uma alteração requer um grande número de confirmações desestabilizadoras. Uma boa regra é fazer essa pergunta: se o desenvolvedor trabalhou por dias em isolamento e depois cometeu a grande alteração de uma só vez (para que / trunk nunca fosse desestabilizado), seria uma mudança muito grande para revisar? Se a resposta a essa pergunta for sim, a mudança deve ser desenvolvida em um ramo de recurso. Conforme o desenvolvedor confirma alterações incrementais na ramificação, elas podem ser facilmente revisadas pelos colegas.
Finalmente, há a questão de como manter um ramo de recursos em sincronia com o tronco à medida que o trabalho progride. Como mencionamos anteriormente, há um grande risco de trabalhar em um ramo por semanas ou meses; as trocas de tronco podem continuar a chegar, até o ponto em que as duas linhas de desenvolvimento diferem tanto que pode se tornar um pesadelo tentar mesclar o ramo de volta ao tronco.
É melhor evitar essa situação mesclando regularmente as alterações do tronco na filial. Crie uma política: uma vez por semana, mescle as alterações de tronco da última semana na agência.
Quando você estiver pronto para mesclar o ramo de recurso sincronizado de volta ao tronco, comece fazendo uma mesclagem final das alterações de tronco mais recentes na ramificação. Quando isso for feito, as versões mais recentes da ramificação e do tronco são absolutamente idênticas, exceto pelas alterações na ramificação. Você então mescla de volta com a opção --reintegrate:
Outra maneira de pensar sobre esse padrão é que sua sincronização semanal de tronco para filial é análoga à execução do svn update em uma cópia de trabalho, enquanto a etapa final de mesclagem é análoga à execução de svn commit de uma cópia de trabalho. Afinal, o que mais é uma cópia de trabalho, mas um ramo privado muito superficial? É um ramo capaz de armazenar apenas uma alteração por vez.
Práticas recomendadas de estratégia de ramificação do Subversion
A empresa para a qual trabalho está começando a ter problemas com seu atual modelo de ramificação e fiquei me perguntando para quais diferentes tipos de estratégias de ramificação a comunidade foi exposta?
Há algum bom para situações diferentes? O que sua empresa usa? Quais são as vantagens e desvantagens deles?
fechado como não construtivo por casperOne Fev 24 '12 às 19:53.
No momento, esta questão não é adequada para o nosso formato de perguntas e respostas. Esperamos que as respostas sejam apoiadas por fatos, referências ou especialização, mas essa questão provavelmente solicitará debates, discussões, pesquisas ou discussões ampliadas. Se achar que esta questão pode ser melhorada e possivelmente reaberta, visite o centro de ajuda para obter orientação. Se essa questão puder ser reformulada para se ajustar às regras da Central de Ajuda, edite a pergunta.
17 respostas.
Aqui está o método que usei no passado com bom sucesso:
/ tronco - margem de sangramento. Próximo lançamento principal do código. Pode ou não pode trabalhar a qualquer momento.
/branches/1.0, 1.1, etc. Ramos de manutenção estáveis do código. Usado para corrigir erros, estabilizar novos lançamentos. Se um ramo de manutenção, ele deve compilar (se for o caso) e estar pronto para QA / envio a qualquer momento. Se um ramo de estabilização, ele deve compilar e ter recursos completos. Nenhum novo recurso deve ser adicionado, nenhuma refatoração e nenhuma limpeza de código. Você pode adicionar um pré-prefixo para indicar ramos de estabilização vs ramos de manutenção.
/ branches / cool_feature. Usado para trabalhos altamente experimentais ou destrutivos que podem ou não entrar no tronco (ou um ramo de manutenção). Não há garantias de compilar, trabalhar ou se comportar de maneira adequada. Deve durar o mínimo de tempo possível antes de se fundir na ramificação da linha principal.
/tags/1.0.1, 1.0.2, 1.1.3a, etc. Usado para marcar um pacote & amp; lançamento enviado. Nunca muda sempre. Faça quantas tags quiser, mas elas são imutáveis.
Eu recomendo fortemente ler a opinião de Eric Sink sobre o assunto:
Eu, como Eric, prefiro o estilo de "pasta" que ele fala.
Para o filão mãe sobre padrões de ramificação, veja Linhas Transplantadas de Brad Appleton: Padrões de Ramificação para Desenvolvimento de Software Paralelo. É pesado, mas não vi nada para superá-lo em termos de amplitude e profundidade de conhecimento sobre ramificação.
Nosso repositório se parece com:
/ trunk é o seu desenvolvimento padrão e de ponta. Usamos o CI para que isso sempre seja feito e aprovado nos testes.
/ branches é onde nós colocamos grandes mudanças 'sancionadas', ou seja, algo que sabemos que irá transformá-lo em tronco, mas pode precisar de algum trabalho e quebrar CI. Também onde trabalhamos em versões de manutenção, que possuem seus próprios projetos de CI.
/ sandbox cada desenvolvedor tem sua própria sandbox, além de uma sandbox compartilhada. Isso é para coisas como "Vamos adicionar um provedor LINQ ao nosso produto" tipo de tarefas que você faz quando você não está fazendo seu trabalho real. Pode eventualmente entrar no tronco, pode não ser, mas está lá e sob controle de versão. Não há CI aqui.
/ vendedor padrão do fornecedor para projetos nos quais compilamos, mas não é o código que mantemos.
/ ccnet são nossas tags de CI, somente o servidor de IC pode gravar aqui. A retrospectiva teria nos dito para renomear isso para algo mais genérico, como CI, BUILDS, etc.
Uma ramificação para o desenvolvimento ativo (/ main ou master, dependendo do jargão) Um branch para cada release de manutenção -> ele receberá apenas pequenas correções, enquanto todo o desenvolvimento principal vai para / main Um branch para cada nova tarefa: criar um novo ramo para trabalhar em cada nova entrada no seu Bugzilla / Jira / Rally. Comprometa-se com frequência, documente a alteração usando check-ins de seixos em polegadas e mescle-a de volta à sua ramificação "pai" somente quando estiver concluída e bem testada.
A primeira coisa: KISS (Mantenha isso simples, estúpido!)
* 1) Manter a manutenção da versão - por exemplo, Service Packs, Hotfixes, correções de erros que podem ser mescladas ao tronco, se necessário e / ou necessário) * 2) major. minor. build. revision.
A pasta Tags não precisa ser registrada Apenas poucas codificações em ramificações de lançamento (simplifica a mesclagem) - sem limpeza de código, etc. Nunca codificar na pasta de tags Nunca coloque informações concretas de versão em arquivos de origem. Use Place-holders ou 0.0.0.0 que o mecanismo de compilação irá substituir pelo número de versão que você está construindo Nunca coloque bibliotecas de terceiros em seu controle de origem (também ninguém adicionará bibliotecas STL, MFC etc. ao SVN ;-)) Apenas código de commit que compila Prefer usando variáveis de ambiente ao invés de caminhos hard-coded (caminhos absolutos e relativos)
Nós nos ramificamos quando um lançamento está pronto para o controle de qualidade final. Se algum problema for descoberto durante o processo de controle de qualidade, os bugs serão corrigidos na filial, validados e depois mesclados no tronco. Depois que o branch passa no controle de qualidade, nós o marcamos como um lançamento. Quaisquer hotfixes para essa versão também são feitos na ramificação, validados, mesclados ao tronco e, em seguida, marcados como uma release separada.
A estrutura da pasta seria semelhante a esta (1 linha de controle de qualidade, 2 lançamentos de hotfix e o tronco):
Usamos o estilo selvagem, selvagem e ocidental dos ramos-git. Temos algumas ramificações que têm nomes conhecidos definidos por convenção, mas, no nosso caso, as tags são realmente mais importantes para atender aos requisitos da política de processos corporativos.
Eu vi abaixo que você usa o Subversion, então estou pensando que você deveria verificar a seção sobre ramificação no Subversion Book. Especificamente, observe a seção "layout do repositório" em Manutenção de Filial e Padrões de Filial Comuns.
A alternativa que não estou vendo aqui é uma filosofia "Branch on Change".
Em vez de ter o seu porta-malas "Wild West", e se o porta-malas for o "Current Release"? Isso funciona bem quando há apenas uma versão do aplicativo lançada por vez - como um site. Quando um novo recurso ou correção de bug é necessário, uma ramificação é feita para manter essa alteração. Geralmente, isso permite que as correções sejam migradas para serem liberadas individualmente e impede que os codificadores de caubóis adicionem acidentalmente um recurso a ser lançado que você não pretendia. (Muitas vezes é um backdoor - "Apenas para desenvolvimento / teste")
Os ponteiros de Ben Collins são bastante úteis para determinar qual estilo funcionaria bem para sua situação.
O Controle de Versão de Henrik Kniberg para Múltiplas Equipes Ágeis também tem alguns pontos positivos a serem levados em consideração.
Atualmente, temos uma filial para manutenção contínua, um ramo para "novas iniciativas", que significa apenas "coisas que sairão em algum momento no futuro; não temos certeza de quando". Ocasionalmente, também tivemos dois ramos de manutenção: um para fornecer correções para o que está atualmente em produção e outro que ainda está em QA.
A principal vantagem que vimos é a capacidade de reagir às solicitações e emergências do usuário mais rapidamente. Podemos fazer a correção na ramificação que está em produção e liberá-la sem liberar nada extra que já tenha sido verificado.
A principal desvantagem é que acabamos fazendo muitas mesclagens entre filiais, o que aumenta a chance de que alguma coisa seja perdida ou mesclada incorretamente. Até agora, isso não tem sido um problema, mas é definitivamente algo para se ter em mente.
Antes de instituirmos esta política, geralmente fazíamos todo o desenvolvimento no tronco e apenas ramificávamos quando lançávamos o código. Em seguida, fizemos correções contra esse ramo, conforme necessário. Era mais simples, mas não tão flexível.
Jeff Atwood escreveu sobre isso em um bom post no blog; Esse post tem alguns links importantes nele.
Gnat escreveu esta excelente análise dos vários conselhos que você pode encontrar em estratégias de ramificação.
Não há uma estratégia de ramificação, é para isso que funciona:
O tamanho da sua equipe Seu produto e os períodos do ciclo de vida A tecnologia que você está usando (aplicativos da Web, incorporados e do Windows) Seu controle de origem, por exemplo, Git, TFS, Hg.
O post de Jeff Atwood divide várias possibilidades. Outro a acrescentar é o conceito de promoção (do link de Ryan Duffield). Nesta configuração você tem uma ramificação dev, testa bracnh e libera a ramificação. Você promove seu código até que ele atinja o ramo de lançamento e seja implantado.
Práticas recomendadas de estratégia de ramificação do Subversion
Qual é a melhor estratégia de ramificação a ser usada quando você deseja fazer integração contínua?
Libertar Ramificação: desenvolver no tronco, manter um ramo para cada lançamento. Recurso ramificação: desenvolver cada recurso em um ramo separado, apenas mesclar uma vez estável.
Faz sentido usar essas duas estratégias juntas? Como em, você ramifica para cada lançamento, mas você também ramifica para grandes recursos? Uma dessas estratégias combina melhor com a integração contínua? O uso de integração contínua faria sentido ao usar um tronco instável?
11 respostas.
A resposta depende do tamanho da equipe e da qualidade do controle de origem e da capacidade de mesclar conjuntos de mudanças complexos corretamente. Por exemplo, no controle de fonte de ramificação completa como CVS ou SVN, a fusão pode ser difícil e você pode estar melhor com o primeiro modelo, enquanto se estiver usando um sistema mais complexo como o IBM ClearCase e com um tamanho maior de equipe, modelo ou uma combinação dos dois.
Eu pessoalmente separaria o modelo de ramificação de feições, onde cada característica principal é desenvolvida em uma ramificação separada, com sub-ramificações de tarefas para cada modificação feita pelo desenvolvedor individual. À medida que os recursos se estabilizam, eles são mesclados ao tronco, que você mantém razoavelmente estável e passando em todos os testes de regressão o tempo todo. À medida que você se aproxima do final de seu ciclo de lançamento e todos os ramos de recursos se mesclam, você estabiliza e ramifica uma ramificação do sistema de lançamento na qual você faz apenas correções de bugs de estabilidade e backports necessários, enquanto o tronco é usado para desenvolvimento da próxima versão e você novamente ramificar para novos ramos de recurso. E assim por diante.
Desta forma, o trunk contém sempre o código mais recente, mas você consegue mantê-lo razoavelmente estável, criando rótulos estáveis (tags) em grandes mudanças e mesclagens de recursos, os ramos de recursos são desenvolvimento rápido com integração contínua e sub-ramificações de tarefas individuais atualizado a partir do ramo de recursos para manter todos trabalhando no mesmo recurso em sincronia, sem afetar outras equipes que trabalham em diferentes recursos.
Ao mesmo tempo, você tem através do histórico um conjunto de releases, onde você pode fornecer backports, suporte e correções de bugs para seus clientes que, por qualquer motivo, permanecem em versões anteriores de seu produto ou até mesmo na última versão lançada. Tal como acontece com o tronco, você não configura a integração contínua nos ramos de lançamento, eles são cuidadosamente integrados ao passarem por todos os testes de regressão e outro controle de qualidade do release.
Se, por algum motivo, dois recursos forem co-dependentes e precisarem de alterações feitos um pelo outro, você poderá considerar desenvolver ambos no mesmo ramo de recursos ou exigir que os recursos mescle regularmente partes estáveis do código no tronco e, em seguida, atualize as alterações tronco para troca de código entre os ramos do tronco. Ou, se você precisar isolar esses dois recursos de outros, poderá criar uma ramificação comum na qual ramificará essas ramificações de recurso e poderá usá-la para trocar códigos entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de código-fonte sem ramificações esparsas e capacidade de mesclagem adequada como CVS ou SVN, o que tornaria todo esse modelo um pesadelo para configurar, gerenciar e integrar.
Recurso ramificando seu caminho para a grandeza.
Ou tarefa ramificando seu caminho até lá. Ou libere ramificações. Você escolhe.
Quase todos os sistemas de controle de versão atualmente suportam ramificações - linhas independentes de trabalho que derivam de uma base de código central. Dependendo do sistema de controle de versão, o ramo principal pode ser chamado de mestre, principal, padrão ou tronco. Os desenvolvedores podem criar suas próprias ramificações a partir da linha de código principal e trabalhar de forma independente ao lado dela.
Por que se preocupar com ramificação?
A ramificação permite que equipes de desenvolvedores colaborem facilmente dentro de uma base de código central. Quando um desenvolvedor cria uma ramificação, o sistema de controle de versão cria uma cópia da base de código naquele momento. As alterações na agência não afetam outros desenvolvedores da equipe. Isso é uma coisa boa, obviamente, porque os recursos em desenvolvimento podem criar instabilidade, o que seria altamente prejudicial se todo o trabalho estivesse acontecendo na linha de código principal. Mas as filiais não precisam viver em confinamento solitário. Os desenvolvedores podem facilmente remover as alterações de outros desenvolvedores para colaborar em recursos e garantir que sua ramificação privada não seja muito distante do mestre.
Os branches não são bons apenas para o trabalho de recursos. Filiais podem isolar a equipe de importantes mudanças arquiteturais, como a atualização de estruturas, bibliotecas comuns etc.
Três estratégias de ramificação para equipes ágeis.
Os modelos de ramificação geralmente diferem entre as equipes e são assunto de muito debate na comunidade de software. Um grande tema é quanto trabalho deve permanecer em um branch antes de ser mesclado de volta ao master.
Liberar ramificação.
Liberar ramificação refere-se à ideia de que uma liberação está contida inteiramente dentro de uma ramificação. Isso significa que, no final do ciclo de desenvolvimento, o gerente de lançamento criará uma ramificação do mestre (por exemplo, & ldquo; 1.1 filial de desenvolvimento & rdquo;). Todas as alterações para a versão 1.1 precisam ser aplicadas duas vezes: uma vez para a ramificação 1.1 e, em seguida, para a linha de código principal. Trabalhar com duas filiais é um trabalho extra para a equipe e é fácil esquecer de se mesclar a ambas as filiais. As ramificações de versão podem ser difíceis e difíceis de gerenciar, já que muitas pessoas estão trabalhando no mesmo ramo. Todos nós sentimos a dor de ter que mesclar muitas mudanças diferentes em um único ramo. Se você deve fazer um branch de release, crie o branch o mais próximo possível do release atual.
O lançamento de ramificações é uma parte importante do suporte a softwares com versão no mercado. Um único produto pode ter vários ramos de liberação (por exemplo, 1.1, 1.2, 2.0) para suportar o desenvolvimento de sustentação. Lembre-se de que as alterações nas versões anteriores (por exemplo, 1.1) podem precisar ser mescladas em filiais de liberação posteriores (por exemplo, 1.2, 2.0). Confira nosso webinar abaixo para saber mais sobre o gerenciamento de filiais de lançamento com o Git.
Ramificação de recursos.
Os ramos de funcionalidades são frequentemente associados a flags de funcionalidades & ndash; & quot; alterna & quot; que habilitam ou desabilitam um recurso dentro do produto. Isso facilita a implantação do código no mestre e no controle quando o recurso é ativado, facilitando a implantação inicial do código antes que o recurso seja exposto aos usuários finais.
Outro benefício de sinalizadores de recursos é que o código pode permanecer dentro da compilação, mas inativo enquanto está em desenvolvimento. Se algo der errado quando o recurso estiver habilitado, um administrador do sistema poderá reverter o sinalizador de recurso e voltar a um bom estado conhecido, em vez de precisar implantar uma nova compilação.
Tarefa Ramificação.
Na Atlassian, nos concentramos em um fluxo de trabalho de ramificação por tarefa. Cada organização tem uma maneira natural de dividir o trabalho em tarefas individuais dentro de um rastreador de problemas, como o Jira Software. Questões, em seguida, torna-se ponto de contato central da equipe para esse trabalho. A ramificação de tarefas, também conhecida como ramificação de problemas, conecta diretamente esses problemas ao código-fonte. Cada problema é implementado em sua própria ramificação com a chave de problema incluída no nome da ramificação. É fácil ver qual código implementa o problema: basta procurar a chave de problema no nome da ramificação. Com esse nível de transparência, é mais fácil aplicar alterações específicas na ramificação de lançamento legado em execução ou mestre.
Como os centros ágeis em torno de histórias de usuários, os ramos de tarefas combinam bem com o desenvolvimento ágil. Cada história de usuário (ou correção de bug) reside em sua própria ramificação, facilitando a visualização de quais problemas estão em andamento e quais estão prontos para serem lançados. Para um mergulho profundo na ramificação de tarefas (às vezes chamada de ramificação de problema ou branch-por-issue), pegue um pouco de pipoca e confira a gravação do webinar abaixo - um dos mais populares de todos os tempos.
Agora encontre o gêmeo maligno da ramificação: a fusão.
Todos sofremos a dor de tentar integrar vários ramos em uma solução sensata. Tradicionalmente, sistemas centralizados de controle de versão, como o Subversion, fizeram da fusão uma operação muito dolorosa. Mas os sistemas de controle de versão mais recentes, como o Git e o Mercurial, adotam uma abordagem diferente para rastrear versões de arquivos que residem em diferentes filiais.
As ramificações tendem a ter vida curta, facilitando a mesclagem e a flexibilidade na base de código. Entre a capacidade de mesclar freqüências e automaticamente ramificações como parte da integração contínua (CI) e o fato de que as ramificações de vida curta simplesmente contêm menos alterações, & quot; mesclar o inferno & quot; Torna-se uma coisa do passado para as equipes que usam Git e Mercurial.
É isso que torna a ramificação de tarefas tão incrível!
Valide, valide, valide.
Um sistema de controle de versão só pode ir tão longe ao afetar o resultado de uma mesclagem. Testes automatizados e integração contínua também são críticos. A maioria dos servidores de CI pode colocar automaticamente novos ramos em teste, reduzindo drasticamente o número de "surpresas" na junção final do upstream e ajudando a manter a linha de código principal estável.
Blog do FileCloud.
Os sistemas de controle de versão desempenham um papel vital no sucesso de uma equipe de desenvolvimento de software. Este blog tem como objetivo fornecer uma estratégia simples de ramificação e mesclagem para gerenciar o código em um ambiente de desenvolvimento de equipe de ritmo acelerado.
Quando você precisa de ramificação?
Você pode precisar adotar ramificações em muitos cenários diferentes. Vamos supor que, no dia a dia, você use metodologias ágeis, como programação extrema ou scrum, e finalmente liberou um projeto razoavelmente complexo com a versão 1.0.0.0. Alguns dias após o lançamento, você recebe uma solicitação para um novo recurso que deve ir como a versão 1.1.0.0. Você imagina que levará algumas semanas para que o recurso seja codificado, testado e liberado. Enquanto isso, modificações e correções simples são solicitadas no dia a dia na versão 1.0.0.0.
Essencialmente, com as necessidades de negócios em mudança, você é obrigado a fazer uma implantação a cada dois dias, ou seja, seu ciclo de implantação é de 2 dias ou menos.
Com uma equipe de 10 desenvolvedores, será um pesadelo na ausência de uma estratégia de ramificação adequada.
Tronco, filial e tag são as 3 principais divisões no repositório do subversion.
O código no tronco é sempre mantido o mais próximo possível do estado de liberação. Qualquer desenvolvedor que fizer alterações no tronco deve ter absoluta certeza de que sua parte pode ser codificada, testada e pronta para ser implantada em dois dias (pode variar dependendo do seu ciclo de implantação). Se demorar mais de dois dias, eles não poderão alterar diretamente o código no tronco. Eles têm que criar um ramo.
Cada desenvolvedor deve criar sua própria ramificação se o código levar mais tempo para ser programado do que o ciclo de implantação normal. É da responsabilidade do desenvolvedor regular (o período de tempo depende do seu ambiente de desenvolvimento) mesclar as alterações do tronco para sua ramificação.
Crie uma ramificação de recurso se dois ou mais desenvolvedores trabalharem em um novo recurso que levará um tempo considerável para ser concluído. É responsabilidade do líder da equipe mesclar as alterações do tronco para esse ramo de recurso regularmente.
É sempre benéfico mesclar alterações do tronco com freqüência. Porque, depois de alguns dias, o conflito entre a versão do tronco e a versão do ramo pode ficar fora de controle e a fusão será praticamente impossível.
Quando a ramificação do desenvolvedor ou a ramificação de recurso estiver pronta para ser liberada, mescle as alterações de volta da ramificação para o tronco.
Finalmente, lembre-se de que não existe uma estratégia ideal de ramificação e fusão. Isso depende muito do seu ambiente de desenvolvimento exclusivo. Se você tiver alguma outra estratégia, eu gostaria de ouvir sobre isso.
Ramificação e mesclagem.
Especialista Técnico em Ferramentas de Desenvolvimento.
Microsoft Pty Ltd, Austrália / Nova Zelândia.
Microsoft Visual Studio 2005 Team Foundation Server.
Resumo: Uma introdução ao conceito de gerenciamento de configuração de software, incluindo informações sobre por que o gerenciamento de configuração é importante e as várias estratégias de ramificação e mesclagem. (6 páginas impressas)
Introdução.
Por algum motivo, o gerenciamento de configuração de software (SCM) ainda é um conceito mal entendido. Talvez seja porque o gerenciamento de configuração de software é praticamente invisível, percebido como restritivo ou visto como chato.
Não tenho certeza do motivo, mas o fato é que as ineficiências de desenvolvimento (e outras atividades posteriores, como operações) são geralmente causadas por implementações inadequadas de práticas de gerenciamento de configuração de software.
Gerenciamento de configuração de software é "O processo de identificar e definir os itens de configuração em um sistema de software, controlando o lançamento, versão e alteração desses itens durante o ciclo de vida do sistema de software, registrando e relatando o status dos itens de configuração e alterando solicitações e verificar a integridade e correção dos itens de configuração. " (Fonte: Infosys)
Como você pode ver, o gerenciamento de configuração de software é um tópico amplo, então decidi me concentrar em um aspecto específico deste documento - ramificação e mesclagem. O tópico é fundamental, ainda que mal compreendido por muitos.
Este documento explica o conceito, não a mecânica, de ramificação e mesclagem, mas não é específico de nenhuma ferramenta específica de gerenciamento de configuração de software.
Por que o SCM é importante.
As práticas de SCM fornecem a base que ajuda todos os membros de uma equipe de desenvolvimento a colaborar de forma eficaz. Ninguém duvida da importância de ter uma base sólida para apoiar um edifício alto, mas poucos parecem entender que o gerenciamento de configuração de software desempenha um papel semelhante no desenvolvimento de software.
Eu freqüentemente discuto ineficiências de teste ou implantação com clientes, apenas para descobrir que a causa raiz eram práticas ruins de gerenciamento de configuração de software, como testar a configuração errada, usar o ambiente de teste errado, implantar uma compilação defeituosa e assim por diante. Esses problemas parecem ser a norma em vez da exceção.
Os benefícios de boas práticas de SCM incluem o seguinte:
Protegendo a propriedade intelectual - os ativos de software. Ajudando a melhorar a comunicação entre os membros da equipe. Fornecer uma maneira de estabelecer responsabilidades e responsabilidades claras. Fornecendo rastreabilidade e reprodutibilidade. Facilitando a reutilização. Fornecendo consistência, confiabilidade e integridade.
Tradeoffs entre risco e produtividade.
Uma estratégia de ramificação e fusão envolve uma troca entre risco e produtividade. Você troca a segurança de trabalhar em isolamento para aumentar a produtividade de trabalhar com outras pessoas. Os aumentos de produtividade vêm com um custo - o esforço adicional necessário para mesclar ativos de software em algum momento no futuro.
O uso de agências fornece melhor isolamento e controle de ativos de software individuais e aumenta a produtividade, porque equipes ou indivíduos podem trabalhar em paralelo. No entanto, o uso de ramificações também requer um aumento nas atividades de mesclagem e, portanto, risco, porque você deve mais tarde remontar as ramificações em um todo.
Infelizmente, não existe almoço grátis!
Ao decidir sobre uma estratégia de SCM, você deve primeiro decidir o que uma ramificação representa. Frequentemente, alinhamos as ramificações com arquiteturas de sistema, unidades organizacionais ou estruturas de divisão de trabalho (WBS), conforme resumido na Figura 1.
Figura 1. Baseando uma estratégia de ramificação em arquitetura, organização ou trabalho.
A tabela a seguir mostra exemplos de estratégias de ramificação.
Tabela 1. Exemplos de Estratégias de Ramificação.
Decidir sobre a melhor estratégia de ramificação é um ato de equilíbrio. Você deve compensar os ganhos de produtividade contra o aumento do risco. Uma maneira de validar uma estratégia escolhida é considerar um cenário de mudança. Por exemplo, se você decidir alinhar as ramificações com a arquitetura do sistema (por exemplo, uma ramificação representa um componente do sistema) e esperar alterações de arquitetura significativas, talvez seja necessário reestruturar suas ramificações e processos e políticas associados a cada alteração. A escolha de uma estratégia de ramificação inadequada pode causar sobrecargas de processo e longos ciclos de integração e lançamento que são frustrantes para toda a equipe.
Estratégias comuns de ramificação.
Esta seção descreve estratégias comuns de ramificação. A intenção não é fornecer orientação específica, mas estimular idéias e demonstrar a importância de planejar cuidadosamente sua estratégia de ramificação.
Filial por lançamento.
Uma das estratégias de ramificação mais comuns é alinhar as ramificações com as liberações de produtos, conforme mostrado na Figura 2. Uma ramificação contém todos os ativos de desenvolvimento de software para uma única liberação. Ocasionalmente, você deve mesclar atualizações de um release para outro, mas elas geralmente nunca são mescladas. Você descontinua uma ramificação quando interromper o lançamento.
Figura 2. Ramificando por Liberação.
Agências de Promoção de Código.
Outra abordagem muito comum é alinhar as ramificações com os níveis de promoção de ativos de software, conforme mostrado na Figura 3. Uma versão de desenvolvimento específica é ramificada em uma ramificação de teste, na qual toda a integração e o teste do sistema são realizados. Quando você conclui o teste, os ativos de desenvolvimento de software são ramificados no ramo Produção e, por fim, implementados.
Figura 3. Ramificação por fase do projeto.
Durante o esforço de teste, você atualiza a base do código de desenvolvimento enquanto encontra e corrige bugs. Você mescla o código alterado na ramificação de desenvolvimento quando você promove o código testado em produção.
Filial por tarefa.
Para evitar tarefas sobrepostas (ou atividades) e uma perda de produtividade, você pode isolar uma tarefa em uma ramificação separada, como mostra a Figura 4. Essas ramificações devem ser ramificações de curto prazo que você mescla assim que concluir a tarefa; caso contrário, o esforço de mesclagem necessário poderá exceder os benefícios de produtividade da criação de uma ramificação separada para uma tarefa.
Figura 4. Ramificação por tarefa.
Filial por componente.
Você pode alinhar cada ramificação com a arquitetura do sistema, conforme mostrado na Figura 5. Nessa estratégia, você ramifica componentes individuais (ou subsistemas). Em seguida, cada equipe que desenvolve um componente decide quando mesclar seu código de volta à linha de desenvolvimento que serve como ramificação de integração.
Figura 5. Ramificação por componente.
Essa estratégia pode funcionar bem se a arquitetura do sistema estiver em vigor e os componentes individuais tiverem interfaces bem definidas. O fato de você desenvolver componentes em ramificações permite um controle mais refinado sobre os ativos de desenvolvimento de software.
Filial por Tecnologia.
A Figura 6 mostra outra estratégia de ramificação alinhada com a arquitetura do sistema. Aqui você alinha as filiais às plataformas de tecnologia. O código comum é gerenciado em uma ramificação separada.
Figura 6. Ramificação por tecnologia.
Devido à natureza exclusiva dos ativos de desenvolvimento de software gerenciados nos ramos, você provavelmente nunca mesclará os ramos.
Há muitas outras opções para a estruturação de filiais, mas espero que seja óbvio que o planejamento da implementação de uma estratégia de ramificação valha a pena e possa retornar benefícios significativos.
Ramificação e fusão de antipadrões.
Você sabe que está no caminho errado se tiver um ou mais dos seguintes sintomas em seu ambiente de desenvolvimento:
Merge Paranoia - evitando a fusão a todo custo, geralmente por causa do medo das conseqüências. Merge Mania - gastando muito tempo mesclando ativos de software em vez de desenvolvê-los. Big Bang Merge - adiando a mesclagem de ramificação até o final do esforço de desenvolvimento e tentando mesclar todas as ramificações simultaneamente. Never-Ending Merge - atividade de mesclagem contínua porque sempre há mais a mesclar. Mala Direta Errada - exibindo uma versão de ativo de software com uma versão anterior. Branch Mania - criando muitos ramos sem motivo aparente. Filiais em cascata - ramificadas, mas nunca se fundindo de volta à linha principal. Ramos misteriosos - ramificados sem motivo aparente. Ramos temporários - ramificando-se por motivos de mudança, de modo que o ramo se torna um espaço de trabalho temporário permanente. Filiais voláteis - com ativos de software instáveis compartilhados por outras filiais ou fundidos em outro ramo. Nota As filiais são voláteis na maior parte do tempo enquanto existem como filiais independentes. Esse é o ponto de tê-los. A diferença é que você não deve compartilhar ou mesclar ramificações enquanto elas estiverem em um estado instável. Congelamento de desenvolvimento - interromper todas as atividades de desenvolvimento enquanto ramifica, mescla e constrói novas linhas de base. Muro de Berlim - usando filiais para dividir os membros da equipe de desenvolvimento, em vez de dividir o trabalho que estão realizando.
Referências.
Para tudo o que você sempre quis saber sobre gerenciamento de configuração de software, consulte CM Crossroads. Para uma discussão mais detalhada sobre o tópico, leia o seguinte livro de Brian A. White: Estratégias de Gerenciamento de Configuração de Software e Rational ClearCase: Uma Introdução Prática. Sim, é específico do ClearCase, mas ele também foi fundamental na formação da solução Microsoft SCM.
Chris Birmele ingressou na Microsoft no final de 2005, após seis anos no IBM Rational, onde ocupou diversos cargos de vendas técnicas. Seus principais interesses são gerenciamento de requisitos, arquitetura de software e metodologias de desenvolvimento. Chris é formado em Tecnologias de Informação Empresarial pela Charles Stuart University.
A empresa para a qual trabalho está começando a ter problemas com seu atual modelo de ramificação e fiquei me perguntando para quais diferentes tipos de estratégias de ramificação a comunidade foi exposta?
Há algum bom para situações diferentes? O que sua empresa usa? Quais são as vantagens e desvantagens deles?
fechado como não construtivo por casperOne Fev 24 '12 às 19:53.
No momento, esta questão não é adequada para o nosso formato de perguntas e respostas. Esperamos que as respostas sejam apoiadas por fatos, referências ou especialização, mas essa questão provavelmente solicitará debates, discussões, pesquisas ou discussões ampliadas. Se achar que esta questão pode ser melhorada e possivelmente reaberta, visite o centro de ajuda para obter orientação. Se essa questão puder ser reformulada para se ajustar às regras da Central de Ajuda, edite a pergunta.
17 respostas.
Aqui está o método que usei no passado com bom sucesso:
/ tronco - margem de sangramento. Próximo lançamento principal do código. Pode ou não pode trabalhar a qualquer momento.
/branches/1.0, 1.1, etc. Ramos de manutenção estáveis do código. Usado para corrigir erros, estabilizar novos lançamentos. Se um ramo de manutenção, ele deve compilar (se for o caso) e estar pronto para QA / envio a qualquer momento. Se um ramo de estabilização, ele deve compilar e ter recursos completos. Nenhum novo recurso deve ser adicionado, nenhuma refatoração e nenhuma limpeza de código. Você pode adicionar um pré-prefixo para indicar ramos de estabilização vs ramos de manutenção.
/ branches / cool_feature. Usado para trabalhos altamente experimentais ou destrutivos que podem ou não entrar no tronco (ou um ramo de manutenção). Não há garantias de compilar, trabalhar ou se comportar de maneira adequada. Deve durar o mínimo de tempo possível antes de se fundir na ramificação da linha principal.
/tags/1.0.1, 1.0.2, 1.1.3a, etc. Usado para marcar um pacote & amp; lançamento enviado. Nunca muda sempre. Faça quantas tags quiser, mas elas são imutáveis.
Eu recomendo fortemente ler a opinião de Eric Sink sobre o assunto:
Eu, como Eric, prefiro o estilo de "pasta" que ele fala.
Para o filão mãe sobre padrões de ramificação, veja Linhas Transplantadas de Brad Appleton: Padrões de Ramificação para Desenvolvimento de Software Paralelo. É pesado, mas não vi nada para superá-lo em termos de amplitude e profundidade de conhecimento sobre ramificação.
Nosso repositório se parece com:
/ trunk é o seu desenvolvimento padrão e de ponta. Usamos o CI para que isso sempre seja feito e aprovado nos testes.
/ branches é onde nós colocamos grandes mudanças 'sancionadas', ou seja, algo que sabemos que irá transformá-lo em tronco, mas pode precisar de algum trabalho e quebrar CI. Também onde trabalhamos em versões de manutenção, que possuem seus próprios projetos de CI.
/ sandbox cada desenvolvedor tem sua própria sandbox, além de uma sandbox compartilhada. Isso é para coisas como "Vamos adicionar um provedor LINQ ao nosso produto" tipo de tarefas que você faz quando você não está fazendo seu trabalho real. Pode eventualmente entrar no tronco, pode não ser, mas está lá e sob controle de versão. Não há CI aqui.
/ vendedor padrão do fornecedor para projetos nos quais compilamos, mas não é o código que mantemos.
/ ccnet são nossas tags de CI, somente o servidor de IC pode gravar aqui. A retrospectiva teria nos dito para renomear isso para algo mais genérico, como CI, BUILDS, etc.
Uma ramificação para o desenvolvimento ativo (/ main ou master, dependendo do jargão) Um branch para cada release de manutenção -> ele receberá apenas pequenas correções, enquanto todo o desenvolvimento principal vai para / main Um branch para cada nova tarefa: criar um novo ramo para trabalhar em cada nova entrada no seu Bugzilla / Jira / Rally. Comprometa-se com frequência, documente a alteração usando check-ins de seixos em polegadas e mescle-a de volta à sua ramificação "pai" somente quando estiver concluída e bem testada.
A primeira coisa: KISS (Mantenha isso simples, estúpido!)
* 1) Manter a manutenção da versão - por exemplo, Service Packs, Hotfixes, correções de erros que podem ser mescladas ao tronco, se necessário e / ou necessário) * 2) major. minor. build. revision.
A pasta Tags não precisa ser registrada Apenas poucas codificações em ramificações de lançamento (simplifica a mesclagem) - sem limpeza de código, etc. Nunca codificar na pasta de tags Nunca coloque informações concretas de versão em arquivos de origem. Use Place-holders ou 0.0.0.0 que o mecanismo de compilação irá substituir pelo número de versão que você está construindo Nunca coloque bibliotecas de terceiros em seu controle de origem (também ninguém adicionará bibliotecas STL, MFC etc. ao SVN ;-)) Apenas código de commit que compila Prefer usando variáveis de ambiente ao invés de caminhos hard-coded (caminhos absolutos e relativos)
Nós nos ramificamos quando um lançamento está pronto para o controle de qualidade final. Se algum problema for descoberto durante o processo de controle de qualidade, os bugs serão corrigidos na filial, validados e depois mesclados no tronco. Depois que o branch passa no controle de qualidade, nós o marcamos como um lançamento. Quaisquer hotfixes para essa versão também são feitos na ramificação, validados, mesclados ao tronco e, em seguida, marcados como uma release separada.
A estrutura da pasta seria semelhante a esta (1 linha de controle de qualidade, 2 lançamentos de hotfix e o tronco):
Usamos o estilo selvagem, selvagem e ocidental dos ramos-git. Temos algumas ramificações que têm nomes conhecidos definidos por convenção, mas, no nosso caso, as tags são realmente mais importantes para atender aos requisitos da política de processos corporativos.
Eu vi abaixo que você usa o Subversion, então estou pensando que você deveria verificar a seção sobre ramificação no Subversion Book. Especificamente, observe a seção "layout do repositório" em Manutenção de Filial e Padrões de Filial Comuns.
A alternativa que não estou vendo aqui é uma filosofia "Branch on Change".
Em vez de ter o seu porta-malas "Wild West", e se o porta-malas for o "Current Release"? Isso funciona bem quando há apenas uma versão do aplicativo lançada por vez - como um site. Quando um novo recurso ou correção de bug é necessário, uma ramificação é feita para manter essa alteração. Geralmente, isso permite que as correções sejam migradas para serem liberadas individualmente e impede que os codificadores de caubóis adicionem acidentalmente um recurso a ser lançado que você não pretendia. (Muitas vezes é um backdoor - "Apenas para desenvolvimento / teste")
Os ponteiros de Ben Collins são bastante úteis para determinar qual estilo funcionaria bem para sua situação.
O Controle de Versão de Henrik Kniberg para Múltiplas Equipes Ágeis também tem alguns pontos positivos a serem levados em consideração.
Atualmente, temos uma filial para manutenção contínua, um ramo para "novas iniciativas", que significa apenas "coisas que sairão em algum momento no futuro; não temos certeza de quando". Ocasionalmente, também tivemos dois ramos de manutenção: um para fornecer correções para o que está atualmente em produção e outro que ainda está em QA.
A principal vantagem que vimos é a capacidade de reagir às solicitações e emergências do usuário mais rapidamente. Podemos fazer a correção na ramificação que está em produção e liberá-la sem liberar nada extra que já tenha sido verificado.
A principal desvantagem é que acabamos fazendo muitas mesclagens entre filiais, o que aumenta a chance de que alguma coisa seja perdida ou mesclada incorretamente. Até agora, isso não tem sido um problema, mas é definitivamente algo para se ter em mente.
Antes de instituirmos esta política, geralmente fazíamos todo o desenvolvimento no tronco e apenas ramificávamos quando lançávamos o código. Em seguida, fizemos correções contra esse ramo, conforme necessário. Era mais simples, mas não tão flexível.
Jeff Atwood escreveu sobre isso em um bom post no blog; Esse post tem alguns links importantes nele.
Gnat escreveu esta excelente análise dos vários conselhos que você pode encontrar em estratégias de ramificação.
Não há uma estratégia de ramificação, é para isso que funciona:
O tamanho da sua equipe Seu produto e os períodos do ciclo de vida A tecnologia que você está usando (aplicativos da Web, incorporados e do Windows) Seu controle de origem, por exemplo, Git, TFS, Hg.
O post de Jeff Atwood divide várias possibilidades. Outro a acrescentar é o conceito de promoção (do link de Ryan Duffield). Nesta configuração você tem uma ramificação dev, testa bracnh e libera a ramificação. Você promove seu código até que ele atinja o ramo de lançamento e seja implantado.
Комментариев нет:
Отправить комментарий