Como você mantém o código de desenvolvimento e o código de produção? [fechadas]

136

Quais são as melhores práticas e regras práticas a serem seguidas enquanto mantém o código? É uma boa prática ter apenas o código pronto para produção no ramo de desenvolvimento ou o código mais recente não testado deve estar disponível no ramo de desenvolvimento?

Como vocês mantêm o código de desenvolvimento e o código de produção?

Editar - Pergunta complementar - Sua equipe de desenvolvimento segue o protocolo "confirmar o mais rápido possível e, muitas vezes, mesmo que o código contenha bugs menores ou esteja incompleto" ou "commit- Protocolo ONLY-perfect-code "ao confirmar o código na ramificação DEVELOPMENT?

Mohit Ranka
fonte
Eu já respondi uma pergunta semelhante (ou bem, uma pergunta no mesmo espaço / direção) antes, então você pode querer verificar esta pergunta: Quais são algumas boas estratégias para permitir que os aplicativos implantados sejam hotfix?
Até
@revo: aguarde ... minha resposta de 2008 está desatualizada? :) Suponho que sim. Faz mais de 10 anos: editei minha resposta.
VonC 13/03/19

Respostas:

114

Atualização 2019:

Atualmente, a questão seria vista em um contexto usando o Git, e 10 anos usando esse fluxo de trabalho de desenvolvimento distribuído (colaborando principalmente através do GitHub ) mostra as melhores práticas gerais:

  • masteré a ramificação pronta para ser implantada na produção a qualquer momento: a próxima versão, com um conjunto selecionado de ramificações de recursos mescladas master.
  • dev(ou ramo de integração ou ' next') é aquele em que o ramo de recurso selecionado para a próxima versão é testado juntos
  • maintenance(ou hot-fix) ramo é aquele para a evolução da versão atual / correções de bugs, com possíveis mesclagens de volta para deve oumaster

Esse tipo de fluxo de trabalho (onde não se fundem devpara master, mas onde você mesclar único ramo recurso para dev, em seguida, se selecionado, para master, a fim de ser capaz de soltar facilmente apresentam ramos não está pronto para o próximo lançamento) é implementado no Git repo em si, com o gitworkflow (uma palavra, ilustrada aqui ).
Veja mais em rocketraman/gitworkflow. O histórico de fazer isso vs Desenvolvimento baseado em tronco é anotado nos comentários e discussões deste artigo por Adam Dymitruk .

https://github.com/rocketraman/gitworkflow/raw/master/docs/images/topicgraduation.png

(fonte: Gitworkflow: uma cartilha orientada a tarefas )

Nota: nesse fluxo de trabalho distribuído, você pode confirmar, sempre que quiser, e enviar para um ramo pessoal algum WIP (Work In Progress) sem problemas: você poderá reorganizar (git rebase) seus commit antes de torná-los parte de um branch de recurso.


Resposta original (outubro de 2008, há mais de 10 anos)

Tudo depende da natureza seqüencial do seu gerenciamento de lançamento

Primeiro, tudo no seu porta-mal é realmente para o próximo lançamento ? Você pode descobrir que algumas das funções desenvolvidas atualmente são:

  • muito complicado e ainda precisa ser refinado
  • não está pronto a tempo
  • interessante, mas não para este próximo lançamento

Nesse caso, o tronco deve conter todos os esforços de desenvolvimento atuais, mas um ramo de versão definido antes do próximo lançamento pode servir como ramo de consolidação, no qual apenas o código apropriado (validado para o próximo lançamento) é mesclado e corrigido durante a fase de homologação, e finalmente congelado à medida que entra em produção.

Quando se trata de código de produção, você também precisa gerenciar suas ramificações de patch , mantendo em mente que:

  • o primeiro conjunto de patches pode realmente começar antes do primeiro lançamento em produção (o que significa que você sabe que entrará em produção com alguns bugs que não podem ser corrigidos a tempo, mas você pode iniciar o trabalho desses bugs em uma ramificação separada)
  • os outros ramos de remendo terão o luxo de começar com um rótulo de produção bem definido

Quando se trata de ramificação de desenvolvimento, você pode ter um tronco, a menos que tenha outros esforços de desenvolvimento que precisa fazer em paralelo, como:

  • refatoração maciça
  • teste de uma nova biblioteca técnica que pode mudar a maneira como você chama as coisas em outras classes
  • início de um novo ciclo de lançamento, no qual mudanças importantes na arquitetura precisam ser incorporadas.

Agora, se o seu ciclo de desenvolvimento-versão é muito seqüencial, você pode simplesmente seguir as outras respostas: um tronco e várias ramificações de versão. Isso funciona para pequenos projetos em que todo o desenvolvimento certamente vai para a próxima versão e pode ser congelado e servir como ponto de partida para a ramificação da versão, onde as correções podem ocorrer. Esse é o processo nominal, mas assim que você tiver um projeto mais complexo ... não será mais suficiente.


Para responder ao comentário de Ville M.:

  • lembre-se de que ramificação do desenvolvedor não significa 'uma ramificação por desenvolvedor' (o que provocaria 'loucura de mesclagem', pois cada desenvolvedor precisaria mesclar o trabalho de outro para ver / obter seu trabalho), mas uma ramificação de desenvolvedor por desenvolvimento esforço.
  • Quando esses esforços precisam ser mesclados de volta ao tronco (ou qualquer outro ramo "principal" ou de liberação que você definir), este é o trabalho do desenvolvedor, não - repito, NÃO - o gerente do SC (que não saberia resolver qualquer fusão conflitante). O líder do projeto pode supervisionar a mesclagem, o que significa garantir que ela comece / termine no prazo.
  • quem você escolher para realmente fazer a mesclagem, o mais importante é:
    • ter testes de unidade e / ou ambiente de montagem no qual você pode implantar / testar o resultado da mesclagem.
    • ter definido uma marca antes do início da mesclagem para poder voltar ao estado anterior se a mesclagem se provar muito complexa ou bastante demorada para resolver.
VonC
fonte
1
@ Adam Obrigado pela edição e desculpe-me por não definir a atribuição adequada mais cedo.
VonC 15/01
Ha! Não se preocupe. Você fez muito pela comunidade aqui, dificilmente é o culpado por qualquer coisa. Estou feliz por termos pessoas como você trabalhando tanto para os benefícios de todos ao redor do mundo!
Adam Dymitruk 16/01
43

Nós usamos:

  • ramo de desenvolvimento exclusivamente

até que o projeto esteja quase completo, ou estamos criando uma versão importante (por exemplo, demonstração do produto, versão de apresentação), então (regularmente) ramificamos nossa ramificação de desenvolvimento atual para:

  • ramo de lançamento

Nenhum novo recurso entra no ramo de lançamento. Somente bugs importantes são corrigidos na ramificação de lançamento e o código para corrigi-los é reintegrado à ramificação de desenvolvimento.

O processo de duas partes com um ramo de desenvolvimento e estável (release) facilita muito a vida para nós, e não acredito que possamos melhorar qualquer parte dele, introduzindo mais ramos. Cada ramificação também possui seu próprio processo de compilação, o que significa que, a cada dois minutos, um novo processo de compilação é gerado; portanto, após um check-in de código, temos um novo executável de todas as versões e ramificações de compilação em cerca de meia hora.

Ocasionalmente, também temos filiais para um único desenvolvedor trabalhando em uma tecnologia nova e não comprovada ou criando uma prova de conceito. Mas geralmente isso é feito apenas se as alterações afetarem muitas partes da base de código. Isso acontece, em média, a cada 3-4 meses e esse ramo geralmente é reintegrado (ou descartado) dentro de um mês ou dois.

Geralmente eu não gosto da idéia de todo desenvolvedor trabalhar em seu próprio ramo, porque você "pula e vai diretamente para o inferno da integração". Eu recomendaria fortemente contra isso. Se você tem uma base de código comum, todos devem trabalhar juntos. Isso torna os desenvolvedores mais cautelosos em relação aos seus check-ins e, com a experiência, todo codificador sabe quais alterações estão potencialmente quebrando a compilação e, portanto, os testes são mais rigorosos nesses casos.

Na pergunta inicial do check-in:

Se você precisar fazer check-in apenas de CÓDIGO PERFEITO , na verdade nada deverá ser feito check-in. Nenhum código é perfeito e, para o controle de qualidade verificar e testá-lo, ele precisa estar no ramo de desenvolvimento para que um novo executável possa ser construído.

Para nós, isso significa que, uma vez que um recurso é concluído e testado pelo desenvolvedor, é feito o check-in. Pode até ser verificado se houver erros conhecidos (não fatais), mas, nesse caso, as pessoas que seriam afetadas pelo bug serão geralmente informado. O código incompleto e em andamento também pode ser verificado, mas apenas se não causar efeitos negativos óbvios, como falhas ou interrupção da funcionalidade existente.

De vez em quando, um inevitável código combinado e verificação de dados tornarão o programa inutilizável até que o novo código seja criado. O mínimo que fazemos é adicionar uma "Aguardar construção" no comentário do check-in e / ou enviar um e-mail.

steffenj
fonte
1
Eu votei. Isso é semelhante ao que fazemos, mas estamos fazendo todas as alterações no desenvolvimento e tentando mesclar essas correções no ramo de lançamento. Não está funcionando. No entanto, acho que se mudarmos para fazer todas as correções de bugs no lançamento e nos unirmos ao desenvolvimento, isso será corrigido.
TheCodeMonk
2
Você implica que o controle de qualidade testa o ramo de desenvolvimento, não seria melhor se eles verificassem o ramo de lançamento? Dessa forma, eu poderia começar a trabalhar no meu novo recurso maluco que não será incluído na próxima versão (e pode quebrar algo), enquanto nesse período o controle de qualidade testará o código existente sem que meu novo recurso interfira?
BornToCode
15

Pelo que vale, é assim que fazemos.

A maior parte do desenvolvimento é realizada no porta-malas, embora recursos experimentais ou coisas que possam danificar o sistema tendam a obter seu próprio ramo. Isso funciona muito bem, pois significa que todo desenvolvedor sempre tem a versão mais recente de tudo em sua cópia de trabalho.

Isso significa que é importante manter o tronco em boas condições de funcionamento, pois é perfeitamente possível quebrá-lo completamente. Na prática, isso não acontece com frequência e raramente é um problema significativo.

Para uma versão de produção, ramificamos o tronco, paramos de adicionar novos recursos e trabalhamos na correção de erros e no teste do ramo (mesclando-se regularmente ao tronco) até que esteja pronto para o lançamento. Nesse ponto, fazemos uma mesclagem final no tronco para garantir que tudo esteja lá e, em seguida, liberamos.

A manutenção pode ser executada na ramificação de liberação, conforme necessário, e essas correções podem ser facilmente mescladas novamente ao tronco.

Não afirmo que seja um sistema perfeito (e ainda tem alguns buracos - não acho que nosso gerenciamento de versões seja um processo suficientemente apertado), mas funciona bem o suficiente.

Dan
fonte
funciona bem o suficiente e também é bastante simples para desenvolvedores de código apenas não-vcs-druids.
Matthieu
12

Por que ninguém ainda menciona isso? Um modelo de ramificação Git bem-sucedido .

É para mim o melhor modelo de ramificação!

Se seu projeto for pequeno, não use o tempo todo todos os diferentes ramos (talvez você possa pular ramos de recursos para recursos pequenos). Mas, caso contrário, é a maneira de fazê-lo!

modelo de ramificação

Philippe
fonte
4
Sim, exceto se muitas vezes um pouco complexo / completo, como ilustra scottchacon.com/2011/08/31/github-flow.html .
VonC
Concordo. Entenda o modelo de ramificação do git flow (que resolve muitos problemas) e simplifique-o para atender às suas necessidades. E o fluxo do GitHub exige implantação rápida, mas isso nem sempre é possível ... É mais ou menos o modelo de ramificação que usamos no meu projeto (para simplificar as coisas), mas enfrentamos um caso em que adoraríamos usar o modelo de fluxo de git: (e isso nos colocou em uma grande merda :(
Philippe
1
Do meu ponto de vista, isso basicamente copia tudo o que o VonC disse aproximadamente um ano antes (em sua resposta), mas de uma maneira mais detalhada e com belas fotos!
Cregox
6

Código de desenvolvimento nas ramificações, código ativo marcado no tronco.

Não é necessário que exista uma regra "comprometer apenas código perfeito" - qualquer coisa que o desenvolvedor perca deve ser identificada em quatro locais: revisão de código, teste de ramificação, teste de regressão e teste final de controle de qualidade.

Aqui está uma explicação passo a passo mais detalhada:

  1. Faça todo o desenvolvimento em uma filial, comprometendo-se regularmente à medida que avança.
  2. Código independente Revisão das alterações quando todo o desenvolvimento estiver concluído.
  3. Em seguida, passe a ramificação para Teste.
  4. Após a conclusão do teste de ramificação, mescle o código na ramificação Release Candidate.
  5. O ramo Release Candidate é testado por regressão após cada mesclagem individual.
  6. O teste final de controle de qualidade e UA foi realizado no RC após a fusão de todos os ramos de desenvolvimento.
  7. Depois que o controle de qualidade e o UAT forem aprovados, mescle a ramificação de liberação na ramificação MAIN / TRUNK.
  8. Por fim, marque o tronco nesse ponto e implante-o no Live.
Peter Boughton
fonte
3

Resolvemos esse problema separando completamente o código de produção (o tronco principal) do código de desenvolvimento (onde cada desenvolvedor tem sua própria ramificação).

Nenhum código é permitido no código de produção antes de ser verificado minuciosamente (pelo controle de qualidade e pelos revisores de código).

Dessa forma, não há confusão sobre qual código funciona, é sempre o ramo principal.

Grimtron
fonte
2

Ah, sim - outra coisa - mantemos o código de não produção (ou seja, aquele que NUNCA será lançado - por exemplo, scripts de ferramentas, utilitários de teste) no cvs HEAD. Normalmente, ele precisa ser claramente marcado para que ninguém o "acidentalmente" o libere.

MarkR
fonte
2
talvez isso seja melhor como uma edição da resposta anterior.
Richard Harrison
6
Ele disse CVS. :-)
Até
2

Desenvolvemos um tronco que é ramificado a cada duas semanas e colocado em produção. Apenas bugs críticos são corrigidos na ramificação, o resto pode esperar mais duas semanas.

Para o tronco, a única regra é que um commit não deve quebrar nada. Para gerenciar o código wip e o código não testado, adicionamos apenas as declarações apropriadas para facilitar a ativação e desativação.

Basicamente, seria possível ramificar o tronco a qualquer momento e colocá-lo em produção.

John Nilsson
fonte
0

Uso git e tenho 2 ramos: master e maint

  • mestre - código de desenvolvimento
  • maint - código de produção

quando eu liberar o código para produção, eu marcá-lo e eu fundir mestre para maint ramo. Eu sempre implantar a partir maint ramo. Patches do ramo de desenvolvimento Eu os escolho para manter o branch e implantar patches.

Vitalie
fonte
0

Temos uma ramificação "release" que contém o que está atualmente em produção ou será implantada em breve (já passou na maioria do controle de qualidade)

Cada projeto, ou em alguns casos outra unidade, tem seu próprio ramo, que é ramificado a partir do lançamento.

As alterações são confirmadas, pelos desenvolvedores do projeto, na própria ramificação do projeto. Periodicamente, a liberação é mesclada novamente em uma ramificação de desenvolvimento.

Depois que todos os pacotes de trabalho na filial tiverem controle de qualidade (teste de unidade, teste do sistema, revisão de código, revisão de controle de qualidade etc.), a filial será mesclada na filial de lançamento. As novas construções são construídas a partir da ramificação de lançamento e a validação final ocorre nessa versão.

O processo está basicamente bom até que um problema seja descoberto após a conclusão da mesclagem. Se um WP ficar "travado" após ser mesclado, ele reterá tudo até ser corrigido (não podemos fazer outra versão até que a versão travada seja lançada).


Também é um pouco flexível - uma mudança muito trivial pode acontecer diretamente no ramo de lançamento, se estiver sendo lançada em uma escala de tempo muito curta (como um ou dois dias).

Se uma alteração fosse colocada diretamente na produção por algum motivo (um problema crítico de produção que afetasse o cliente que exigia uma alteração imediata do código para corrigir), essas alterações seriam colocadas novamente em BRANCH_RELEASE. Isso quase nunca acontece.

MarkR
fonte
0

Depende do projeto. Nosso código da web é verificado de maneira bastante consistente, enquanto o código do aplicativo é verificado apenas se for compilado. Percebi que isso é bem parecido com o modo como lançamos as coisas. O material da Web aumenta sempre que possível, enquanto os aplicativos atingem um prazo final. Eu não vi uma perda de qualidade em nenhum dos métodos.

icco
fonte