Estratégia de ramificação do subversion
Estratégia de ramificação do Subversion
Um dos recursos dos sistemas de controle de versão é a capacidade de isolar as alterações em uma linha separada de desenvolvimento. Esta linha é conhecida como um ramo. As ramificações geralmente são usadas para testar novos recursos sem atrapalhar a linha principal de desenvolvimento com erros e bugs do compilador. Assim que o novo recurso estiver estável o suficiente, o branch de desenvolvimento é mesclado de volta ao branch principal (trunk).
Outro recurso dos sistemas de controle de versão é a capacidade de marcar revisões específicas (por exemplo, uma versão de lançamento), para que você possa, a qualquer momento, recriar uma determinada construção ou ambiente. Esse processo é conhecido como marcação.
O Subversion não possui comandos especiais para ramificação ou marcação, mas usa as chamadas “cópias baratas”. Cópias baratas são semelhantes aos links físicos no Unix, o que significa que, em vez de fazer uma cópia completa no repositório, um link interno é criado, apontando para uma árvore / revisão específica. Como resultado, as ramificações e tags são muito rápidas de criar e quase não ocupam espaço extra no repositório.
Criando um Branch ou Tag.
Se você importou seu projeto com a estrutura de diretório recomendada, criar uma versão de ramificação ou tag é muito simples:
Figura 4.52. A caixa de diálogo Filial / Tag.
Selecione a pasta em sua cópia de trabalho que você deseja copiar para um ramo ou tag, em seguida, selecione o comando TortoiseSVN → Branch / Tag. .
O URL de destino padrão da nova filial será o URL de origem no qual sua cópia de trabalho é baseada. Você precisará editar esse URL para o novo caminho da sua filial / tag. Então, ao invés de.
você pode agora usar algo parecido.
Se você não conseguir lembrar a convenção de nomenclatura usada na última vez, clique no botão à direita para abrir o navegador do repositório para poder visualizar a estrutura do repositório existente.
pastas intermediárias.
Quando você especifica o URL de destino, todas as pastas até o último já devem existir ou você receberá uma mensagem de erro. No exemplo acima, a URL svn. collab / repos / ProjectName / tags / deve existir para criar a tag Release_1.10.
No entanto, se você quiser criar uma ramificação / tag para uma URL que tenha pastas intermediárias que ainda não existem, marque a opção Criar pastas intermediárias na parte inferior da caixa de diálogo. Se essa opção estiver ativada, todas as pastas intermediárias serão criadas automaticamente.
Observe que esta opção está desativada por padrão para evitar erros de digitação. Por exemplo, se você digitar o URL de destino como svn. collab / repos / NomeProjeto / Tags / Release_1.10 em vez de svn. collab / repos / NomeDoProjeto / tags / Release_1.10, você receberá um erro com a opção desabilitada, mas com a opção ativada, uma pasta Tags seria criada automaticamente e você acabaria com uma pasta Tags e uma tag de pasta.
Agora você tem que selecionar a fonte da cópia. Aqui você tem três opções:
A nova ramificação é copiada diretamente no repositório da revisão HEAD. Nenhum dado precisa ser transferido de sua cópia de trabalho e a ramificação é criada muito rapidamente.
Revisão específica no repositório.
A nova ramificação é copiada diretamente no repositório, mas você pode escolher uma revisão mais antiga. Isso é útil se você esqueceu de criar uma tag quando liberou seu projeto na semana passada. Se não conseguir lembrar o número de revisão, clique no botão à direita para mostrar o registro de revisão e selecione o número de revisão a partir dele. Novamente, nenhum dado é transferido de sua cópia de trabalho e a ramificação é criada muito rapidamente.
A nova ramificação é uma cópia idêntica da sua cópia de trabalho local. Se você atualizou alguns arquivos para uma revisão mais antiga no seu WC, ou se você fez alterações locais, é exatamente isso que vai para a cópia. Naturalmente, esse tipo de tag complexo pode envolver a transferência de dados do seu WC de volta para o repositório, se ele ainda não existir.
Se você deseja que sua cópia de trabalho seja alternada para a ramificação recém-criada automaticamente, use a caixa de seleção Alternar cópia de trabalho para nova ramificação / marcação. Mas se você fizer isso, primeiro certifique-se de que sua cópia de trabalho não contenha modificações. Em caso afirmativo, essas alterações serão mescladas no WC da filial quando você alternar.
Se sua cópia de trabalho tiver outros projetos incluídos com as propriedades svn: externals, essas externas serão listadas na parte inferior da caixa de diálogo branch / tag. Para cada externo, o caminho de destino e o URL de origem são mostrados.
Se você quiser ter certeza de que a nova tag está sempre em um estado consistente, verifique todas as externas para ter suas revisões marcadas. Se você não checar os externos e aqueles externos apontam para uma revisão HEAD que pode mudar no futuro, o check out da nova tag irá verificar que a revisão HEAD do externo e sua tag podem não ser mais compiladas. Por isso, é sempre uma boa ideia definir os elementos externos para uma revisão explícita ao criar uma tag.
Os externos são automaticamente fixados na revisão HEAD atual ou na revisão BASE da cópia de trabalho, dependendo da origem da ramificação / tag:
Estratégia de ramificação do Subversion
Há muitos usos diferentes para ramificação e svn merge, e esta seção descreve os mais comuns.
O controle de versão é mais frequentemente usado para desenvolvimento de software, então aqui está uma rápida olhada em dois dos padrões mais comuns de ramificação / fusão usados por equipes de programadores. Se você não estiver usando o Subversion para desenvolvimento de software, fique à vontade para pular esta seção. Se você é um desenvolvedor de software que usa o controle de versão pela primeira vez, preste muita atenção, pois esses padrões geralmente são considerados práticas recomendadas por pessoas experientes. Esses processos não são específicos do Subversion; eles são aplicáveis a qualquer sistema de controle de versão. Ainda assim, pode ser útil vê-los descritos em termos do Subversion.
Liberar filiais.
A maioria dos softwares tem um ciclo de vida típico: codificar, testar, liberar, repetir. Existem dois problemas com este processo. Primeiro, os desenvolvedores precisam continuar criando novos recursos, enquanto as equipes de garantia de qualidade levam tempo para testar versões supostamente estáveis do software. Novo trabalho não pode parar enquanto o software é testado. Em segundo lugar, a equipe quase sempre precisa suportar versões mais antigas do software; Se um bug for descoberto no código mais recente, é mais provável que exista também nas versões lançadas, e os clientes desejarão obter essa correção de bug sem ter que esperar por uma nova versão importante.
Aqui é onde o controle de versão pode ajudar. O procedimento típico é assim:
Os desenvolvedores cometem todo o novo trabalho no tronco. As alterações do dia a dia são confirmadas no / trunk: novos recursos, correções de erros e assim por diante.
O tronco é copiado para uma ramificação "release". Quando a equipe acha que o software está pronto para ser lançado (digamos, uma versão 1.0), o / trunk pode ser copiado para /branches/1.0.
As equipes continuam a trabalhar em paralelo. Uma equipe inicia testes rigorosos do ramo de lançamento, enquanto outra equipe continua um novo trabalho (digamos, para a versão 2.0) em / trunk. Se os bugs forem descobertos em qualquer local, as correções serão transportadas para frente e para trás conforme necessário. Em algum momento, no entanto, até esse processo é interrompido. A ramificação está congelada para testes finais antes de uma liberação.
O ramo é marcado e liberado. Quando o teste estiver concluído, /branches/1.0 é copiado para /tags/1.0.0 como um instantâneo de referência. A tag é empacotada e liberada para os clientes.
A filial é mantida ao longo do tempo. Enquanto o trabalho continua em / trunk para a versão 2.0, correções de bugs continuam sendo portadas de / trunk para /branches/1.0. Quando consertos de bugs suficientes se acumulam, o gerenciamento pode decidir fazer uma versão 1.0.1: /branches/1.0 é copiado para /tags/1.0.1, e a tag é empacotada e liberada.
Todo esse processo é repetido à medida que o software amadurece: quando o trabalho do 2.0 é concluído, um novo branch de release 2.0 é criado, testado, marcado e, eventualmente, liberado. Depois de alguns anos, o repositório acaba com um número de ramificações de liberação em "manutenção" e um número de tags representando as versões finais enviadas.
Ramos de recursos.
Um branch de recursos é o tipo de branch que tem sido o exemplo dominante neste capítulo (aquele em que você está trabalhando enquanto Sally continua trabalhando / trunk). É uma ramificação temporária criada para trabalhar em uma alteração complexa sem interferir na estabilidade de / trunk. Ao contrário das ramificações do release (que talvez precisem ser suportadas para sempre), filiais de recursos nascem, são usadas por um tempo, mescladas de volta ao tronco e, finalmente, excluídas. Eles têm uma extensão finita de utilidade.
Mais uma vez, as políticas do projeto variam muito no que diz respeito exatamente quando é apropriado criar um ramo de recursos. Alguns projetos nunca usam ramificações de recursos: os commits para / trunk são gratuitos. A vantagem deste sistema é que é simples: ninguém precisa aprender sobre ramificação ou fusão. A desvantagem é que o código de tronco é muitas vezes instável ou inutilizável. Outros projetos usam ramificações ao extremo: nenhuma alteração é confirmada diretamente no tronco. Até mesmo as mudanças mais triviais são criadas em uma ramificação de curta duração, cuidadosamente revisadas e mescladas ao tronco. Em seguida, a ramificação é excluída. Este sistema garante um tronco excepcionalmente estável e utilizável em todos os momentos, mas ao custo de sobrecarga de processo tremenda.
A maioria dos projetos usa uma abordagem intermediária. Eles geralmente insistem que / trunk compile e passem os testes de regressão a todo momento. Um ramo de recurso é necessário apenas quando uma alteração requer um grande número de confirmações desestabilizadoras. Uma boa regra é fazer essa pergunta: se o desenvolvedor trabalhou por dias em isolamento e depois cometeu a grande alteração de uma só vez (para que / trunk nunca fosse desestabilizado), seria uma mudança muito grande para revisar? Se a resposta a essa pergunta for sim, a mudança deve ser desenvolvida em um ramo de recurso. Conforme o desenvolvedor confirma alterações incrementais na ramificação, elas podem ser facilmente revisadas pelos colegas.
Finalmente, há a questão de como manter um ramo de recursos em sincronia com o tronco à medida que o trabalho progride. Como mencionamos anteriormente, há um grande risco de trabalhar em um ramo por semanas ou meses; as trocas de tronco podem continuar a chegar, até o ponto em que as duas linhas de desenvolvimento diferem tanto que pode se tornar um pesadelo tentar mesclar o ramo de volta ao tronco.
É melhor evitar essa situação mesclando regularmente as alterações do tronco na filial. Crie uma política: uma vez por semana, mescle as alterações de tronco da última semana na agência.
Quando você estiver pronto para mesclar o ramo de recurso sincronizado de volta ao tronco, comece fazendo uma mesclagem final das alterações de tronco mais recentes na ramificação. Quando isso for feito, as versões mais recentes da ramificação e do tronco são absolutamente idênticas, exceto pelas alterações na ramificação. Você então mescla de volta com a opção --reintegrate:
Outra maneira de pensar sobre esse padrão é que sua sincronização semanal de tronco para filial é análoga à execução do svn update em uma cópia de trabalho, enquanto a etapa final de mesclagem é análoga à execução de svn commit de uma cópia de trabalho. Afinal, o que mais é uma cópia de trabalho, mas um ramo privado muito superficial? É um ramo capaz de armazenar apenas uma alteração por vez.
Capítulo 4. Branching and Merging.
¥ ђђ ›еђеЉЎжњ¬ (É no tronco que um cavalheiro trabalha).
Ramificação e fusão são aspectos fundamentais do controle de versão, simples o suficiente para explicar conceitualmente, mas oferecendo complexidade e nuances suficientes para merecer seu próprio capítulo neste livro. Aqui, apresentaremos as idéias gerais por trás dessas operações, bem como a abordagem um pouco exclusiva do Subversion a elas. Se você não está familiarizado com os conceitos básicos do Subversion (encontrado no Capítulo 1, Conceitos Fundamentais), recomendamos que você faça isso antes de ler este capítulo.
Você está lendo Controle de Versão com o Subversion (para o Subversion 1.7), por Ben Collins-Sussman, Brian W. Fitzpatrick e C. Michael Pilato.
Estratégia de ramificação do Subversion
Se você não "rebase" (Fig. A), você acabará entregando todo o conjunto de alterações toda vez e mesclará efetivamente as alterações que já foram mescladas. Mas se você fizer o rebase (Fig. B) - que é mesclar o tronco para o ramo de desenvolvimento imediatamente, então o subversion é capaz de saber a diferença.
svn switch svn: // servidor / trunk svn: // servidor / branches / trunk / dev1.
Faça uma mudança e comprometa-a.
svn commit - m "Adicionado um diretório b"
Volte para o tronco e puxe as mudanças do ramo dev.
svn merge svn: // servidor / trunk svn: // servidor / ramificações / trunk / dev1.
svn commit - m "empurrou o dev1 para o trunk"
Agora volte para continuar a trabalhar no ramo de desenvolvimento.
Aí vem a solução muito importante para o desconhecimento do ramo de desenvolvimento sobre o que aconteceu. Você simplesmente mescla o tronco no ramo de desenvolvimento antes de continuar trabalhando.
E agora é seguro continuar usando o ramo de desenvolvimento - como você faria no git, Mercurial ou ClearCase.
Estratégia de ramificação do Subversion
Qual é a melhor estratégia de ramificação a ser usada quando você deseja fazer integração contínua?
Libertar Ramificação: desenvolver no tronco, manter um ramo para cada lançamento. Recurso ramificação: desenvolver cada recurso em um ramo separado, apenas mesclar uma vez estável.
Faz sentido usar essas duas estratégias juntas? Como em, você ramifica para cada lançamento, mas você também ramifica para grandes recursos? Uma dessas estratégias combina melhor com a integração contínua? O uso de integração contínua faria sentido ao usar um tronco instável?
11 respostas.
A resposta depende do tamanho da equipe e da qualidade do controle de origem e da capacidade de mesclar conjuntos de mudanças complexos corretamente. Por exemplo, no controle de fonte de ramificação completa como CVS ou SVN, a fusão pode ser difícil e você pode estar melhor com o primeiro modelo, enquanto se estiver usando um sistema mais complexo como o IBM ClearCase e com um tamanho maior de equipe, modelo ou uma combinação dos dois.
Eu pessoalmente separaria o modelo de ramificação de feições, onde cada característica principal é desenvolvida em uma ramificação separada, com sub-ramificações de tarefas para cada modificação feita pelo desenvolvedor individual. À medida que os recursos se estabilizam, eles são mesclados ao tronco, que você mantém razoavelmente estável e passando em todos os testes de regressão o tempo todo. À medida que você se aproxima do final de seu ciclo de lançamento e todos os ramos de recursos se mesclam, você estabiliza e ramifica uma ramificação do sistema de lançamento na qual você faz apenas correções de bugs de estabilidade e backports necessários, enquanto o tronco é usado para desenvolvimento da próxima versão e você novamente ramificar para novos ramos de recurso. 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) em grandes mudanças e mesclagens de recursos, os ramos de recursos são desenvolvimento rápido com integração contínua e sub-ramificações de tarefas individuais atualizado a partir do ramo de recursos para manter todos trabalhando no mesmo recurso em sincronia, sem afetar outras equipes que trabalham em diferentes recursos.
Ao mesmo tempo, você tem através do histórico um conjunto de releases, onde você pode fornecer backports, suporte e correções de bugs para seus clientes que, por qualquer motivo, permanecem em versões anteriores de seu produto ou até mesmo na última versão lançada. Tal como acontece com o tronco, você não configura a integração contínua nos ramos de lançamento, eles são cuidadosamente integrados ao passarem por todos os testes de regressão e outro controle de qualidade do release.
Se, por algum motivo, dois recursos forem co-dependentes e precisarem de alterações feitos um pelo outro, você poderá considerar desenvolver ambos no mesmo ramo de recursos ou exigir que os recursos mescle regularmente partes estáveis do código no tronco e, em seguida, atualize as alterações tronco para troca de código entre os ramos do tronco. Ou, se você precisar isolar esses dois recursos de outros, poderá criar uma ramificação comum na qual ramificará essas ramificações de recurso e poderá usá-la para trocar códigos entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de código-fonte sem ramificações esparsas e capacidade de mesclagem adequada como CVS ou SVN, o que tornaria todo esse modelo um pesadelo para configurar, gerenciar e integrar.
Recurso ramificando seu caminho para a grandeza.
Ou tarefa ramificando seu caminho até lá. Ou libere ramificações. Você escolhe.
Quase todos os sistemas de controle de versão atualmente suportam ramificações - linhas independentes de trabalho que derivam de uma base de código central. Dependendo do sistema de controle de versão, o ramo principal pode ser chamado de mestre, principal, padrão ou tronco. Os desenvolvedores podem criar suas próprias ramificações a partir da linha de código principal e trabalhar de forma independente ao lado dela.
Por que se preocupar com ramificação?
A ramificação permite que equipes de desenvolvedores colaborem facilmente dentro de uma base de código central. Quando um desenvolvedor cria uma ramificação, o sistema de controle de versão cria uma cópia da base de código naquele momento. As alterações na agência não afetam outros desenvolvedores da equipe. Isso é uma coisa boa, obviamente, porque os recursos em desenvolvimento podem criar instabilidade, o que seria altamente prejudicial se todo o trabalho estivesse acontecendo na linha de código principal. Mas as filiais não precisam viver em confinamento solitário. Os desenvolvedores podem facilmente remover as alterações de outros desenvolvedores para colaborar em recursos e garantir que sua ramificação privada não seja muito distante do mestre.
Os branches não são bons apenas para o trabalho de recursos. Filiais podem isolar a equipe de importantes mudanças arquiteturais, como a atualização de estruturas, bibliotecas comuns etc.
Três estratégias de ramificação para equipes ágeis.
Os modelos de ramificação geralmente diferem entre as equipes e são assunto de muito debate na comunidade de software. Um grande tema é quanto trabalho deve permanecer em um branch antes de ser mesclado de volta ao master.
Liberar ramificação.
Liberar ramificação refere-se à ideia de que uma liberação está contida inteiramente dentro de uma ramificação. Isso significa que, no final do ciclo de desenvolvimento, o gerente de lançamento criará uma ramificação do mestre (por exemplo, & ldquo; 1.1 filial de desenvolvimento & rdquo;). Todas as alterações para a versão 1.1 precisam ser aplicadas duas vezes: uma vez para a ramificação 1.1 e, em seguida, para a linha de código principal. Trabalhar com duas filiais é um trabalho extra para a equipe e é fácil esquecer de se mesclar a ambas as filiais. As ramificações de versão podem ser difíceis e difíceis de gerenciar, já que muitas pessoas estão trabalhando no mesmo ramo. Todos nós sentimos a dor de ter que mesclar muitas mudanças diferentes em um único ramo. Se você deve fazer um branch de release, crie o branch o mais próximo possível do release atual.
O lançamento de ramificações é uma parte importante do suporte a softwares com versão no mercado. Um único produto pode ter vários ramos de liberação (por exemplo, 1.1, 1.2, 2.0) para suportar o desenvolvimento de sustentação. Lembre-se de que as alterações nas versões anteriores (por exemplo, 1.1) podem precisar ser mescladas em filiais de liberação posteriores (por exemplo, 1.2, 2.0). Confira nosso webinar abaixo para saber mais sobre o gerenciamento de filiais de lançamento com o Git.
Ramificação de recursos.
Os ramos de funcionalidades são frequentemente associados a flags de funcionalidades & ndash; & quot; alterna & quot; que habilitam ou desabilitam um recurso dentro do produto. Isso facilita a implantação do código no mestre e no controle quando o recurso é ativado, facilitando a implantação inicial do código antes que o recurso seja exposto aos usuários finais.
Outro benefício de sinalizadores de recursos é que o código pode permanecer dentro da compilação, mas inativo enquanto está em desenvolvimento. Se algo der errado quando o recurso estiver habilitado, um administrador do sistema poderá reverter o sinalizador de recurso e voltar a um bom estado conhecido, em vez de precisar implantar uma nova compilação.
Tarefa Ramificação.
Na Atlassian, nos concentramos em um fluxo de trabalho de ramificação por tarefa. Cada organização tem uma maneira natural de dividir o trabalho em tarefas individuais dentro de um rastreador de problemas, como o Jira Software. Questões, em seguida, torna-se ponto de contato central da equipe para esse trabalho. A ramificação de tarefas, também conhecida como ramificação de problemas, conecta diretamente esses problemas ao código-fonte. Cada problema é implementado em sua própria ramificação com a chave de problema incluída no nome da ramificação. É fácil ver qual código implementa o problema: basta procurar a chave de problema no nome da ramificação. Com esse nível de transparência, é mais fácil aplicar alterações específicas na ramificação de lançamento legado em execução ou mestre.
Como os centros ágeis em torno de histórias de usuários, os ramos de tarefas combinam bem com o desenvolvimento ágil. Cada história de usuário (ou correção de bug) reside em sua própria ramificação, facilitando a visualização de quais problemas estão em andamento e quais estão prontos para serem lançados. Para um mergulho profundo na ramificação de tarefas (às vezes chamada de ramificação de problema ou branch-por-issue), pegue um pouco de pipoca e confira a gravação do webinar abaixo - um dos mais populares de todos os tempos.
Agora encontre o gêmeo maligno da ramificação: a fusão.
Todos sofremos a dor de tentar integrar vários ramos em uma solução sensata. Tradicionalmente, sistemas centralizados de controle de versão, como o Subversion, fizeram da fusão uma operação muito dolorosa. Mas os sistemas de controle de versão mais recentes, como o Git e o Mercurial, adotam uma abordagem diferente para rastrear versões de arquivos que residem em diferentes filiais.
As ramificações tendem a ter vida curta, facilitando a mesclagem e a flexibilidade na base de código. Entre a capacidade de mesclar freqüências e automaticamente ramificações como parte da integração contínua (CI) e o fato de que as ramificações de vida curta simplesmente contêm menos alterações, & quot; mesclar o inferno & quot; Torna-se uma coisa do passado para as equipes que usam Git e Mercurial.
É isso que torna a ramificação de tarefas tão incrível!
Valide, valide, valide.
Um sistema de controle de versão só pode ir tão longe ao afetar o resultado de uma mesclagem. Testes automatizados e integração contínua também são críticos. A maioria dos servidores de CI pode colocar automaticamente novos ramos em teste, reduzindo drasticamente o número de "surpresas" na junção final do upstream e ajudando a manter a linha de código principal estável.
Há muitos usos diferentes para ramificação e svn merge, e esta seção descreve os mais comuns.
O controle de versão é mais frequentemente usado para desenvolvimento de software, então aqui está uma rápida olhada em dois dos padrões mais comuns de ramificação / fusão usados por equipes de programadores. Se você não estiver usando o Subversion para desenvolvimento de software, fique à vontade para pular esta seção. Se você é um desenvolvedor de software que usa o controle de versão pela primeira vez, preste muita atenção, pois esses padrões geralmente são considerados práticas recomendadas por pessoas experientes. Esses processos não são específicos do Subversion; eles são aplicáveis a qualquer sistema de controle de versão. Ainda assim, pode ser útil vê-los descritos em termos do Subversion.
Liberar filiais.
A maioria dos softwares tem um ciclo de vida típico: codificar, testar, liberar, repetir. Existem dois problemas com este processo. Primeiro, os desenvolvedores precisam continuar criando novos recursos, enquanto as equipes de garantia de qualidade levam tempo para testar versões supostamente estáveis do software. Novo trabalho não pode parar enquanto o software é testado. Em segundo lugar, a equipe quase sempre precisa suportar versões mais antigas do software; Se um bug for descoberto no código mais recente, é mais provável que exista também nas versões lançadas, e os clientes desejarão obter essa correção de bug sem ter que esperar por uma nova versão importante.
Aqui é onde o controle de versão pode ajudar. O procedimento típico é assim:
Os desenvolvedores cometem todo o novo trabalho no tronco. As alterações do dia a dia são confirmadas no / trunk: novos recursos, correções de erros e assim por diante.
O tronco é copiado para uma ramificação "release". Quando a equipe acha que o software está pronto para ser lançado (digamos, uma versão 1.0), o / trunk pode ser copiado para /branches/1.0.
As equipes continuam a trabalhar em paralelo. Uma equipe inicia testes rigorosos do ramo de lançamento, enquanto outra equipe continua um novo trabalho (digamos, para a versão 2.0) em / trunk. Se os bugs forem descobertos em qualquer local, as correções serão transportadas para frente e para trás conforme necessário. Em algum momento, no entanto, até esse processo é interrompido. A ramificação está congelada para testes finais antes de uma liberação.
O ramo é marcado e liberado. Quando o teste estiver concluído, /branches/1.0 é copiado para /tags/1.0.0 como um instantâneo de referência. A tag é empacotada e liberada para os clientes.
A filial é mantida ao longo do tempo. Enquanto o trabalho continua em / trunk para a versão 2.0, correções de bugs continuam sendo portadas de / trunk para /branches/1.0. Quando consertos de bugs suficientes se acumulam, o gerenciamento pode decidir fazer uma versão 1.0.1: /branches/1.0 é copiado para /tags/1.0.1, e a tag é empacotada e liberada.
Todo esse processo é repetido à medida que o software amadurece: quando o trabalho do 2.0 é concluído, um novo branch de release 2.0 é criado, testado, marcado e, eventualmente, liberado. Depois de alguns anos, o repositório acaba com um número de ramificações de liberação em "manutenção" e um número de tags representando as versões finais enviadas.
Ramos de recursos.
Um branch de recursos é o tipo de branch que tem sido o exemplo dominante neste capítulo (aquele em que você está trabalhando enquanto Sally continua trabalhando / trunk). É uma ramificação temporária criada para trabalhar em uma alteração complexa sem interferir na estabilidade de / trunk. Ao contrário das ramificações do release (que talvez precisem ser suportadas para sempre), filiais de recursos nascem, são usadas por um tempo, mescladas de volta ao tronco e, finalmente, excluídas. Eles têm uma extensão finita de utilidade.
Mais uma vez, as políticas do projeto variam muito no que diz respeito exatamente quando é apropriado criar um ramo de recursos. Alguns projetos nunca usam ramificações de recursos: os commits para / trunk são gratuitos. A vantagem deste sistema é que é simples: ninguém precisa aprender sobre ramificação ou fusão. A desvantagem é que o código de tronco é muitas vezes instável ou inutilizável. Outros projetos usam ramificações ao extremo: nenhuma alteração é confirmada diretamente no tronco. Até mesmo as mudanças mais triviais são criadas em uma ramificação de curta duração, cuidadosamente revisadas e mescladas ao tronco. Em seguida, a ramificação é excluída. Este sistema garante um tronco excepcionalmente estável e utilizável em todos os momentos, mas ao custo de sobrecarga de processo tremenda.
A maioria dos projetos usa uma abordagem intermediária. Eles geralmente insistem que / trunk compile e passem os testes de regressão a todo momento. Um ramo de recurso é necessário apenas quando uma alteração requer um grande número de confirmações desestabilizadoras. Uma boa regra é fazer essa pergunta: se o desenvolvedor trabalhou por dias em isolamento e depois cometeu a grande alteração de uma só vez (para que / trunk nunca fosse desestabilizado), seria uma mudança muito grande para revisar? Se a resposta a essa pergunta for sim, a mudança deve ser desenvolvida em um ramo de recurso. Conforme o desenvolvedor confirma alterações incrementais na ramificação, elas podem ser facilmente revisadas pelos colegas.
Finalmente, há a questão de como manter um ramo de recursos em sincronia com o tronco à medida que o trabalho progride. Como mencionamos anteriormente, há um grande risco de trabalhar em um ramo por semanas ou meses; as trocas de tronco podem continuar a chegar, até o ponto em que as duas linhas de desenvolvimento diferem tanto que pode se tornar um pesadelo tentar mesclar o ramo de volta ao tronco.
É melhor evitar essa situação mesclando regularmente as alterações do tronco na filial. Crie uma política: uma vez por semana, mescle as alterações de tronco da última semana na agência.
Quando você estiver pronto para mesclar o ramo de recurso sincronizado de volta ao tronco, comece fazendo uma mesclagem final das alterações de tronco mais recentes na ramificação. Quando isso for feito, as versões mais recentes da ramificação e do tronco são absolutamente idênticas, exceto pelas alterações na ramificação. Você então mescla de volta com a opção --reintegrate:
Outra maneira de pensar sobre esse padrão é que sua sincronização semanal de tronco para filial é análoga à execução do svn update em uma cópia de trabalho, enquanto a etapa final de mesclagem é análoga à execução de svn commit de uma cópia de trabalho. Afinal, o que mais é uma cópia de trabalho, mas um ramo privado muito superficial? É um ramo capaz de armazenar apenas uma alteração por vez.
Capítulo 4. Branching and Merging.
¥ ђђ ›еђеЉЎжњ¬ (É no tronco que um cavalheiro trabalha).
Ramificação e fusão são aspectos fundamentais do controle de versão, simples o suficiente para explicar conceitualmente, mas oferecendo complexidade e nuances suficientes para merecer seu próprio capítulo neste livro. Aqui, apresentaremos as idéias gerais por trás dessas operações, bem como a abordagem um pouco exclusiva do Subversion a elas. Se você não está familiarizado com os conceitos básicos do Subversion (encontrado no Capítulo 1, Conceitos Fundamentais), recomendamos que você faça isso antes de ler este capítulo.
Você está lendo Controle de Versão com o Subversion (para o Subversion 1.7), por Ben Collins-Sussman, Brian W. Fitzpatrick e C. Michael Pilato.
Estratégia de ramificação do Subversion
Se você não "rebase" (Fig. A), você acabará entregando todo o conjunto de alterações toda vez e mesclará efetivamente as alterações que já foram mescladas. Mas se você fizer o rebase (Fig. B) - que é mesclar o tronco para o ramo de desenvolvimento imediatamente, então o subversion é capaz de saber a diferença.
svn switch svn: // servidor / trunk svn: // servidor / branches / trunk / dev1.
Faça uma mudança e comprometa-a.
svn commit - m "Adicionado um diretório b"
Volte para o tronco e puxe as mudanças do ramo dev.
svn merge svn: // servidor / trunk svn: // servidor / ramificações / trunk / dev1.
svn commit - m "empurrou o dev1 para o trunk"
Agora volte para continuar a trabalhar no ramo de desenvolvimento.
Aí vem a solução muito importante para o desconhecimento do ramo de desenvolvimento sobre o que aconteceu. Você simplesmente mescla o tronco no ramo de desenvolvimento antes de continuar trabalhando.
E agora é seguro continuar usando o ramo de desenvolvimento - como você faria no git, Mercurial ou ClearCase.
Estratégia de ramificação do Subversion
Qual é a melhor estratégia de ramificação a ser usada quando você deseja fazer integração contínua?
Libertar Ramificação: desenvolver no tronco, manter um ramo para cada lançamento. Recurso ramificação: desenvolver cada recurso em um ramo separado, apenas mesclar uma vez estável.
Faz sentido usar essas duas estratégias juntas? Como em, você ramifica para cada lançamento, mas você também ramifica para grandes recursos? Uma dessas estratégias combina melhor com a integração contínua? O uso de integração contínua faria sentido ao usar um tronco instável?
11 respostas.
A resposta depende do tamanho da equipe e da qualidade do controle de origem e da capacidade de mesclar conjuntos de mudanças complexos corretamente. Por exemplo, no controle de fonte de ramificação completa como CVS ou SVN, a fusão pode ser difícil e você pode estar melhor com o primeiro modelo, enquanto se estiver usando um sistema mais complexo como o IBM ClearCase e com um tamanho maior de equipe, modelo ou uma combinação dos dois.
Eu pessoalmente separaria o modelo de ramificação de feições, onde cada característica principal é desenvolvida em uma ramificação separada, com sub-ramificações de tarefas para cada modificação feita pelo desenvolvedor individual. À medida que os recursos se estabilizam, eles são mesclados ao tronco, que você mantém razoavelmente estável e passando em todos os testes de regressão o tempo todo. À medida que você se aproxima do final de seu ciclo de lançamento e todos os ramos de recursos se mesclam, você estabiliza e ramifica uma ramificação do sistema de lançamento na qual você faz apenas correções de bugs de estabilidade e backports necessários, enquanto o tronco é usado para desenvolvimento da próxima versão e você novamente ramificar para novos ramos de recurso. 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) em grandes mudanças e mesclagens de recursos, os ramos de recursos são desenvolvimento rápido com integração contínua e sub-ramificações de tarefas individuais atualizado a partir do ramo de recursos para manter todos trabalhando no mesmo recurso em sincronia, sem afetar outras equipes que trabalham em diferentes recursos.
Ao mesmo tempo, você tem através do histórico um conjunto de releases, onde você pode fornecer backports, suporte e correções de bugs para seus clientes que, por qualquer motivo, permanecem em versões anteriores de seu produto ou até mesmo na última versão lançada. Tal como acontece com o tronco, você não configura a integração contínua nos ramos de lançamento, eles são cuidadosamente integrados ao passarem por todos os testes de regressão e outro controle de qualidade do release.
Se, por algum motivo, dois recursos forem co-dependentes e precisarem de alterações feitos um pelo outro, você poderá considerar desenvolver ambos no mesmo ramo de recursos ou exigir que os recursos mescle regularmente partes estáveis do código no tronco e, em seguida, atualize as alterações tronco para troca de código entre os ramos do tronco. Ou, se você precisar isolar esses dois recursos de outros, poderá criar uma ramificação comum na qual ramificará essas ramificações de recurso e poderá usá-la para trocar códigos entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de código-fonte sem ramificações esparsas e capacidade de mesclagem adequada como CVS ou SVN, o que tornaria todo esse modelo um pesadelo para configurar, gerenciar e integrar.
Recurso ramificando seu caminho para a grandeza.
Ou tarefa ramificando seu caminho até lá. Ou libere ramificações. Você escolhe.
Quase todos os sistemas de controle de versão atualmente suportam ramificações - linhas independentes de trabalho que derivam de uma base de código central. Dependendo do sistema de controle de versão, o ramo principal pode ser chamado de mestre, principal, padrão ou tronco. Os desenvolvedores podem criar suas próprias ramificações a partir da linha de código principal e trabalhar de forma independente ao lado dela.
Por que se preocupar com ramificação?
A ramificação permite que equipes de desenvolvedores colaborem facilmente dentro de uma base de código central. Quando um desenvolvedor cria uma ramificação, o sistema de controle de versão cria uma cópia da base de código naquele momento. As alterações na agência não afetam outros desenvolvedores da equipe. Isso é uma coisa boa, obviamente, porque os recursos em desenvolvimento podem criar instabilidade, o que seria altamente prejudicial se todo o trabalho estivesse acontecendo na linha de código principal. Mas as filiais não precisam viver em confinamento solitário. Os desenvolvedores podem facilmente remover as alterações de outros desenvolvedores para colaborar em recursos e garantir que sua ramificação privada não seja muito distante do mestre.
Os branches não são bons apenas para o trabalho de recursos. Filiais podem isolar a equipe de importantes mudanças arquiteturais, como a atualização de estruturas, bibliotecas comuns etc.
Três estratégias de ramificação para equipes ágeis.
Os modelos de ramificação geralmente diferem entre as equipes e são assunto de muito debate na comunidade de software. Um grande tema é quanto trabalho deve permanecer em um branch antes de ser mesclado de volta ao master.
Liberar ramificação.
Liberar ramificação refere-se à ideia de que uma liberação está contida inteiramente dentro de uma ramificação. Isso significa que, no final do ciclo de desenvolvimento, o gerente de lançamento criará uma ramificação do mestre (por exemplo, & ldquo; 1.1 filial de desenvolvimento & rdquo;). Todas as alterações para a versão 1.1 precisam ser aplicadas duas vezes: uma vez para a ramificação 1.1 e, em seguida, para a linha de código principal. Trabalhar com duas filiais é um trabalho extra para a equipe e é fácil esquecer de se mesclar a ambas as filiais. As ramificações de versão podem ser difíceis e difíceis de gerenciar, já que muitas pessoas estão trabalhando no mesmo ramo. Todos nós sentimos a dor de ter que mesclar muitas mudanças diferentes em um único ramo. Se você deve fazer um branch de release, crie o branch o mais próximo possível do release atual.
O lançamento de ramificações é uma parte importante do suporte a softwares com versão no mercado. Um único produto pode ter vários ramos de liberação (por exemplo, 1.1, 1.2, 2.0) para suportar o desenvolvimento de sustentação. Lembre-se de que as alterações nas versões anteriores (por exemplo, 1.1) podem precisar ser mescladas em filiais de liberação posteriores (por exemplo, 1.2, 2.0). Confira nosso webinar abaixo para saber mais sobre o gerenciamento de filiais de lançamento com o Git.
Ramificação de recursos.
Os ramos de funcionalidades são frequentemente associados a flags de funcionalidades & ndash; & quot; alterna & quot; que habilitam ou desabilitam um recurso dentro do produto. Isso facilita a implantação do código no mestre e no controle quando o recurso é ativado, facilitando a implantação inicial do código antes que o recurso seja exposto aos usuários finais.
Outro benefício de sinalizadores de recursos é que o código pode permanecer dentro da compilação, mas inativo enquanto está em desenvolvimento. Se algo der errado quando o recurso estiver habilitado, um administrador do sistema poderá reverter o sinalizador de recurso e voltar a um bom estado conhecido, em vez de precisar implantar uma nova compilação.
Tarefa Ramificação.
Na Atlassian, nos concentramos em um fluxo de trabalho de ramificação por tarefa. Cada organização tem uma maneira natural de dividir o trabalho em tarefas individuais dentro de um rastreador de problemas, como o Jira Software. Questões, em seguida, torna-se ponto de contato central da equipe para esse trabalho. A ramificação de tarefas, também conhecida como ramificação de problemas, conecta diretamente esses problemas ao código-fonte. Cada problema é implementado em sua própria ramificação com a chave de problema incluída no nome da ramificação. É fácil ver qual código implementa o problema: basta procurar a chave de problema no nome da ramificação. Com esse nível de transparência, é mais fácil aplicar alterações específicas na ramificação de lançamento legado em execução ou mestre.
Como os centros ágeis em torno de histórias de usuários, os ramos de tarefas combinam bem com o desenvolvimento ágil. Cada história de usuário (ou correção de bug) reside em sua própria ramificação, facilitando a visualização de quais problemas estão em andamento e quais estão prontos para serem lançados. Para um mergulho profundo na ramificação de tarefas (às vezes chamada de ramificação de problema ou branch-por-issue), pegue um pouco de pipoca e confira a gravação do webinar abaixo - um dos mais populares de todos os tempos.
Agora encontre o gêmeo maligno da ramificação: a fusão.
Todos sofremos a dor de tentar integrar vários ramos em uma solução sensata. Tradicionalmente, sistemas centralizados de controle de versão, como o Subversion, fizeram da fusão uma operação muito dolorosa. Mas os sistemas de controle de versão mais recentes, como o Git e o Mercurial, adotam uma abordagem diferente para rastrear versões de arquivos que residem em diferentes filiais.
As ramificações tendem a ter vida curta, facilitando a mesclagem e a flexibilidade na base de código. Entre a capacidade de mesclar freqüências e automaticamente ramificações como parte da integração contínua (CI) e o fato de que as ramificações de vida curta simplesmente contêm menos alterações, & quot; mesclar o inferno & quot; Torna-se uma coisa do passado para as equipes que usam Git e Mercurial.
É isso que torna a ramificação de tarefas tão incrível!
Valide, valide, valide.
Um sistema de controle de versão só pode ir tão longe ao afetar o resultado de uma mesclagem. Testes automatizados e integração contínua também são críticos. A maioria dos servidores de CI pode colocar automaticamente novos ramos em teste, reduzindo drasticamente o número de "surpresas" na junção final do upstream e ajudando a manter a linha de código principal estável.
Qual é a melhor estratégia de ramificação a ser usada quando você deseja fazer integração contínua?
Libertar Ramificação: desenvolver no tronco, manter um ramo para cada lançamento. Recurso ramificação: desenvolver cada recurso em um ramo separado, apenas mesclar uma vez estável.
Faz sentido usar essas duas estratégias juntas? Como em, você ramifica para cada lançamento, mas você também ramifica para grandes recursos? Uma dessas estratégias combina melhor com a integração contínua? O uso de integração contínua faria sentido ao usar um tronco instável?
11 respostas.
A resposta depende do tamanho da equipe e da qualidade do controle de origem e da capacidade de mesclar conjuntos de mudanças complexos corretamente. Por exemplo, no controle de fonte de ramificação completa como CVS ou SVN, a fusão pode ser difícil e você pode estar melhor com o primeiro modelo, enquanto se estiver usando um sistema mais complexo como o IBM ClearCase e com um tamanho maior de equipe, modelo ou uma combinação dos dois.
Eu pessoalmente separaria o modelo de ramificação de feições, onde cada característica principal é desenvolvida em uma ramificação separada, com sub-ramificações de tarefas para cada modificação feita pelo desenvolvedor individual. À medida que os recursos se estabilizam, eles são mesclados ao tronco, que você mantém razoavelmente estável e passando em todos os testes de regressão o tempo todo. À medida que você se aproxima do final de seu ciclo de lançamento e todos os ramos de recursos se mesclam, você estabiliza e ramifica uma ramificação do sistema de lançamento na qual você faz apenas correções de bugs de estabilidade e backports necessários, enquanto o tronco é usado para desenvolvimento da próxima versão e você novamente ramificar para novos ramos de recurso. 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) em grandes mudanças e mesclagens de recursos, os ramos de recursos são desenvolvimento rápido com integração contínua e sub-ramificações de tarefas individuais atualizado a partir do ramo de recursos para manter todos trabalhando no mesmo recurso em sincronia, sem afetar outras equipes que trabalham em diferentes recursos.
Ao mesmo tempo, você tem através do histórico um conjunto de releases, onde você pode fornecer backports, suporte e correções de bugs para seus clientes que, por qualquer motivo, permanecem em versões anteriores de seu produto ou até mesmo na última versão lançada. Tal como acontece com o tronco, você não configura a integração contínua nos ramos de lançamento, eles são cuidadosamente integrados ao passarem por todos os testes de regressão e outro controle de qualidade do release.
Se, por algum motivo, dois recursos forem co-dependentes e precisarem de alterações feitos um pelo outro, você poderá considerar desenvolver ambos no mesmo ramo de recursos ou exigir que os recursos mescle regularmente partes estáveis do código no tronco e, em seguida, atualize as alterações tronco para troca de código entre os ramos do tronco. Ou, se você precisar isolar esses dois recursos de outros, poderá criar uma ramificação comum na qual ramificará essas ramificações de recurso e poderá usá-la para trocar códigos entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de código-fonte sem ramificações esparsas e capacidade de mesclagem adequada como CVS ou SVN, o que tornaria todo esse modelo um pesadelo para configurar, gerenciar e integrar.
Recurso ramificando seu caminho para a grandeza.
Ou tarefa ramificando seu caminho até lá. Ou libere ramificações. Você escolhe.
Quase todos os sistemas de controle de versão atualmente suportam ramificações - linhas independentes de trabalho que derivam de uma base de código central. Dependendo do sistema de controle de versão, o ramo principal pode ser chamado de mestre, principal, padrão ou tronco. Os desenvolvedores podem criar suas próprias ramificações a partir da linha de código principal e trabalhar de forma independente ao lado dela.
Por que se preocupar com ramificação?
A ramificação permite que equipes de desenvolvedores colaborem facilmente dentro de uma base de código central. Quando um desenvolvedor cria uma ramificação, o sistema de controle de versão cria uma cópia da base de código naquele momento. As alterações na agência não afetam outros desenvolvedores da equipe. Isso é uma coisa boa, obviamente, porque os recursos em desenvolvimento podem criar instabilidade, o que seria altamente prejudicial se todo o trabalho estivesse acontecendo na linha de código principal. Mas as filiais não precisam viver em confinamento solitário. Os desenvolvedores podem facilmente remover as alterações de outros desenvolvedores para colaborar em recursos e garantir que sua ramificação privada não seja muito distante do mestre.
Os branches não são bons apenas para o trabalho de recursos. Filiais podem isolar a equipe de importantes mudanças arquiteturais, como a atualização de estruturas, bibliotecas comuns etc.
Três estratégias de ramificação para equipes ágeis.
Os modelos de ramificação geralmente diferem entre as equipes e são assunto de muito debate na comunidade de software. Um grande tema é quanto trabalho deve permanecer em um branch antes de ser mesclado de volta ao master.
Liberar ramificação.
Liberar ramificação refere-se à ideia de que uma liberação está contida inteiramente dentro de uma ramificação. Isso significa que, no final do ciclo de desenvolvimento, o gerente de lançamento criará uma ramificação do mestre (por exemplo, & ldquo; 1.1 filial de desenvolvimento & rdquo;). Todas as alterações para a versão 1.1 precisam ser aplicadas duas vezes: uma vez para a ramificação 1.1 e, em seguida, para a linha de código principal. Trabalhar com duas filiais é um trabalho extra para a equipe e é fácil esquecer de se mesclar a ambas as filiais. As ramificações de versão podem ser difíceis e difíceis de gerenciar, já que muitas pessoas estão trabalhando no mesmo ramo. Todos nós sentimos a dor de ter que mesclar muitas mudanças diferentes em um único ramo. Se você deve fazer um branch de release, crie o branch o mais próximo possível do release atual.
O lançamento de ramificações é uma parte importante do suporte a softwares com versão no mercado. Um único produto pode ter vários ramos de liberação (por exemplo, 1.1, 1.2, 2.0) para suportar o desenvolvimento de sustentação. Lembre-se de que as alterações nas versões anteriores (por exemplo, 1.1) podem precisar ser mescladas em filiais de liberação posteriores (por exemplo, 1.2, 2.0). Confira nosso webinar abaixo para saber mais sobre o gerenciamento de filiais de lançamento com o Git.
Ramificação de recursos.
Os ramos de funcionalidades são frequentemente associados a flags de funcionalidades & ndash; & quot; alterna & quot; que habilitam ou desabilitam um recurso dentro do produto. Isso facilita a implantação do código no mestre e no controle quando o recurso é ativado, facilitando a implantação inicial do código antes que o recurso seja exposto aos usuários finais.
Outro benefício de sinalizadores de recursos é que o código pode permanecer dentro da compilação, mas inativo enquanto está em desenvolvimento. Se algo der errado quando o recurso estiver habilitado, um administrador do sistema poderá reverter o sinalizador de recurso e voltar a um bom estado conhecido, em vez de precisar implantar uma nova compilação.
Tarefa Ramificação.
Na Atlassian, nos concentramos em um fluxo de trabalho de ramificação por tarefa. Cada organização tem uma maneira natural de dividir o trabalho em tarefas individuais dentro de um rastreador de problemas, como o Jira Software. Questões, em seguida, torna-se ponto de contato central da equipe para esse trabalho. A ramificação de tarefas, também conhecida como ramificação de problemas, conecta diretamente esses problemas ao código-fonte. Cada problema é implementado em sua própria ramificação com a chave de problema incluída no nome da ramificação. É fácil ver qual código implementa o problema: basta procurar a chave de problema no nome da ramificação. Com esse nível de transparência, é mais fácil aplicar alterações específicas na ramificação de lançamento legado em execução ou mestre.
Como os centros ágeis em torno de histórias de usuários, os ramos de tarefas combinam bem com o desenvolvimento ágil. Cada história de usuário (ou correção de bug) reside em sua própria ramificação, facilitando a visualização de quais problemas estão em andamento e quais estão prontos para serem lançados. Para um mergulho profundo na ramificação de tarefas (às vezes chamada de ramificação de problema ou branch-por-issue), pegue um pouco de pipoca e confira a gravação do webinar abaixo - um dos mais populares de todos os tempos.
Agora encontre o gêmeo maligno da ramificação: a fusão.
Todos sofremos a dor de tentar integrar vários ramos em uma solução sensata. Tradicionalmente, sistemas centralizados de controle de versão, como o Subversion, fizeram da fusão uma operação muito dolorosa. Mas os sistemas de controle de versão mais recentes, como o Git e o Mercurial, adotam uma abordagem diferente para rastrear versões de arquivos que residem em diferentes filiais.
As ramificações tendem a ter vida curta, facilitando a mesclagem e a flexibilidade na base de código. Entre a capacidade de mesclar freqüências e automaticamente ramificações como parte da integração contínua (CI) e o fato de que as ramificações de vida curta simplesmente contêm menos alterações, & quot; mesclar o inferno & quot; Torna-se uma coisa do passado para as equipes que usam Git e Mercurial.
É isso que torna a ramificação de tarefas tão incrível!
Valide, valide, valide.
Um sistema de controle de versão só pode ir tão longe ao afetar o resultado de uma mesclagem. Testes automatizados e integração contínua também são críticos. A maioria dos servidores de CI pode colocar automaticamente novos ramos em teste, reduzindo drasticamente o número de "surpresas" na junção final do upstream e ajudando a manter a linha de código principal estável.
Comments
Post a Comment