Mantendo duas versões de software separadas da mesma base de código no controle de versão

45

Digamos que estou escrevendo duas versões diferentes do mesmo software / programa / aplicativo / script e armazenando-as sob controle de versão. A primeira versão é uma versão "Basic" gratuita, enquanto a segunda é uma versão "Premium" paga que pega a base de código da versão gratuita e expande-a com alguns recursos extras de valor agregado. Quaisquer novos patches, correções ou recursos precisam encontrar o caminho para as duas versões.

No momento, estou pensando em usar as ramificações master e develop para a base de código principal (versão gratuita) ao lado das ramificações master-premium e develop-premium da versão paga. Quando uma alteração é feita na versão gratuita e mesclada à ramificação master (após o teste completo em develop , é claro), ela é copiada para a ramificação develop-premium por meio do comando cherry-pick para mais testes e mesclado em master-premium .

Este é o melhor fluxo de trabalho para lidar com essa situação? Há algum problema em potencial, ressalva ou armadilhas a serem percebidos? Existe uma estratégia de ramificação melhor do que a que eu já inventei?

O seu feedback é muito apreciado!

P.S. Isto é para um script PHP armazenado no Git, mas as respostas devem se aplicar a qualquer idioma ou VCS.

    
por Joseph Leedy 11.06.2014 / 05:23
fonte

5 respostas

83

Em vez de ter duas versões de código com uma base comum, você deve projetar seu aplicativo de forma a tornar esses recursos premium plugáveis e orientados pela configuração, em vez de bases de código diferentes.

Se você tem medo de enviar esses recursos premium (desativados por configuração) com a versão básica, ainda é possível remover esse código em uma etapa final de compilação / empacotamento e ter apenas dois perfis de compilação.

Tendo esse design, você também pode enviar 5 sabores diferentes e ficar muito flexível, talvez até mesmo permitindo que terceiros contribuam.

    
por 11.06.2014 / 10:28
fonte
39

Eu recomendo strongmente que não use as agências para essa finalidade. Em geral, você deve considerar as ramificações para as coisas que serão (ou podem ser) mescladas novamente mais tarde (ou para as ramificações de release, onde você eventualmente interrompe o desenvolvimento de uma das ramificações). No seu caso, você nunca mesclará suas versões "básica" e "premium", e ambas serão mantidas indefinidamente, de modo que as ramificações não sejam apropriadas.

Em vez disso, mantenha uma versão comum do código-fonte e use a compilação condicional (por exemplo, #ifdef em C / C ++, sem saber qual é o equivalente para PHP) para incluir ou excluir as seções de código que diferem entre "e" premium ".

Parece que o PHP pode não ter um recurso de compilação condicional embutido, então você pode usar o pré-processador C ( cpp , você provavelmente já tem) para pré-processar seu código-fonte comum e, a partir disso, produzir um "e uma versão" premium "sem as diretivas do pré-processador. Claro, se você optar por fazer isso, você deve usar make ou algo semelhante para automatizar o processo de execução do pré-processador.

    
por 11.06.2014 / 05:53
fonte
8

Estamos usando 2 projetos separados, o Básico e o Premium, que depende do projeto Básico. Não use braches, eles geralmente são usados para recursos.

    
por 11.06.2014 / 07:48
fonte
3

Embora as respostas mais atuais sejam favoráveis à compilação condicional em vez de ramificações, há um cenário em que há um benefício claro no uso de ramificações: se você (agora ou mais tarde) decidir disponibilizar o código-fonte da versão básica, incluindo todo o histórico de versões, mas excluindo todos os recursos premium, você pode fazer isso com a abordagem de ramificações, mas não com uma única ramificação e compilação condicional.

Eu não recomendaria o cherry picking e, em vez disso, mesclaria todas as alterações da versão básica para a versão premium. Não deve haver nenhum recurso ou correção de bug incluído no básico, mas ausente na versão premium. Para tornar as coisas o mais simples possível, você deve certificar-se de que o ramo premium modifica os arquivos comuns o mínimo possível. Portanto, o ramo premium deve conter principalmente arquivos adicionais e talvez algumas pequenas modificações para criar instruções. Dessa forma, as alterações da versão básica serão mescladas automaticamente sem causar conflitos.

A resposta de Greg sugeriu que você “considerasse as ramificações para as coisas que serão (ou podem ser) fundidas novamente de novo mais tarde". Com a abordagem que acabei de descrever, esse é o caso, exceto que a ramificação final de todas as confirmações será master-premium não master (que na verdade é master-basic ).

Submódulos seriam, obviamente, uma opção também. Depende do seu processo de construção, mas se você puder fazer a versão premium em um projeto que usa a versão básica como um módulo, isso seria ótimo. No entanto, você pode ter mais dificuldade se, em algum momento, decidir escolher recursos do ramo premium para o ramo básico. Com submódulos essa mudança seria representada como dois commits distintos, enquanto que com branches isso seria um commit único para a versão básica, e a próxima mesclagem na versão premium saberia que essas mudanças já estão incluídas e não têm para ser mesclado novamente.

    
por 12.06.2014 / 10:56
fonte
0

Em "hardware" isso é feito com frequência, eles são sistemas vendidos para controlar a bagunça, desculpe, não consigo lembrar como eles são chamados.

Uma vez que a máquina de lavar roupa “mid range” é fornecida, o código não é alterado, exceto por uma correção de bug muito importante, mesmo quando o mesmo código é alterado na máquina de lavar “low end” que é enviada alguns meses depois. / p>

Os clientes não esperam obter upgrades em uma máquina de lavar roupa que já trouxeram, um novo modelo também não é enviado a cada poucos meses.

A maioria de nós não mora nesse mundo, então faça o que Greg diz, a menos que você esteja escrevendo softwares para máquinas de lavar roupa.

    
por 12.06.2014 / 10:27
fonte