Você continua o desenvolvimento em uma filial ou no tronco? [fechadas]

170

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"?

Sam McAfee
fonte
3
Querendo saber se isso pode ser marcado novamente sem svn, pois é bastante genérico para gerenciar o controle de origem?
Scott Saad
4
Essa parece ser uma daquelas questões "religiosas".
James McMahon
@ James McMahon - é mais que realmente existem duas práticas recomendadas mutuamente exclusivas, mas algumas pessoas pensam que existe apenas uma. Não ajuda que a SO queira que você tenha uma resposta correta.
Ken Liu

Respostas:

151

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:

  • Codifique cada tarefa (ou conjunto de tarefas relacionado) em sua própria ramificação, e você terá a flexibilidade de quando deseja mesclar essas tarefas e executar uma liberação.
  • O controle de qualidade deve ser feito em cada filial antes de ser mesclado ao tronco.
  • Ao fazer o controle de qualidade em cada ramo individual, você saberá exatamente o que causou o erro mais facilmente.
  • Essa solução é escalável para qualquer número de desenvolvedores.
  • Este método funciona, pois a ramificação é uma operação quase instantânea no SVN.
  • Marque cada versão que você executa.
  • Você pode desenvolver recursos que não planeja liberar por um tempo e decidir exatamente quando mesclá-los.
  • Por todo o trabalho que você faz, você pode ter o benefício de confirmar seu código. Se você trabalhar apenas fora do tronco, provavelmente manterá seu código muito comprometido e, portanto, desprotegido e sem histórico automático.

Se você tentar fazer o oposto e fazer todo o seu desenvolvimento no tronco, terá os seguintes problemas:

  • Problemas constantes de compilação para compilações diárias
  • Perda de produtividade quando um desenvolvedor comete um problema para todas as outras pessoas no projeto
  • Ciclos de lançamento mais longos, porque você precisa finalmente obter uma versão estável
  • Versões menos estáveis

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.

Brian R. Bondy
fonte
35
Desculpe, mas esta resposta está errada. Todo o desenvolvimento deve acontecer no porta-malas. Se você tem algo para 'disparar' ou algum recurso 'arriscado', crie uma ramificação de recurso. As ramificações devem ser mantidas para cada versão do produto em produção ou, se houver uma única versão, use uma ramificação de Integração.
Mitch Wheat
52
Eu não estava afirmando que esse era o único caminho, apenas o melhor. É claro que se você acha que tem motivos suficientes para achar que estou errado, você deve publicá-la. Pelo menos minha resposta é justificada.
Brian R. Bondy
5
Isso é problemático, pois os desenvolvedores podem trabalhar muito tempo em uma filial que está divergindo do tronco principal. Integrar essas coisas mais tarde pode produzir grandes dores de cabeça. Para mim, era sempre mais fácil manter um tronco de borda sangrenta com alguns requisitos mínimos (sempre deve compilar) e ramificar as coisas que deveriam ser estabilizadas para uma liberação.
Mnementh 09/09/09
31
Em resposta à postagem de Mnementh, acredito que uma boa solução é que um desenvolvedor deve mesclar o tronco periodicamente em seu ramo para que não fiquem muito longe do estado do tronco. Cabe a cada desenvolvedor fazer isso com frequência suficiente para que eles não tenham uma enorme dor de cabeça de reintegração em nenhum momento.
RjOllos 11/09/09
8
@Mementement isso não é desculpa. As práticas recomendadas e apenas o bom senso dizem que todos na equipe devem atualizar suas ramificações com tronco. O tronco da linha principal não é perfeito nem deve ser o que você empurra para a produção, ele só precisa compilar e é por isso que, em bons ambientes de desenvolvimento, a maioria dos desenvolvedores é muito boa em garantir que isso aconteça e, se não, o a equipe tem o direito de dificultar essa pessoa ... também ferramentas como o Cruise Control e outras configurações contínuas de compilação. É disso que se trata a integração contínua! Você tem o controle de qualidade para testar suas filiais e não o tronco da linha principal.
PositiveGuy
66

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á:

  • Problemas constantes de compilação para compilações diárias
  • Perda de produtividade quando um desenvolvedor comete um problema para todas as outras pessoas no projeto

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.

Rob Wells
fonte
1
O que a 'integração contínua' tem a ver com a probabilidade de uma equipe se atrasar em seu recurso e atrasar todo um ciclo de lançamento? É o melhor caminho a seguir 'para você'! Fazer várias construções por dia não resolve nenhum problema em potencial, a não ser que você saiba que ela cria! Seus argumentos não fornecem prova de que essa é uma maneira melhor (embora essa seja a maneira que eu costumo fazer também).
Jeach 29/10/10
O IC é necessário para esta resposta, mas também para o de Brian.
jyoungdev
2
@Jeach, fazer várias compilações por dia dá a você a confiança de que é compilada, para que você possa executar testes regularmente, seja simples testes de fumaça durante o dia ou testes de regressão durante a noite. Se você deixar a compilação até a compilação da noite para o teste de regressão, poderá atrasar o projeto inteiro por um dia apenas porque não pode compilar. Isso significa que todos os desenvolvedores não poderão ver os resultados dos testes de regressão para o novo código enviado. Um custo bastante caro, apenas porque, por exemplo, alguém fez check-in de código contendo um erro de sintaxe.
Rob Wells
e se um recurso leva 2 meses para construir, e outra leva 6 meses para construir, você tem que ramos de uso lá, nem tudo pode ser verificado no tronco, em tais casos
Kalpesh Soni
1
@Wolf você está confundindo confusão com confusão, as pessoas a construir produtos, nem todo mundo trabalha para DevOps
Kalpesh Soni
36

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.

Matt Dillard
fonte
19

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.

Andrew Edgecombe
fonte
3
Estou com você nisto ... desenvolvedores que usam apenas um método o tempo todo são o problema!
Jeach
14

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:

texto alternativo texto alternativo

Eu gosto disto porque:

  • É simples: você pode obtê-lo da imagem.
  • Funciona (e dimensiona) bem, sem muitos problemas de mesclagem e conflito.
  • Você pode lançar o "software de trabalho" a qualquer momento (no espírito do ágil).

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.

Pascal Thivent
fonte
Minha experiência pessoal é que isso APENAS funciona para equipes pequenas, ao contrário do seu comentário 'escalável'. À medida que as equipes crescem e as histórias são reformuladas, todas as outras equipes gastam quantidades consideráveis ​​de equipes fazendo fusões. E em projetos muito grandes (muitos arquivos e KLOC), os problemas de mesclagem começam a aparecer regularmente, especialmente quando há muita volatilidade de código.
Jeach 29/10/10
@Jeach Funcionou bem para nós em um grande projeto com 5 equipes organizadas em equipes de recursos, embora não negue que a fusão tenha um custo.
Pascal Thivent
11

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:

  • Todo o trabalho realizado deve ter um ticket associado a ele
  • Uma nova ramificação é criada para cada ticket em que o trabalho para esse ticket é realizado.
  • As alterações dessa ramificação não são mescladas novamente ao tronco da linha principal sem serem revisadas por outro membro do projeto

Eles usam o SVN para isso, mas isso pode ser feito facilmente com qualquer um dos sistemas de controle de versão distribuídos.

Travis B. Hartwell
fonte
10

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.

Jon Limjap
fonte
8

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.

Brian Stewart
fonte
5

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.

Josh Segall
fonte
4

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.

Mandril
fonte
4

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

Harpreet
fonte
4

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.

adriaanp
fonte
1
Por que a regra de nenhum banco de dados é alterada no ramo?
Bjorn Reppen
Nós apenas temos a regra porque facilita a fusão de versões do banco de dados. Isso pode ser porque, da maneira como estamos usando o seqüenciamento nos nomes dos arquivos de script para atualizar o banco de dados, tenho certeza de que, se houver um método diferente, as alterações no banco de dados podem ser alteradas no ramo.
#
2

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.

DevelopingChris
fonte
2

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).

Lou
fonte
1

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.

17 de 26
fonte
1

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.

Jim
fonte
1

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 ...

cpm
fonte
1

Realmente depende de quão bem sua organização / equipe gerencia versões e qual SCM você usa.

  • Se o que vem a seguir (na próxima versão) puder ser facilmente planejado, é melhor você desenvolver o tronco. O gerenciamento de filiais leva mais tempo e recursos. Mas se o próximo passo não puder ser planejado com facilidade (acontece o tempo todo em organizações maiores), você provavelmente acabará escolhendo commits (centenas / milhares) em vez de ramos (várias ou dezenas).
  • Com o Git ou Mercurial, gerenciar ramificações é muito mais fácil que o cvs e o subversion. Eu iria para o methodlogy de tronco / tópico estável. É isso que a equipe do git.git está usando. leia: http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
  • Com o Subversion, apliquei primeiro o methodlogy de desenvolvimento no tronco. Houve algum trabalho na data de lançamento, porque toda vez que eu tinha que escolher cometer erros (minha empresa não é boa em planejamento). Agora eu sou um especialista no Subversion e sei muito bem como gerenciar ramificações no Subversion, então estou indo para o methodlogy estável de ramificações de tópicos / troncos. Funciona muito melhor do que antes. Agora estou tentando a maneira como a equipe git.git funciona, embora provavelmente continuemos com o Subversion.
bo bo
fonte
1

Aqui está o design SVN que eu prefiro:

  • raiz
    • desenvolvimento
      • galhos
        • feature1
        • feature2
        • ...
      • tronco
    • beta
      • Tag
      • tronco
    • liberação
      • Tag
      • tronco

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.

Kevin Crowell
fonte
0

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
0

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.

dev de um olho
fonte
-1

@ 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.

pointernil
fonte
Temos vários controles de qualidade envolvidos em nossa equipe. Eles testam cada recurso de um instalador completo criado a partir da ramificação antes de ser mesclado.
Brian R. Bondy