Suponha que você esteja desenvolvendo um produto de software que possui lançamentos periódicos. Quais são as melhores práticas em relação à ramificação e fusão? Cortar ramificações periódicas de lançamento ao público (ou quem quer que seja o seu cliente) e, em seguida, continuar o desenvolvimento no tronco, ou considerar o tronco a versão estável, identificando-o como um lançamento periodicamente e fazendo seu trabalho experimental em ramos. O que as pessoas acham que o tronco é considerado "dourado" ou "caixa de areia"?
version-control
Sam McAfee
fonte
fonte
Respostas:
Eu tentei ambos os métodos com uma grande aplicação comercial.
A resposta para qual método é melhor depende muito da sua situação exata, mas vou escrever o que minha experiência geral mostrou até agora.
O melhor método geral (na minha experiência): o tronco deve ser sempre estável.
Aqui estão algumas diretrizes e benefícios deste método:
Se você tentar fazer o oposto e fazer todo o seu desenvolvimento no tronco, terá os seguintes problemas:
Você simplesmente não terá a flexibilidade necessária se tentar manter um ramo estável e o tronco como caixa de proteção de desenvolvimento. O motivo é que você não pode escolher no tronco o que deseja colocar nessa versão estável. Já estaria tudo misturado no porta-malas.
O único caso em particular que eu diria para fazer todo o desenvolvimento no tronco é quando você está iniciando um novo projeto. Também pode haver outros casos, dependendo da sua situação.
A propósito, os sistemas de controle de versão distribuídos oferecem muito mais flexibilidade e eu recomendo mudar para hg ou git.
fonte
Eu trabalhei com ambas as técnicas e diria que desenvolver no tronco e ramificar pontos estáveis como lançamentos é o melhor caminho a percorrer.
As pessoas acima que se opõem a dizer que você terá:
provavelmente não utilizaram técnicas de integração contínua.
É verdade que, se você não realizar várias compilações de teste durante o dia, digamos que uma vez a cada hora, elas se abrirão para esses problemas que estrangularão rapidamente o ritmo do desenvolvimento.
A realização de várias compilações de teste durante o dia desdobra rapidamente as atualizações da base de código principal, para que outras pessoas possam usá-la e também o alerta durante o dia, se alguém quebrou a compilação para que possa corrigi-la antes de voltar para casa.
Como apontado, apenas descobrir sobre uma compilação quebrada quando a compilação noturna para executar os testes de regressão falha é pura tolice e desacelera rapidamente as coisas.
Leia o artigo de Martin Fowler sobre integração contínua . Rolamos nosso próprio sistema para um grande projeto (3.000kSLOC) em cerca de 2.000 linhas de Posix sh.
fonte
Tenho a tendência de adotar a abordagem "ramo de lançamento". O tronco é volátil. Quando o tempo de lançamento se aproxima, eu fazia um ramo de lançamento, que trataria com mais cautela. Quando isso for feito, eu rotularia / rotularia o estado do repositório para conhecer a versão lançada "oficial".
Entendo que existem outras maneiras de fazê-lo - foi assim que eu fiz no passado.
fonte
Ambos.
O tronco é usado para a maioria do desenvolvimento. Mas espera-se que sejam feitos os melhores esforços para garantir que qualquer check-in no porta-malas não o interrompa. (parcialmente verificado por um sistema automatizado de construção e teste)
As versões são mantidas em seu próprio diretório, com apenas correções de erros sendo feitas nelas (e depois mescladas no tronco).
Qualquer novo recurso que deixe o tronco em um estado instável ou inoperante é feito em sua própria ramificação separada e depois mesclado no tronco após a conclusão.
fonte
Gosto e uso a abordagem descrita por Henrik Kniberg no Controle de versão para várias equipes ágeis . Henrik fez um ótimo trabalho ao explicar como lidar com o controle de versão em um ambiente ágil com várias equipes (funciona também para uma única equipe em ambientes tradicionais) e não há sentido em parafrasear ele, então vou postar a "folha de dicas" (que é auto-explicativo) abaixo:
Eu gosto disto porque:
E, caso não tenha sido suficientemente explícito: o desenvolvimento é feito em "ramo (s) de trabalho", o tronco é usado para o código DONE (liberável). Verifique o Controle de versão para várias equipes ágeis para obter todos os detalhes.
fonte
Uma boa referência em um processo de desenvolvimento que mantém o tronco estável e faz todo o trabalho em filiais é o Sistema de Desenvolvimento de Qualidade Final da Divmod . Um resumo rápido:
Eles usam o SVN para isso, mas isso pode ser feito facilmente com qualquer um dos sistemas de controle de versão distribuídos.
fonte
Acho que sua segunda abordagem (por exemplo, etiquetar lançamentos e fazer coisas experimentais nos galhos, considerando o tronco estável) é a melhor abordagem.
Deve ficar claro que as ramificações herdam todos os erros de um sistema no momento em que ela é ramificada: se as correções forem aplicadas a um tronco, você terá que ir uma a uma a todas as ramificações, se você mantiver ramificações como uma espécie de liberte o terminador do ciclo. Se você já teve 20 lançamentos e descobriu um bug que remonta ao primeiro, precisará reaplicar sua correção 20 vezes.
As ramificações devem ser as verdadeiras caixas de areia, embora o tronco também tenha esse papel: as tags indicarão se o código é "dourado" naquele momento, adequado para liberação.
fonte
Desenvolvemos no porta-malas, a menos que as alterações sejam muito grandes, desestabilizadoras ou estamos chegando a um grande lançamento de um de nossos produtos; nesse caso, criamos uma filial temporária. Também criamos uma filial permanente para cada versão individual do produto. Achei o documento da Microsoft sobre Orientação de Ramificação bastante útil. O tutorial de Eric Sink sobre ramificação também é interessante e aponta que o que funciona para a Microsoft pode ser muito pesado para alguns de nós. Foi no nosso caso, na verdade, usamos a abordagem que Eric diz que sua equipe faz.
fonte
Depende das suas situações. Usamos o Perforce e normalmente temos várias linhas de desenvolvimento. O tronco é considerado "ouro" e todo o desenvolvimento acontece em filiais que são mescladas de volta à linha principal quando são estáveis o suficiente para serem integradas. Isso permite a rejeição de recursos que não são cortados e pode fornecer uma capacidade incremental sólida ao longo do tempo que projetos / recursos independentes podem captar.
Há um custo de integração para a fusão e a atualização de novos recursos lançados no tronco, mas você sofrerá essa dor de qualquer maneira. Fazer com que todos desenvolvam juntos no porta-malas pode levar a uma situação do oeste selvagem, enquanto a ramificação permite escalar e escolher os pontos nos quais você gostaria de tomar as pílulas de integração amargas. Atualmente, estamos escalados para mais de cem desenvolvedores em uma dúzia de projetos, cada um com várias versões usando os mesmos componentes principais, e funciona muito bem.
A vantagem disso é que você pode fazer isso recursivamente: um ramo de grande recurso pode ser seu próprio tronco, com outros ramos saindo. Além disso, as versões finais obtêm uma nova ramificação para oferecer a você um local para manutenção estável.
fonte
Tentar gerenciar a manutenção do código de produção atual de acordo com o novo desenvolvimento é problemático na melhor das hipóteses. Para mitigar esses problemas, o código deve se ramificar em uma linha de manutenção assim que os esforços de teste forem concluídos e o código estiver pronto para entrega. Além disso, a linha principal deve ramificar-se para ajudar na estabilização da liberação, conter esforços experimentais de desenvolvimento ou alojar quaisquer esforços de desenvolvimento cujo ciclo de vida se estenda por várias liberações.
Uma ramificação que não seja de manutenção deve ser criada apenas quando houver a probabilidade (ou certeza) de colisões entre o código que seria difícil de gerenciar de outra maneira. Se o ramo não resolver um problema logístico, ele criará um.
O desenvolvimento normal da versão ocorre na linha principal. Os desenvolvedores entram e saem da linha principal para obter o trabalho normal de lançamento. O trabalho de desenvolvimento de correções para o código de produção atual deve estar na ramificação dessa versão e depois ser mesclado à linha principal assim que o patch passar no teste e for implantado. O trabalho em ramos que não são de manutenção deve ser coordenado caso a caso.
fonte
Depende do tamanho do seu esforço de desenvolvimento. Várias equipes trabalhando em paralelo não conseguirão trabalhar efetivamente, tudo no mesmo código (tronco). Se você tem apenas um pequeno grupo de pessoas trabalhando e sua principal preocupação é cortar uma filial, você pode continuar trabalhando enquanto volta à filial para fazer correções de bugs no código de produção atual que funcionaria. Este é um uso trivial de ramificação e não muito oneroso.
Se você tiver muito desenvolvimento paralelo, precisará de ramificações para cada um dos esforços, mas isso também exigirá mais disciplina: verifique se suas ramificações estão testadas e prontas para serem fundidas novamente. O agendamento é mesclado para que dois grupos não tentem mesclar ao mesmo tempo etc.
Algumas ramificações estão em desenvolvimento há tanto tempo que é necessário permitir a mesclagem do tronco para a ramificação, a fim de reduzir o número de surpresas ao finalmente se mesclar novamente ao tronco.
Você terá que experimentar se tiver um grande grupo de desenvolvedores e sentir o que funciona na sua situação. Aqui está uma página da Microsoft que pode ser útil: http://msdn.microsoft.com/en-us/library/aa730834(VS.80).aspx
fonte
Estamos usando o tronco para o desenvolvimento principal e a filial para trabalhos de manutenção de lançamentos. Isso funciona bem. Porém, as ramificações devem ser usadas apenas para correção de bugs, sem grandes alterações, especialmente no lado do banco de dados, temos uma regra de que somente uma alteração de esquema pode ocorrer no tronco principal e nunca na ramificação.
fonte
Se você estiver trabalhando em um ciclo de lançamento, grande recurso, será abandonado em um galho. Caso contrário, trabalhamos em tronco e ramificamos para cada versão de produção no momento em que construímos.
As compilações de produção anteriores são movidas naquele momento para old_production_ e a liberação atual do produto é sempre apenas produção. Tudo o que nosso servidor de build sabe sobre produção é como implantar a ramificação de produção, e nós a iniciamos com um gatilho de força.
fonte
Seguimos a abordagem trunk = stream de desenvolvimento atual, branch = release (s). Ao ser liberado para o cliente, ramificamos o porta-malas e continuamos a avançar. Você precisará decidir quantos lançamentos você está preparado para oferecer suporte. Quanto mais você suporta, mais você estará mesclando as correções de bugs. Tentamos manter nossos clientes com no máximo 2 lançamentos atrás do porta-malas. (Por exemplo, Dev = 1.3, versões suportadas 1.2 e 1.1).
fonte
O tronco é geralmente a principal linha de desenvolvimento.
As liberações são ramificadas e, muitas vezes, o trabalho experimental ou principal é feito nas filiais e depois fundido de volta ao tronco quando ele está pronto para ser integrado à linha de desenvolvimento principal.
fonte
O tronco geralmente deve ser sua principal fonte de desenvolvimento. Caso contrário, você gastará muito tempo mesclando novos recursos. Já vi isso de outra maneira e geralmente leva a muitas dores de cabeça de integração de última hora.
Rotulamos nossos lançamentos para que possamos responder rapidamente a emergências de produção sem distribuir o desenvolvimento ativo.
fonte
Para mim, isso depende do software que estou usando.
No CVS, eu apenas trabalhava no "tronco" e nunca tag / branch, porque era realmente doloroso fazer o contrário.
No SVN, eu fazia minhas coisas "de ponta" no porta-malas, mas quando era hora de fazer um push no servidor era etiquetado adequadamente.
Recentemente, mudei para o git. Agora acho que nunca trabalho no porta-malas. Em vez disso, utilizo uma ramificação da caixa de areia denominada "new-featurename" e, em seguida, mesclo-a em uma ramificação fixa da "produção atual". Agora que penso nisso, eu realmente deveria estar criando ramificações "release-VERSIONNUMBER" antes de me fundir novamente na "produção atual" para poder voltar às versões estáveis mais antigas ...
fonte
Realmente depende de quão bem sua organização / equipe gerencia versões e qual SCM você usa.
fonte
Aqui está o design SVN que eu prefiro:
Todo o trabalho é feito a partir do desenvolvimento / tronco, exceto os principais recursos que exigem sua própria ramificação. Depois que o trabalho é testado em relação ao desenvolvimento / tronco, mesclamos os problemas testados no beta / tronco. Se necessário, o código é testado no servidor beta. Quando estamos prontos para implementar algumas alterações, apenas mesclamos as revisões apropriadas em release / trunk e implantamos.
As tags podem ser criadas na ramificação beta ou na ramificação de lançamento, para que possamos rastrear versões específicas para versões beta e versões.
Esse design permite muita flexibilidade. Também facilita deixar revisões no beta / tronco enquanto mesclamos outros para liberar / tronco se algumas revisões não passarem nos testes no beta.
fonte
O método que usamos é a abordagem Perforce, que é discutida detalhadamente no grande livro de Laura Wingerd:
http://oreilly.com/catalog/9780596101855/index.html
Enquanto o livro é centrado forçosamente (Wingerd é um gerente de produtos Perforce), os conceitos podem ser aplicados a todo ou qualquer VCS.
A abordagem forçada (e plataforma) nos serviu muito bem. É usado em muitas empresas (google, Intuit e, ouvi dizer, o próprio Microsoft Windows).
Vale a pena ler o livro.
fonte
Leia isto: http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf
fonte
Não existe uma resposta única para a questão da convenção de subversão IMHO.
Realmente depende da dinâmica do projeto e da empresa que o utiliza. Em um ambiente de ritmo acelerado, quando uma versão pode ocorrer com frequência a cada poucos dias, se você tentar marcar e ramificar religiosamente, você terminará com um repositório incontrolável. Nesse ambiente, a abordagem de ramificação quando necessário criaria um ambiente muito mais sustentável.
Além disso - na minha experiência, é extremamente fácil, do ponto de vista administrativo, alternar entre metodologias svn quando você escolher.
As duas abordagens que eu sei que funcionam melhor são a ramificação quando necessário e a ramificação de cada tarefa. É claro que estes são exatamente o oposto um do outro. Como eu disse - é tudo sobre a dinâmica do projeto.
fonte
@ Brian R. Bondy: Observe que isso não é uma solução, uma vez que sua equipe atinge uma certa quantidade de ppl / tarefas tratadas em paralelo no projeto.
Depois que um departamento de controle de qualidade está envolvido no controle de qualidade, os esforços necessários para fornecer uma instalação por filial em andamento são simplesmente muito altos. Pense em SOA / Clientes / Servidores / Serviços da Web / Bancos de dados, todos os quais devem ser fornecidos por filial .
Essa solução também não possui o estágio de integração.
fonte