Estratégia de ramificação ágil Subversion
Esta documentação foi escrita para descrever a série 1.7.x do Apacheв "ў Subversion®. Se você estiver executando uma versão diferente do Subversion, você é fortemente encorajado a visitar svnbook / e, em vez disso, consulte a versão desta documentação apropriada para sua versão do Subversion.
Padrões comuns de ramificação.
Há muitos usos diferentes para ramificação e svn mesclar, e esta seção descreve o mais comum.
O controle de versão é usado com mais freqüência para o desenvolvimento de software, então é uma rápida olhada em dois dos padrões de ramificação / fusão mais comuns usados por equipes de programadores. Se você não estiver usando o Subversion para desenvolvimento de software, sinta-se à vontade para ignorar 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 são muitas vezes considerados melhores práticas 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 ajudar a vê-los descritos nos termos do Subversion.
Ramos de publicação.
A maioria dos programas tem um ciclo de vida típico: código, teste, lançamento, repetição. Existem dois problemas com esse processo. Primeiro, os desenvolvedores precisam continuar escrevendo novos recursos, enquanto as equipes de garantia de qualidade levam tempo para testar versões supostamente estáveis do software. O novo trabalho não pode parar enquanto o software é testado. Em segundo lugar, o time quase sempre precisa suportar versões de software mais antigas e lançadas; Se um bug for descoberto no código mais recente, provavelmente também existe em versões lançadas, e os clientes vão querer obter essa correção de bugs sem ter que esperar por uma nova versão importante.
Aqui é onde o controle de versão pode ajudar. O procedimento típico parece assim:
Os desenvolvedores comprometem todo o trabalho novo no tronco. As mudanças do dia-a-dia estão comprometidas com / tronco: novos recursos, correções de bugs, e assim por diante.
O tronco é copiado para um ramo de "liberação". Quando a equipe pensa que o software está pronto para a liberação (por exemplo, uma versão 1.0), o tronco pode ser copiado para /branches/1.0.
As equipes continuam a trabalhar em paralelo. Uma equipe começa testes rigorosos do ramo de lançamento, enquanto outra equipe continua um novo trabalho (digamos, para a versão 2.0) no / tronco. Se os erros forem descobertos em qualquer local, as correções serão carregadas para frente e para trás, conforme necessário. Em algum momento, no entanto, mesmo esse processo pára. O ramo está "congelado" para o teste final antes de um lançamento.
O ramo é marcado e liberado. Quando o teste estiver completo, /branches/1.0 é copiado para /tags/1.0.0 como um instantâneo de referência. A etiqueta é empacotada e lançada para clientes.
O ramo é mantido ao longo do tempo. Enquanto o trabalho continuar no / tronco para a versão 2.0, as correções de bugs continuam sendo portadas de / tronco para /branches/1.0. Quando suficientes correções de bugs se acumulam, o gerenciamento pode decidir fazer uma versão 1.0.1: /branches/1.0 é copiado para /tags/1.0.1 e a etiqueta é empacotada e liberada.
Todo esse processo se repete à medida que o software amadurece: quando o trabalho 2.0 estiver completo, um novo ramo de liberação 2.0 é criado, testado, etiquetado e eventualmente lançado. Depois de alguns anos, o repositório termina com vários ramos de lançamento no modo "manutenção", e uma série de tags que representam as versões enviadas.
Ramos de recursos.
Um ramo de recursos é o tipo de ramo que tem sido o exemplo dominante neste capítulo (aquele em que você trabalhou enquanto a Sally continua trabalhando no tronco). É um ramo temporário criado para trabalhar em uma mudança complexa sem interferir com a estabilidade do tronco. Ao contrário dos ramos de lançamento (que podem precisar ser suportados para sempre), os ramos de recursos nascem, usados por um tempo, fundidos de volta ao tronco e, em seguida, excluídos. Eles têm um período finito de utilidade.
Novamente, as políticas de projetos variam amplamente sobre exatamente quando é apropriado criar um ramo de recursos. Alguns projetos nunca usam ramos de recursos: os compromissos para / tronco são gratuitos para todos. A vantagem desse sistema é que é simples: "ninguém precisa aprender sobre ramificação ou fusão. A desvantagem é que o código do tronco é muitas vezes instável ou inutilizável. Outros projetos usam ramos para um extremo: nenhuma mudança já foi comprometida com o tronco diretamente. Mesmo as mudanças mais triviais são criadas em um ramo de curta duração, cuidadosamente revisadas e fundidas no tronco. Em seguida, o ramo é excluído. Este sistema garante um tronco excepcionalmente estável e utilizável em todos os momentos, mas ao custo de uma enorme carga de processo.
A maioria dos projetos aborda a abordagem do meio-da-estrada. Eles geralmente insistem em que / compilar tronco e passar testes de regressão em todos os momentos. Um ramo de recursos é necessário apenas quando uma mudança requer um grande número de compromissos desestabilizadores. Uma boa regra geral é fazer esta pergunta: se o desenvolvedor trabalhou por dias isoladamente e depois comprometeu a grande mudança de uma só vez (de modo que o tronco nunca foi desestabilizado), seria uma grande mudança para revisão? Se a resposta a essa pergunta é "sim", a mudança deve ser desenvolvida em um ramo de recursos. À medida que o desenvolvedor compromete mudanças incrementais no ramo, eles podem ser facilmente revisados por colegas.
Finalmente, há a questão de como manter melhor um ramo de recursos em "sincronização" com o tronco à medida que o trabalho avança. Como mencionamos anteriormente, há um grande risco de trabalhar em uma filial por semanas ou meses; as mudanças do tronco podem continuar a derramar, até o ponto em que as duas linhas de desenvolvimento diferem tanto que pode se tornar um pesadelo tentando unir o ramo de volta ao tronco.
Esta situação é melhor evitada através da fusão regular das mudanças no tronco para o ramo. Elimine uma política: uma vez por semana, combine o valor da semana passada de alterações no tronco para o ramo.
Quando você finalmente estiver pronto para mesclar o ramo de características sincronizadas do tronco, comece fazendo uma fusão final das últimas mudanças no tronco para o ramo. Quando isso for feito, as versões mais recentes do ramo e do tronco são absolutamente idênticas, exceto para as mudanças de sua filial. Em seguida, você combina novamente com a opção --reintegrar:
Outra maneira de pensar sobre esse padrão é que sua sincronização semanal do tronco para o ramo é análoga à execução da atualização do svn em uma cópia de trabalho, enquanto a etapa de mesclagem final é análoga à execução do commit do svn a partir de uma cópia de trabalho. Afinal, o que mais é uma cópia de trabalho, mas um ramo privado muito superficial? É um ramo que é capaz de armazenar apenas uma mudança por vez.
Você está lendo o Controle de Versão com Subversion (para Subversion 1.7), de Ben Collins-Sussman, Brian W. Fitzpatrick e C. Michael Pilato.
Estratégia de ramificação ágil Subversion
Obter através da App Store Leia esta publicação em nosso aplicativo!
Melhor estratégia de ramificação ao fazer integração contínua?
Qual é a melhor estratégia de ramificação a ser usada quando você quer fazer integração contínua?
Release Branching: desenvolva no tronco, mantenha um ramo para cada lançamento. Ramificação de recursos: desenvolva cada recurso em uma ramificação separada, apenas funde uma vez estável.
Faz sentido usar essas duas estratégias juntas? Como em, você se ramifica para cada versão, mas você também se ramifica para grandes recursos? Uma dessas estratégias engrena melhor com a integração contínua? Usar integração contínua ainda faz sentido ao usar um tronco instável?
11 Respostas.
A resposta depende do tamanho da sua equipe e da qualidade do seu controle de origem e da capacidade de mesclar conjuntos de mudanças complexas corretamente. Por exemplo, no controle de fonte de ramo completo, como a fusão CVS ou SVN pode ser difícil e você pode estar melhor com o primeiro modelo, enquanto que se usar um sistema mais complexo como o IBM ClearCase e com um tamanho maior de equipe, você poderia ser melhor com o segundo modelo ou uma combinação dos dois.
Eu, pessoalmente, separaria o modelo de ramal de recursos, onde cada característica principal é desenvolvida em um ramo separado, com subdivisões de tarefas para cada mudança feita pelo desenvolvedor individual. À medida que os recursos se estabilizam, eles são mesclados ao tronco, o que você mantém razoavelmente estável e passa todos os testes de regressão em todos os momentos. À medida que você está perto do final do seu ciclo de lançamento e todos os ramos de recursos se fundem, você se estabiliza e se ramifica de um ramo do sistema de liberação no qual você apenas faz correções de bug de estabilidade e backports necessários, enquanto o tronco é usado para o desenvolvimento da próxima versão e você novamente se ramificam para novos ramos de recursos. E assim por diante.
Desta forma, o tronco 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 fusões de recursos, os ramos de recursos são desenvolvimento de ritmo rápido com integração contínua e sub-ramos de tarefas individuais podem ser muitas vezes atualizado do ramo de recursos para manter todos os que trabalham no mesmo recurso em sincronia, enquanto simultaneamente não afetam outras equipes trabalhando em diferentes recursos.
Ao mesmo tempo, você tem através do histórico um conjunto de ramos de lançamento, onde você pode fornecer backports, suporte e correções de erros para seus clientes que, por qualquer motivo, permanecem em versões anteriores do seu produto ou mesmo apenas na versão mais recente 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 passar todos os testes de regressão e outros controles de qualidade de liberação.
Se por algum motivo dois recursos são co-dependentes e precisam de mudanças feitas um com o outro, você pode considerar desenvolver ambos no mesmo ramo de recursos ou exigir que os recursos agrupem regularmente partes estáveis do código no tronco e depois atualize as alterações de tronco para trocar código entre ramos do tronco. Ou se você precisar isolar esses dois recursos de outros, você pode criar um ramo comum do qual você ramifica esses ramos de recursos e que você pode usar para trocar código entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de fonte sem ramos esparsos e capacidade de fusão adequada como CVS ou SVN, o que tornaria todo esse modelo um pesadelo para configurar, gerenciar e integrar.
Eu acho o tópico realmente interessante, porque eu confio muito nas filiais no meu trabalho diário.
Lembro-me de Mark Shuttleworth, que propõe um modelo sobre manter o ramo principal puro enquanto vai além do CI convencional. Eu postei sobre isso aqui. Como estou familiarizado com o Cruise Control, também bloguei sobre filiais de tarefas e CI aqui. É um tutorial passo a passo explicando como fazê-lo com SCM de plástico. Finalmente, encontrei alguns dos tópicos sobre CI (e potencialmente falando sobre ramificação) no livro de Duvall sobre a CI também muito interessante.
Espero que você ache os links interessantes.
Eu pessoalmente acho muito mais limpo ter um tronco estável e apresentar ramificações. Dessa forma, os testadores e similares conseguem permanecer em uma única "versão" e atualizar do tronco para testar qualquer recurso que seja codificado.
Além disso, se vários desenvolvedores estiverem trabalhando em recursos diferentes, eles podem ter seus próprios ramos separados, depois fundir no tronco quando terminarem e enviar um recurso para serem testados sem que o testador tenha que alternar para vários ramos para testar diferentes recursos.
Como um bônus adicional, há algum nível de testes de integração que vem automaticamente.
Penso que qualquer uma das estratégias pode ser usada com o desenvolvimento contínuo, desde que você se lembre de um dos princípios fundamentais que cada desenvolvedor comete no tronco / mainline todos os dias.
Eu tenho feito uma leitura deste livro sobre a CI e os autores sugerem que a ramificação por lançamento é a estratégia de ramificação preferida. Eu tenho que concordar. O raciocínio por recurso não faz sentido para mim ao usar o CI.
Vou tentar e explicar por que estou pensando dessa maneira. Digamos que três desenvolvedores tomem um ramo para trabalhar em um recurso. Cada recurso levará vários dias ou semanas para terminar. Para garantir que a equipe esteja se integrando continuamente, eles devem se comprometer com a filial principal pelo menos uma vez por dia. Assim que eles começam a fazer isso, eles perdem o benefício de criar um ramo de recursos. Suas mudanças não são mais separadas de todas as mudanças do outro desenvolvedor. Sendo assim, por que se preocupar em criar filiais de recursos em primeiro lugar?
O uso de ramificação por versão requer muito menos fusão entre os ramos (sempre é uma coisa boa), garante que todas as alterações sejam integradas o mais rápido possível e (se feito corretamente) garante que sua base de código esteja sempre pronta para ser liberada. O lado negativo para se ramificar pelo lançamento é que você deve ter um cuidado consideravelmente mais cuidadoso com as mudanças. Por exemplo. A refatoração ampla deve ser feita de forma incremental e, se você já integrou um novo recurso que não deseja na próxima versão, ele deve estar oculto usando algum tipo de mecanismo de alternância de recursos.
Há mais de uma opinião sobre este assunto. Aqui está uma postagem de blog que é uma ramificação de recursos pro com CI.
Os ramos de lançamento são muito úteis, e até mesmo absolutamente necessários, se você precisar manter várias versões do seu aplicativo.
Os ramos de recursos também são muito convenientes, especialmente se um desenvolvedor precisa trabalhar em uma grande mudança, enquanto outros ainda lançam novas versões.
Então, para mim, usar ambos os mecanismos é uma estratégia muito boa.
Link interessante do Livro do SVN.
Recentemente, gostei desse modelo ao usar o git. Embora sua pergunta seja marcada como "svn", você ainda pode fazer algum uso disso.
A integração contínua pode, em certa medida, acontecer no ramo "desenvolver" (ou seja o que for que você chamar) neste modelo, embora possuir ramos de recursos longos para lançamentos futuros não o tornem tão rígido quanto a considerar cada mudança acontecendo com o código em algum lugar. A questão permanece, se você realmente quer isso. Martin Fowler faz.
A integração contínua não deve ser qualquer tipo de fator na determinação de sua estratégia de ramificação. Sua abordagem de ramificação deve ser selecionada com base em sua equipe, o sistema em desenvolvimento e as ferramentas disponíveis para você.
Tendo dito isto .
não há nenhuma razão para que a CI não possa ser usada em ambas as abordagens que você descreve, essas abordagens funcionam bastante bem em combinação, nenhum dos dois trabalha "melhor" do que o outro CI faz todo o sentido com um tronco instável.
Tudo isso foi respondido na quarta pergunta na página da qual você tirou os diagramas: blogs. collab / subversion / 2007/11 / branching-strat /
Enquanto você entender os princípios, você sempre pode reinventar as melhores práticas. Se você não entender os princípios, as melhores práticas irão levá-lo até antes de desmoronar devido a algum requisito externo conflitante.
Leia o link. Uma vez que você obteve o básico, leia o seguinte artigo pelo venerável Henrik Kniberg. Ele irá ajudá-lo a relacionar o Mainline Model com integração contínua.
Quando iniciamos nossa equipe, herdamos uma estratégia baseada em lançamentos do fornecedor que originalmente desenvolveu o sistema ao qual estávamos prestes a se encarregar. Isso funcionou até o momento em que nossos clientes solicitaram que vários recursos desenvolvidos não fossem incluídos em um lançamento (f. y.i.
250k linhas de código,
2500 arquivos, Scrum com XP SDLC).
Em seguida, começamos a olhar para os ramos baseados em recursos. Isso também funcionou por um tempo - como 2 meses até o momento em que percebemos que nosso processo de teste de regressão levaria mais de 2 semanas, o que combinado com a incerteza do que seria lançado criou uma enorme inconveniência.
O último "prego no caixão" de estratégias SC puras veio quando decidimos que deveríamos ter 1. tronco estável e 2. A produção deveria conter BINÁRIOS testados ST, UAT e Regressão (não apenas fonte - pense CC).
Isso nos leva a conceber uma estratégia que seja um híbrido entre as estratégias SC e baseadas em lançamento.
Então nós temos um baú. Todos os sprints nos ramificamos no ramo de sprint (para pessoas não ágeis - um sprint é apenas um esforço de desenvolvimento com caixa de tempo com saída variável com base na complexidade). Do ramo de sprint criamos os ramos de recursos e o desenvolvimento paralelo é iniciado neles. Uma vez que os recursos estão completos e testados pelo sistema, e recebemos a intenção de implementá-los, eles são incorporados ao ramo de sprint - alguns podem flutuar em vários sprints, geralmente os mais complexos. Uma vez que o sprint está perto do seu fim e as características estão completas. nós "renomeamos" o ramo de sprint para "regressão" (isso permite que o CruiseControl o apanhe sem qualquer reconfiguração) e o teste de regressão / integração começa no EAR construído no cc. Quando tudo estiver pronto, ele vai em produção.
Em suma, os ramos baseados em recursos são usados para desenvolver, teste do sistema e funcionalidade UAT. O ramo de sprint (realmente o ramo de lançamento) é usado para mesclar seletivamente os recursos sob demanda e teste de integração.
Agora, aqui é uma questão para a comunidade - obviamente estamos tendo problemas para realizar uma integração contínua devido ao fato de que o desenvolvimento acontece em muitos ramos e a sobrecarga de reconfiguração do CruiseControl. Alguém pode sugerir e orientar?
Do jeito que eu vejo você quer ter um conjunto limitado de ramos onde você pode se concentrar. Uma vez que você deseja testes, métricas de qualidade de código e muitas coisas interessantes para executar com as compilações, ter muitos relatórios provavelmente irá levá-lo a perder informações.
Quando e o que se ramifica, geralmente depende do tamanho da equipe e do tamanho das características que estão sendo desenvolvidas. Eu não acho que haja uma regra de ouro. Certifique-se de usar uma estratégia onde você possa receber comentários com antecedência / freqüência, e isso inclui ter qualidade envolvida desde o início dos recursos. O bit de qualidade significa que, à medida que você está automatizando à medida que a equipe se desenvolve, se você se ramifica para um grande conjunto de recursos criado por uma equipe, você também deve ter qualidade envolvida na equipe.
ps Onde você obteve as referências da abordagem? - não sente que esses gráficos representam todas as opções.
Atualização 1: expandindo porque eu disse que não é uma regra de ouro. Basicamente, para equipes relativamente pequenas, achei melhor usar uma abordagem que seja uma mistura. Os ramos de recursos são criados se for algo longo e parte da equipe continuará adicionando recursos menores.
Eu acho que as ferramentas que você usa são um grande fator aqui.
Se você estiver usando a subversão, aderindo à opção 1 e soltando as filiais. Se você estiver usando o GIT, a opção 2 funcionará bem para você.
Estratégia de ramificação ágil Subversion
Obter através da App Store Leia esta publicação em nosso aplicativo!
Estratégia de ramo único no desenvolvimento ágil.
Atualmente, em nosso projeto, temos trunk, lançamos ramos também hotfix brances, estamos planejando manter uma estratégia de ramo único em vez de manter múltiplas. Alguém pode explicar o que são todas as abordagens que precisamos tomar e como isso pode afetar nosso desempenho e desenvolvimento de projeto.
Sou muito novo na equipe da CI e estou tentando entender esse processo. Existe alguma ferramenta para fundir a base do código sem intervenção manual.
Desbloquear! Um guia para o novo Agile contínuo.
Ramo e Forking.
Nos padrões de ramificação e mesclagem, cada colaborador mantém sua própria versão do software (um ramo ou um garfo). O colaborador copia a linha principal no início e, em seguida, mantém-a combinando mudanças da linha principal para ficar atualizado. Quando o contribuidor tiver uma mudança completa para contribuir, ele pode fundê-lo diretamente na linha principal, ou colocar uma solicitação de mestrado & ldquo; rdquo; ou & ldquo; pull request & rdquo; em um sistema de revisão.
Este é um padrão muito flexível que pode implementar vários dos padrões anteriores.
Informal. Você pode atualizar com freqüência e mesclar cada alteração diretamente, sem revisão.
Revisão do ramo. Naturalmente, você obterá o padrão de revisão do ramo se você fizer & ldquo; ramos de tarefas & rdquo; para cada mudança que você deseja trabalhar.
Cascading. Você obterá um padrão em cascata se você fizer filiais ou garfos para cada característica principal ou equipe. Isso é comumente chamado de & ldquo; feature branch & rdquo; padrão se você usá-lo para recursos. Se você usá-lo para equipes ou contribuidores individuais, você recebe um & ldquo; maintainer & rdquo; padrão em que cada colaborador envia mudanças para um mantenedor, que os integra em um sistema maior.
Entrega contínua distribuída: no capítulo de entrega contínua, veremos como os ramos podem ser usados para testar e liberar cada alteração.
Branching tem vários sabores, ilustrados abaixo.
Ramificação: os colaboradores podem fazer um ramo dentro de qualquer repositório. As filiais e as permissões das filiais são autorizadas por um proprietário do repositório. Este fluxo de trabalho torna o conteúdo e as mudanças visíveis para todos em uma equipe pequena.
Stream: em um sistema baseado em stream como o Perforce, os ramos do desenvolvedor se lembraram dos ramos a montante que devem ser a fonte de suas atualizações e os ramos a jusante aos quais suas mudanças devem fluir. Os sistemas de fluxo são úteis se você estiver montando um sistema ou um ambiente de desenvolvedor a partir de um conjunto complicado de componentes. Neste exemplo, vemos um ramo ou um espaço de trabalho que possui componentes de vários outros ramos.
Forquilha: o colaborador usa um DVCS (sistema de controle de versão distribuído) como o Git para fazer uma cópia da versão principal, chamada de garfo. Quando você fork, há duas cópias do código em repositórios separados, com permissões separadas. O proprietário do garfo decide quando atualizar o garfo e o proprietário da origem decide quando aceita contribuições. Você pode conceder permissão de leitura a muitos colaboradores e você não precisa administrar permissões de gravação.
Esta é uma ótima maneira de expandir o número de contribuidores para um projeto de código aberto. Também é popular para o desenvolvimento comercial devido à flexibilidade que dá ao contribuidor.
Atualize sucursais ou garfos freqüentemente.
Os críticos muitas vezes observam que os desenvolvedores tendem a trabalhar muito nos ramos e, em seguida, causam problemas de integração ao fundir grandes lotes de código. Encontrar problemas nesses grandes lotes de código é difícil. Os processos de ramificação serão quebrados quando as contribuições dos ramos ou garfos dos recursos forem grandes ou difíceis de mesclar ou contenham erros que devem ser resolvidos no momento da mesclagem.
Este temido problema de "ramificações longas" é a principal razão pela qual os defensores da integração contínua centralizada se opõem a bifurcação e ramificação distribuídas.
No entanto, você pode facilmente evitar esse problema se você atualizar seu ramo de recursos com freqüência com mudanças da origem. Se você usar ramos ou garfos, você deve:
Junte-se com frequência da origem ou versão de produção para a sua versão de desenvolvimento. Ao atualizar, integrar e testar freqüentemente na sua versão de desenvolvimento, você pode ficar perto da versão de produção. Teste o seu ramo ANTES de enviar alterações à origem. Você deve certificar-se de que as alterações no ramo ou no garfo de funções funcionem corretamente antes de enviá-los para serem mesclados. A versão muda com a maior freqüência possível. Quando você libera quantidades menores de código, você encontrará problemas mais rapidamente porque você tem menos lugares para procurar problemas.
Fusionando com o Git.
O Git usa ramificações e garfos por padrão. O Git tem excelente suporte para o processo de atualização de uma ramificação ou garfo da origem. O Git possui uma característica única chamada "rebase & quot; o que permite que um colaborador atualize a partir da origem e, em seguida, forneça um conjunto de alterações fácil de mesclar. A Rebase tira todo o histórico de intercâmbios de código que levam à entrega do conjunto de alterações e coloca todas as mudanças em um pacote.
Esta é uma abordagem radical porque ele reescreve o histórico & quot; tirando o registro de compromissos anteriores. Outros VCS são projetados para evitar qualquer perda de histórico. É possível que essa abordagem radical para rebase seja a razão pela qual o Git se tornou o DVCS mais popular. Como veremos, é importante no padrão de integração contínua distribuída.
Mesclando com o Subversion.
O Subversion não funciona bem quando você tenta juntar várias vezes da origem ou ramo do tronco. Por isso, a maioria dos usuários do Subversion aprende a evitar ramos de longa duração e a maioria das equipes do Subversion usa um modelo centralizado de entrega contínua que evita a ramificação.
Se você encontrar um ramo de longa duração no Subversion, você pode usar dois truques para mesclá-lo. A primeira é a nova implementação de mesclagem no Subversion 1.8, de Julian Foad. Ele atualizou o Subversion para que seja mais inteligente sobre como mudar as mudanças entre o tronco e os ramos. Ao escrever isso em maio de 2018, a equipe do Apache Subversion está testando essas mudanças para serem lançadas.
A segunda técnica é um rebase manual. Para fazer um rebase manual, primeiro faça um segundo ramo do tronco ou origem, em seguida, combine suas alterações no segundo ramo e teste-o. Isso tem o efeito de colocar todas as suas mudanças em uma revisão ou conjunto de revisões na cabeça do histórico do ramo - o mesmo efeito que um rebase Git. Depois disso, você encontrará as revisões fáceis de fundir no tronco ou na origem.
Por que usar ramos de recursos de longa duração?
Falamos anteriormente sobre o uso de ramos temporários ou ramos de tarefas para revisão de código. Você também pode usar ramos de recursos de longa duração ou garfos para fazer revisão de código, com testes automatizados, comentários e votação. Neste sistema, contribui para não fazer uma ramificação temporária para cada mudança. Em vez disso, eles mantêm uma versão de execução mais longa, e eles postam "quitar pedidos" ou "pedidos de mesclagem" para informar os revisores para rever e aceitar alterações.
Os ramos ou garfos de longa duração serão úteis se você:
Montar componentes em um sistema completo usando o padrão em cascata. Tem colaboradores independentes que gostam de experimentar ou não fazem parte da equipe com permissões internas. Não possuem revisores em tempo integral.
O recurso abre caminho para a grandeza.
Ou tarefa que se ramifica para lá. Ou liberar ramificações. Você escolhe.
Quase todos os sistemas de controle de versão hoje oferecem suporte a ramos e ndash, linhas de trabalho independentes que decorrem de uma base de código central. Dependendo do seu sistema de controle de versão, o ramo principal pode ser chamado de mestre, mainline, padrão ou tronco. Os desenvolvedores podem criar seus próprios ramos da linha principal do código e trabalhar de forma independente ao lado dele.
Por que se preocupar com a ramificação?
O Branching permite que equipes de desenvolvedores colaborem facilmente dentro de uma base de código central. Quando um desenvolvedor cria um ramo, o sistema de controle de versão cria uma cópia da base de código naquele momento. As mudanças na filial não afetam outros desenvolvedores no time. Isso é uma coisa boa, obviamente, porque os recursos em desenvolvimento podem criar instabilidade, o que seria altamente perturbador se todo o trabalho estava acontecendo na linha principal do código. Mas os ramos não precisam viver em confinamento solitário. Os desenvolvedores podem facilmente reduzir as mudanças de outros desenvolvedores para colaborar em recursos e garantir que seus ramos privados não se divertem muito do mestre.
Os ramos não são bons para o trabalho de recurso. Os ramos podem isolar o time de mudanças arquitetônicas importantes, como atualizações, bibliotecas comuns, etc.
Três estratégias de ramificação para equipes ágeis.
Os modelos de ramificação geralmente diferem entre equipes e são objeto de muito debate na comunidade de software. Um grande tema é a quantidade de trabalho que deve permanecer em um ramo antes de ser incorporado de novo ao mestre.
Liberação de ramificação.
A ramificação de lançamento refere-se à idéia de que uma versão está inteiramente contida em um ramo. Isso significa que, no final do ciclo de desenvolvimento, o gerente de lançamento criará um ramo do mestre (por exemplo, & ldquo; 1.1 ramo de desenvolvimento & rdquo;). Todas as alterações para a versão 1.1 devem ser aplicadas duas vezes: uma vez para o ramo 1.1 e, em seguida, para a linha do código mestre. Trabalhar com dois ramos é trabalho extra para a equipe e é fácil esquecer de fundir os dois ramos. Os ramos de liberação podem ser difíceis de manejar e difíceis de gerenciar, pois muitas pessoas estão trabalhando no mesmo ramo. Nós sentimos a dor de ter que combinar muitas mudanças diferentes em um único ramo. Se você deve fazer um ramo de lançamento, crie o ramo o mais próximo possível da versão real.
A ramificação de lançamento é uma parte importante do suporte de software versionado no mercado. Um único produto pode ter vários ramos de libertação (por exemplo, 1.1, 1.2, 2.0) para suportar o desenvolvimento de sustentação. Tenha em mente que as mudanças em versões anteriores (ou seja, 1.1) podem precisar ser mescladas para ramos de liberação posteriores (ou seja, 1.2, 2.0). Confira nosso webinar abaixo para saber mais sobre como gerenciar os ramos de lançamento com o Git.
Característica ramificação.
Os ramos de recursos geralmente são acoplados com bandeiras de recurso e ndash; & quot; toggles & quot; que permitem ou desativam um recurso dentro do produto. Isso facilita a implantação do código em mestre e controle quando o recurso é ativado, facilitando a implantação do código antes do recurso ser exposto aos usuários finais.
Outro benefício das bandeiras de recursos é que o código pode permanecer dentro da compilação, mas inativo enquanto ele está em desenvolvimento. Se algo estiver errado quando o recurso estiver ativado, um administrador do sistema pode reverter o sinalizador de recurso e voltar para um bom estado conhecido em vez de ter que implantar uma nova compilação.
Ramificação de tarefas.
Na Atlassian, nos concentramos em um fluxo de trabalho de ramificação por tarefa. Toda organização tem uma maneira natural de quebrar o trabalho em tarefas individuais dentro de um rastreador de problemas, como o Jira Software. As questões então se tornam o ponto central de contato da equipe para esse trabalho. A ramificação de tarefas, também conhecida como ramificação de problemas, conecta diretamente esses problemas com o código-fonte. Cada questão é implementada em seu próprio ramo com a chave de problema incluída no nome da filial. É fácil ver qual código implementa qual questão: basta procurar a chave de problema no nome do ramo. Com esse nível de transparência, é mais fácil aplicar mudanças específicas ao mestre ou qualquer ramo de lançamento legado em execução.
Desde centros ágiles em torno de histórias de usuários, os ramos de tarefas parecem bem com o desenvolvimento ágil. Cada história de usuário (ou correção de bugs) vive dentro de seu próprio ramo, facilitando a visão de quais problemas estão em andamento e estão prontos para serem lançados. Para um mergulho profundo em uma ramificação de tarefas (às vezes chamado de ramificação de problemas ou ramificação por questão), pegue algumas pipocas e confira a gravação do webinar abaixo do & ndash, um dos nossos mais populares de todos os tempos.
Agora conheça o gêmeo malvado da ramificação: a fusão.
Todos nós sofremos a dor de tentar integrar vários ramos em uma solução sensata. Tradicionalmente, sistemas de controle de versão centralizados como o Subversion fizeram uma operação muito dolorosa. Mas os sistemas de controle de versões mais recentes, como o Git e o Mercurial, tomam uma abordagem diferente para rastrear versões de arquivos que vivem em diferentes ramos.
Os ramos tendem a ser de curta duração, tornando-os mais fáceis de fundir e mais flexíveis em toda a base do código. Entre a capacidade de mesclar freqüentemente e automaticamente os ramos como parte da integração contínua (CI), e o fato de que os ramos de curta duração simplesmente contêm menos mudanças, "fundir o inferno" torna-se uma coisa do passado para equipes usando Git e Mercurial.
Isso é o que faz a ramificação de tarefas tão incrível!
Validar, validar, validar.
Um sistema de controle de versão só pode ir tão longe em afetar o resultado de uma fusão. Testes automatizados e integração contínua também são críticos. A maioria dos servidores CI pode automaticamente colocar novos ramos em teste, reduzindo drasticamente o número de "surpresas" na junção final a montante e ajudando a manter a linha principal do código estável.
A Agile teve um enorme impacto sobre mim tanto profissional como pessoalmente, como eu aprendi, as melhores experiências são ágeis, tanto no código como na vida. Muitas vezes, você me encontrará na interseção de tecnologia, fotografia e motociclismo. Encontre-me no Twitter! @danradigan.
Inscreva-se para mais artigos.
Obrigado por inscrever-se!
Como fazer scrum com o Jira Software.
A step-by-step guide on how to drive a scrum project, prioritize and organize your backlog into sprints, run the Scrum ceremonies and more, all within Jira Software.
Git branching for agile teams.
Moving to Git opens up a whole new level of agility for software teams. Here's how to design branching schemes for shipping both SaaS and installed products.
Obter através da App Store Leia esta publicação em nosso aplicativo!
Melhor estratégia de ramificação ao fazer integração contínua?
Qual é a melhor estratégia de ramificação a ser usada quando você quer fazer integração contínua?
Release Branching: desenvolva no tronco, mantenha um ramo para cada lançamento. Ramificação de recursos: desenvolva cada recurso em uma ramificação separada, apenas funde uma vez estável.
Faz sentido usar essas duas estratégias juntas? Como em, você se ramifica para cada versão, mas você também se ramifica para grandes recursos? Uma dessas estratégias engrena melhor com a integração contínua? Usar integração contínua ainda faz sentido ao usar um tronco instável?
11 Respostas.
A resposta depende do tamanho da sua equipe e da qualidade do seu controle de origem e da capacidade de mesclar conjuntos de mudanças complexas corretamente. Por exemplo, no controle de fonte de ramo completo, como a fusão CVS ou SVN pode ser difícil e você pode estar melhor com o primeiro modelo, enquanto que se usar um sistema mais complexo como o IBM ClearCase e com um tamanho maior de equipe, você poderia ser melhor com o segundo modelo ou uma combinação dos dois.
Eu, pessoalmente, separaria o modelo de ramal de recursos, onde cada característica principal é desenvolvida em um ramo separado, com subdivisões de tarefas para cada mudança feita pelo desenvolvedor individual. À medida que os recursos se estabilizam, eles são mesclados ao tronco, o que você mantém razoavelmente estável e passa todos os testes de regressão em todos os momentos. À medida que você está perto do final do seu ciclo de lançamento e todos os ramos de recursos se fundem, você se estabiliza e se ramifica de um ramo do sistema de liberação no qual você apenas faz correções de bug de estabilidade e backports necessários, enquanto o tronco é usado para o desenvolvimento da próxima versão e você novamente se ramificam para novos ramos de recursos. E assim por diante.
Desta forma, o tronco 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 fusões de recursos, os ramos de recursos são desenvolvimento de ritmo rápido com integração contínua e sub-ramos de tarefas individuais podem ser muitas vezes atualizado do ramo de recursos para manter todos os que trabalham no mesmo recurso em sincronia, enquanto simultaneamente não afetam outras equipes trabalhando em diferentes recursos.
Ao mesmo tempo, você tem através do histórico um conjunto de ramos de lançamento, onde você pode fornecer backports, suporte e correções de erros para seus clientes que, por qualquer motivo, permanecem em versões anteriores do seu produto ou mesmo apenas na versão mais recente 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 passar todos os testes de regressão e outros controles de qualidade de liberação.
Se por algum motivo dois recursos são co-dependentes e precisam de mudanças feitas um com o outro, você pode considerar desenvolver ambos no mesmo ramo de recursos ou exigir que os recursos agrupem regularmente partes estáveis do código no tronco e depois atualize as alterações de tronco para trocar código entre ramos do tronco. Ou se você precisar isolar esses dois recursos de outros, você pode criar um ramo comum do qual você ramifica esses ramos de recursos e que você pode usar para trocar código entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de fonte sem ramos esparsos e capacidade de fusão adequada como CVS ou SVN, o que tornaria todo esse modelo um pesadelo para configurar, gerenciar e integrar.
Eu acho o tópico realmente interessante, porque eu confio muito nas filiais no meu trabalho diário.
Lembro-me de Mark Shuttleworth, que propõe um modelo sobre manter o ramo principal puro enquanto vai além do CI convencional. Eu postei sobre isso aqui. Como estou familiarizado com o Cruise Control, também bloguei sobre filiais de tarefas e CI aqui. É um tutorial passo a passo explicando como fazê-lo com SCM de plástico. Finalmente, encontrei alguns dos tópicos sobre CI (e potencialmente falando sobre ramificação) no livro de Duvall sobre a CI também muito interessante.
Espero que você ache os links interessantes.
Eu pessoalmente acho muito mais limpo ter um tronco estável e apresentar ramificações. Dessa forma, os testadores e similares conseguem permanecer em uma única "versão" e atualizar do tronco para testar qualquer recurso que seja codificado.
Além disso, se vários desenvolvedores estiverem trabalhando em recursos diferentes, eles podem ter seus próprios ramos separados, depois fundir no tronco quando terminarem e enviar um recurso para serem testados sem que o testador tenha que alternar para vários ramos para testar diferentes recursos.
Como um bônus adicional, há algum nível de testes de integração que vem automaticamente.
Penso que qualquer uma das estratégias pode ser usada com o desenvolvimento contínuo, desde que você se lembre de um dos princípios fundamentais que cada desenvolvedor comete no tronco / mainline todos os dias.
Eu tenho feito uma leitura deste livro sobre a CI e os autores sugerem que a ramificação por lançamento é a estratégia de ramificação preferida. Eu tenho que concordar. O raciocínio por recurso não faz sentido para mim ao usar o CI.
Vou tentar e explicar por que estou pensando dessa maneira. Digamos que três desenvolvedores tomem um ramo para trabalhar em um recurso. Cada recurso levará vários dias ou semanas para terminar. Para garantir que a equipe esteja se integrando continuamente, eles devem se comprometer com a filial principal pelo menos uma vez por dia. Assim que eles começam a fazer isso, eles perdem o benefício de criar um ramo de recursos. Suas mudanças não são mais separadas de todas as mudanças do outro desenvolvedor. Sendo assim, por que se preocupar em criar filiais de recursos em primeiro lugar?
O uso de ramificação por versão requer muito menos fusão entre os ramos (sempre é uma coisa boa), garante que todas as alterações sejam integradas o mais rápido possível e (se feito corretamente) garante que sua base de código esteja sempre pronta para ser liberada. O lado negativo para se ramificar pelo lançamento é que você deve ter um cuidado consideravelmente mais cuidadoso com as mudanças. Por exemplo. A refatoração ampla deve ser feita de forma incremental e, se você já integrou um novo recurso que não deseja na próxima versão, ele deve estar oculto usando algum tipo de mecanismo de alternância de recursos.
Há mais de uma opinião sobre este assunto. Aqui está uma postagem de blog que é uma ramificação de recursos pro com CI.
Os ramos de lançamento são muito úteis, e até mesmo absolutamente necessários, se você precisar manter várias versões do seu aplicativo.
Os ramos de recursos também são muito convenientes, especialmente se um desenvolvedor precisa trabalhar em uma grande mudança, enquanto outros ainda lançam novas versões.
Então, para mim, usar ambos os mecanismos é uma estratégia muito boa.
Link interessante do Livro do SVN.
Recentemente, gostei desse modelo ao usar o git. Embora sua pergunta seja marcada como "svn", você ainda pode fazer algum uso disso.
A integração contínua pode, em certa medida, acontecer no ramo "desenvolver" (ou seja o que for que você chamar) neste modelo, embora possuir ramos de recursos longos para lançamentos futuros não o tornem tão rígido quanto a considerar cada mudança acontecendo com o código em algum lugar. A questão permanece, se você realmente quer isso. Martin Fowler faz.
A integração contínua não deve ser qualquer tipo de fator na determinação de sua estratégia de ramificação. Sua abordagem de ramificação deve ser selecionada com base em sua equipe, o sistema em desenvolvimento e as ferramentas disponíveis para você.
Tendo dito isto .
não há nenhuma razão para que a CI não possa ser usada em ambas as abordagens que você descreve, essas abordagens funcionam bastante bem em combinação, nenhum dos dois trabalha "melhor" do que o outro CI faz todo o sentido com um tronco instável.
Tudo isso foi respondido na quarta pergunta na página da qual você tirou os diagramas: blogs. collab / subversion / 2007/11 / branching-strat /
Enquanto você entender os princípios, você sempre pode reinventar as melhores práticas. Se você não entender os princípios, as melhores práticas irão levá-lo até antes de desmoronar devido a algum requisito externo conflitante.
Leia o link. Uma vez que você obteve o básico, leia o seguinte artigo pelo venerável Henrik Kniberg. Ele irá ajudá-lo a relacionar o Mainline Model com integração contínua.
Quando iniciamos nossa equipe, herdamos uma estratégia baseada em lançamentos do fornecedor que originalmente desenvolveu o sistema ao qual estávamos prestes a se encarregar. Isso funcionou até o momento em que nossos clientes solicitaram que vários recursos desenvolvidos não fossem incluídos em um lançamento (f. y.i.
250k linhas de código,
2500 arquivos, Scrum com XP SDLC).
Em seguida, começamos a olhar para os ramos baseados em recursos. Isso também funcionou por um tempo - como 2 meses até o momento em que percebemos que nosso processo de teste de regressão levaria mais de 2 semanas, o que combinado com a incerteza do que seria lançado criou uma enorme inconveniência.
O último "prego no caixão" de estratégias SC puras veio quando decidimos que deveríamos ter 1. tronco estável e 2. A produção deveria conter BINÁRIOS testados ST, UAT e Regressão (não apenas fonte - pense CC).
Isso nos leva a conceber uma estratégia que seja um híbrido entre as estratégias SC e baseadas em lançamento.
Então nós temos um baú. Todos os sprints nos ramificamos no ramo de sprint (para pessoas não ágeis - um sprint é apenas um esforço de desenvolvimento com caixa de tempo com saída variável com base na complexidade). Do ramo de sprint criamos os ramos de recursos e o desenvolvimento paralelo é iniciado neles. Uma vez que os recursos estão completos e testados pelo sistema, e recebemos a intenção de implementá-los, eles são incorporados ao ramo de sprint - alguns podem flutuar em vários sprints, geralmente os mais complexos. Uma vez que o sprint está perto do seu fim e as características estão completas. nós "renomeamos" o ramo de sprint para "regressão" (isso permite que o CruiseControl o apanhe sem qualquer reconfiguração) e o teste de regressão / integração começa no EAR construído no cc. Quando tudo estiver pronto, ele vai em produção.
Em suma, os ramos baseados em recursos são usados para desenvolver, teste do sistema e funcionalidade UAT. O ramo de sprint (realmente o ramo de lançamento) é usado para mesclar seletivamente os recursos sob demanda e teste de integração.
Agora, aqui é uma questão para a comunidade - obviamente estamos tendo problemas para realizar uma integração contínua devido ao fato de que o desenvolvimento acontece em muitos ramos e a sobrecarga de reconfiguração do CruiseControl. Alguém pode sugerir e orientar?
Do jeito que eu vejo você quer ter um conjunto limitado de ramos onde você pode se concentrar. Uma vez que você deseja testes, métricas de qualidade de código e muitas coisas interessantes para executar com as compilações, ter muitos relatórios provavelmente irá levá-lo a perder informações.
Quando e o que se ramifica, geralmente depende do tamanho da equipe e do tamanho das características que estão sendo desenvolvidas. Eu não acho que haja uma regra de ouro. Certifique-se de usar uma estratégia onde você possa receber comentários com antecedência / freqüência, e isso inclui ter qualidade envolvida desde o início dos recursos. O bit de qualidade significa que, à medida que você está automatizando à medida que a equipe se desenvolve, se você se ramifica para um grande conjunto de recursos criado por uma equipe, você também deve ter qualidade envolvida na equipe.
ps Onde você obteve as referências da abordagem? - não sente que esses gráficos representam todas as opções.
Atualização 1: expandindo porque eu disse que não é uma regra de ouro. Basicamente, para equipes relativamente pequenas, achei melhor usar uma abordagem que seja uma mistura. Os ramos de recursos são criados se for algo longo e parte da equipe continuará adicionando recursos menores.
Eu acho que as ferramentas que você usa são um grande fator aqui.
Se você estiver usando a subversão, aderindo à opção 1 e soltando as filiais. Se você estiver usando o GIT, a opção 2 funcionará bem para você.
Комментариев нет:
Отправить комментарий