Qual é a melhor estratégia de ramificação a ser usada quando você deseja fazer integração contínua?
- Ramificação de versão: desenvolva no tronco, mantenha uma ramificação para cada versão.
- Ramificação de recurso: desenvolva cada recurso em uma ramificação separada, mescle apenas quando estiver estável.
Faz sentido usar essas duas estratégias juntas? Tipo, você ramifica para cada versão, mas também ramifica para grandes recursos? Uma dessas estratégias combina melhor com a integração contínua? Usar a integração contínua faria sentido ao usar um tronco instável?
svn
version-control
continuous-integration
branch
KingNestor
fonte
fonte
Respostas:
Acho o assunto muito interessante, pois confio muito em ramos no meu trabalho diário.
Espero que você ache os links interessantes.
fonte
A resposta depende do tamanho de sua equipe e da qualidade de seu controle de origem e da capacidade de mesclar conjuntos de mudanças complexos corretamente. Por exemplo, em controle de fonte de filial completo como CVS ou mesclagem de SVN pode ser difícil e você pode ficar melhor com o primeiro modelo, enquanto se usar um sistema mais complexo como IBM ClearCase e com um tamanho de equipe maior, você poderia ser melhor com o segundo modelo ou uma combinação dos dois.
Eu, pessoalmente, separaria o modelo de branch de recurso, onde cada recurso principal é desenvolvido em um branch separado, com sub-branches de tarefa para cada mudança feita por desenvolvedor individual. Conforme os recursos se estabilizam, eles são mesclados ao tronco, que você mantém razoavelmente estável e passa em todos os testes de regressão o tempo todo. Conforme você se aproxima do fim do seu ciclo de lançamento e todos os ramos de recursos se fundem, você estabiliza e ramifica um ramo do sistema de lançamento no qual você apenas faz correções de bugs de estabilidade e backports necessários, enquanto o tronco é usado para o desenvolvimento da próxima versão e você novamente ramificar para novos ramos de recursos. 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) nas principais mudanças e fusões de recursos, os branches de recursos são de desenvolvimento rápido com integração contínua e sub-branches de tarefas individuais podem ser frequentemente atualizado a partir do branch de recursos para manter todos trabalhando no mesmo recurso em sincronia, enquanto simultaneamente não afeta outras equipes que trabalham em recursos diferentes.
Ao mesmo tempo, você tem ao longo da história um conjunto de ramos de lançamento, onde você pode fornecer backports, suporte e correções de bugs para seus clientes que por qualquer motivo permanecem nas versões anteriores do seu produto ou mesmo apenas na última versão lançada. Assim como com o tronco, você não configura a integração contínua nos ramos de lançamento, eles são cuidadosamente integrados ao passar em todos os testes de regressão e outros controles de qualidade de lançamento.
Se por algum motivo dois recursos são co-dependentes e precisam de mudanças feitas um pelo outro, você pode considerar desenvolver ambos no mesmo ramo de recurso ou exigir que os recursos mesclem regularmente partes estáveis do código para o tronco e, em seguida, atualize as alterações de tronco para trocar código entre ramos de tronco. Ou, se você precisar isolar esses dois recursos de outros, pode criar uma ramificação comum a partir da qual ramificará essas ramificações de recursos e que poderá 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 origem sem ramificações esparsas e capacidade de mesclagem adequada como CVS ou SVN, o que tornaria todo este modelo um pesadelo para configurar, gerenciar e integrar.
fonte
Eu pessoalmente acho muito mais limpo ter um tronco estável e ramificar recursos. Dessa forma, os testadores e similares conseguem ficar em uma única "versão" e atualizar do tronco para testar qualquer recurso que seja de código completo.
Além disso, se vários desenvolvedores estiverem trabalhando em recursos diferentes, todos eles podem ter seus próprios ramos separados e, em seguida, mesclar para o tronco quando terminar e enviar um recurso para ser testado sem que o testador precise alternar para vários ramos para testar recursos diferentes.
Como um bônus adicional, há algum nível de teste de integração que vem automaticamente.
fonte
Acho que qualquer uma das estratégias pode ser usada com desenvolvimento contínuo, desde que você se lembre de um dos princípios-chave que cada desenvolvedor se compromete com o tronco / linha principal todos os dias.
http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitsToTheMainlineEveryDay
EDITAR
Tenho feito algumas leituras deste livro sobre CI e os autores sugerem que a ramificação por lançamento é sua estratégia de ramificação preferida. Eu tenho que concordar. Ramificar por recurso não faz sentido para mim ao usar CI.
Vou tentar explicar porque estou pensando dessa maneira. Digamos que três desenvolvedores cada um pegue um ramo para trabalhar em um recurso. Cada recurso levará vários dias ou semanas para ser concluído. Para garantir que a equipe esteja continuamente integrada, eles devem se comprometer com a filial principal pelo menos uma vez por dia. Assim que começam a fazer isso, perdem o benefício de criar um branch de recurso. Suas alterações não são mais separadas de todas as alterações do outro desenvolvedor. Sendo esse o caso, por que se preocupar em criar ramificações de recursos em primeiro lugar?
Usar ramificação por lançamento requer muito menos fusão entre ramos (sempre uma coisa boa), garante que todas as mudanças sejam integradas o mais rápido possível e (se feito corretamente) garante que sua base de código esteja sempre pronta para lançamento. O lado ruim da ramificação por lançamento é que você precisa ser consideravelmente mais cuidadoso com as mudanças. Por exemplo, a refatoração grande deve ser feita de forma incremental e se você já integrou um novo recurso que não deseja na próxima versão, então ele deve ser oculto usando algum tipo de mecanismo de alternância de recursos .
OUTRA EDIÇÃO
Existe mais de uma opinião sobre este assunto. Aqui está uma postagem de blog que é um recurso profissional ramificado com CI
http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/
fonte
Ramificações de lançamento são muito úteis, e até mesmo absolutamente necessárias, se você precisar manter várias versões de seu aplicativo.
Ramificações de recursos também são muito convenientes, principalmente se um desenvolvedor precisar trabalhar em uma grande mudança, enquanto outros ainda lançam novas versões.
Portanto, para mim, usar os dois mecanismos é uma estratégia muito boa.
Link interessante do Livro de SVN .
fonte
Recentemente, passei a gostar desse modelo ao usar o git. Embora sua pergunta esteja marcada como "svn", você ainda poderá fazer algum uso dela.
A integração contínua pode, até certo ponto, acontecer no branch "desenvolver" (ou como você quiser) neste modelo, embora ter branches de recursos de longa execução para lançamentos futuros não o tornaria tão rígido a ponto de considerar cada mudança acontecendo no código em algum lugar. A questão permanece, se você realmente deseja isso. Martin Fowler, sim.
fonte
A integração contínua não deve ser nenhum 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 ...
Tudo isso foi respondido na quarta pergunta da página de onde você tirou os diagramas: http://blogs.collab.net/subversion/2007/11/branching-strat/
fonte
Contanto que você entenda os princípios, você sempre pode reinventar as melhores práticas. Se você não entender os princípios, as melhores práticas o levarão muito longe antes de desmoronar devido a algum requisito externo conflitante.
Para a melhor introdução ao Mainline Model, leia isto: https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf
Leia o link. Depois de aprender o básico, leia o seguinte artigo do venerável Henrik Kniberg. Isso o ajudará a relacionar o Mainline Model com integração contínua.
http://www.infoq.com/articles/agile-version-control
fonte
Quando começamos nossa equipe, herdamos uma estratégia baseada no lançamento do fornecedor que originalmente desenvolveu o sistema que estávamos prestes a assumir. Funcionou até o momento em que nossos clientes solicitaram que vários recursos desenvolvidos não fossem incluídos em uma versão (fyi ~ 250k linhas de código, ~ 2500 arquivos, Scrum com XP SDLC).
Então começamos a olhar para branches baseados em recursos. Isso também funcionou por um tempo - como 2 meses até o ponto 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 um grande inconveniente.
O "prego no caixão" final das estratégias SC puras veio quando decidimos que deveríamos ter 1. tronco estável e 2. A produção deve conter ST, UAT e BINÁRIOS testados por regressão (não apenas na origem - pense em CC).
Isso nos levou a criar uma estratégia que é um híbrido entre estratégias de SC baseadas em recursos e versões.
Portanto, temos um baú. A cada sprint, ramificamos o branch sprint (para o pessoal não ágil - um sprint é apenas um esforço de desenvolvimento com tempo limitado e saída variável com base na complexidade). No branch sprint, criamos os branches de recursos e o desenvolvimento paralelo começa neles. Depois que os recursos são concluídos e o sistema testado, e recebemos a intenção de implantá-los, eles são mesclados ao branch do sprint - alguns podem flutuar em vários sprints, geralmente os mais complexos. Uma vez que o sprint está próximo do fim e os recursos estão completos ... nós "renomeamos" o branch do sprint para "regressão" (isso permite que o CruiseControl o pegue sem qualquer reconfiguração) e, em seguida, os testes de regressão / integração começam no cc-construído ORELHA. Quando tudo estiver pronto, ele vai para a produção.
Em suma, ramificações baseadas em recursos são usadas para desenvolver, testar o sistema e a funcionalidade do UAT. A ramificação sprint (na verdade, a ramificação de lançamento) é usada para mesclar seletivamente recursos sob demanda e teste de integração.
Agora, aqui está uma pergunta para a comunidade - obviamente estamos tendo problemas para realizar a integração contínua devido ao fato de que o desenvolvimento acontece em muitas ramificações e à sobrecarga de reconfiguração do CruiseControl. Alguém pode sugerir e aconselhar?
fonte
A meu ver, você deseja ter um conjunto limitado de ramos onde possa se concentrar. Já 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 fará com que você perca informações.
Quando e o que ramificar, geralmente depende do tamanho da equipe e do tamanho dos recursos que estão sendo desenvolvidos. Não acho que haja uma regra de ouro. Certifique-se de usar uma estratégia em que possa obter feedback com antecedência / frequência, e isso inclui ter qualidade envolvida desde o início dos recursos. A parte da qualidade significa que, conforme você está automatizando à medida que a equipe se desenvolve, se você ramificar para um grande conjunto de recursos que uma equipe está construindo, terá que ter qualidade envolvida na equipe também.
ps Onde você conseguiu essas referências de abordagem? - não sinto que esses gráficos representam todas as opções
Atualização 1: explicando por que eu disse que não é uma regra de ouro. Basicamente, para equipes relativamente pequenas, descobri que é melhor usar uma abordagem mista. Ramificações de recursos são criadas se for algo longo e parte da equipe continuará adicionando recursos menores.
fonte
Dave Farley , autor de Continuous Delivery , referiu-se ao Trunk Based Development (TBD) como a pedra angular da Continuous Integration (CI) e Continuous Delivery (CD). Ele diz:
Ele também diz,
Desenvolvimento baseado em tronco (TBD) é a prática de integrar alterações de código no tronco (também conhecido como mestre, linha principal) pelo menos uma vez por dia - de preferência várias vezes por dia. Integração contínua (CI) é uma prática semelhante, exceto que também envolve a verificação das alterações de código usando testes automatizados. A melhor estratégia de ramificação para isso é trabalhar diretamente fora do tronco e realizar revisões de código por meio da Programação em par . Se, por algum motivo, você não conseguir emparelhar ou apenas quiser ramificar, certifique-se de que seus ramos tenham vida curta (menos de um dia).
Para recursos grandes (ou seja, aqueles que levam mais de um dia), tente dividi-los em pequenos pedaços de lógica que podem ser integrados ao tronco sem quebrar o software. Você também pode usar técnicas como sinalização de recurso e ramificação por abstração, que permitem implantar trabalho incompleto sem afetar os usuários finais.
fonte
Acho que as ferramentas que você usa são um grande fator aqui.
fonte