Trabalhando em uma ramificação com dependência de outra ramificação que está sendo revisada

52

Como o git ajuda a lidar com o cenário abaixo:

Eu tenho uma tarefa dividida em duas partes: tarefa de back-end e tarefa frontend. Eu faço uma solicitação pull para mesclar as alterações de back-end e aguardo a fusão (e o feedback de endereço). Enquanto aguardo, não posso trabalhar nas alterações do frontend porque depende das alterações de backend e elas ainda não estão disponíveis na ramificação principal.

Qual é a melhor maneira de inserir alterações nas ramificações de front-end do ramo de alterações de back-end enquanto elas ainda estão sendo revisadas?

    
por sul4bh 28.06.2017 / 02:18
fonte

7 respostas

40

Eu tenho esse problema também às vezes. O Git é muito flexível. Aqui está uma maneira de fazer isso.

Sua primeira filial featureA está pronta para revisão.

Sua segunda ramificação featureB está em desenvolvimento e depende do código na ramificação featureA .

Mesclar a ramificação featureA na ramificação featureB .

Se você fizer alterações na ramificação featureA , deverá mesclar a ramificação featureA na ramificação featureB novamente para incorporar as alterações.

Você também deve certificar-se de mesclar featureA no tronco principal primeiro, caso contrário, quando você mesclar featureB no tronco principal, você mesclará inadvertidamente featureA . Quando featureA for mesclado no tronco principal, você poderá se livrar da ramificação featureA , já que featureB depende apenas do tronco principal.

Eu prefiro quando minhas ramificações de recursos não dependem uma da outra, mas às vezes elas acontecem e você precisa rolar com ela.

    
por 28.06.2017 / 02:43
fonte
28

Você já tem uma ramificação da qual depende todo o seu ramo de recursos e que continua mudando. É chamado master .

A maneira típica de um branch de recursos ficar em sincronia com master é ficar no topo dele. Quando master muda, você normalmente git fetch origin master:master && git rebase master no diretório de trabalho da sua filial.

Você pode fazer a mesma coisa com outra ramificação de recurso: continue buscando e rebaixando em cima dela.

Se, por algum motivo, você precisar mover suas alterações para um ramo diferente, poderá selecionar os seus commits, que nunca serão misturados aos commits de outras filiais.

    
por 28.06.2017 / 05:17
fonte
21

Aguarde, pule a fusão

Para essa abordagem, você não deseja mesclar seu feature_a em feature_b repetidamente.

Rebasing foi mencionado em outras respostas, mas apenas para rebase de coisas em master . O que você quer fazer no seu caso é:

  • Inicie seu feature_b de feature_a , por exemplo:

    git checkout feature_a
    git checkout -b feature_b
    
  • Sempre que feature_a for alterado enquanto aguarda a mesclagem em master , você rebase feature_b nele:

    ... commit something onto feature_a ...
    git checkout feature_b
    git rebase feature_a
    
  • Por fim, assim que feature_a for mesclado em master , você simplesmente obterá a nova master e a rebase feature_a na última vez:

    git checkout master
    git pull origin master
    git checkout feature_b
    git rebase --onto master feature_a feature_b
    

    Esta rebase final irá enxertar todas as confirmações que estão pendentes da feature_a commit (que agora é irrelevante à medida que foi mesclada em master ) diretamente para master . Seu feature_b agora é uma ramificação simples e padrão que vai direto de master .

EDIT: inspirado nos comentários, um pouco direcionado: se você precisar fazer alguma alteração que afete ambos recursos, certifique-se de fazer isso em feature_a (e então rebase conforme mostrado ). Não faça em dois commits diferentes em ambos os branches, mesmo que seja tentador; como feature_a faz parte do histórico de feature_b , ter a única alteração em dois commits diferentes será semanticamente errada e possivelmente levar a conflitos ou "ressurreições" de código indesejado, posteriormente.

    
por 28.06.2017 / 21:31
fonte
5

Neste caso, onde a tarefa frontend tem uma dependência crítica do código backend, e você quer começar a trabalhar no frontend antes que o backend seja finalizado e aceito no master, eu simplesmente começaria a tarefa do frontend como um branch de recursos vindo fora da ramificação do backend, em vez de ramificar o frontend no master.

Um ramo de recurso que vive o suficiente precisa mesclar as alterações do mestre ocasionalmente (para ter certeza de reconciliar quaisquer conflitos de mesclagem ou semântica como parte do trabalho de desenvolvimento no ramo de recursos, em vez de fazer parte da "revisão, qa , merge-to-master "processo). Então você faz isso no seu front end branch, e quando o trabalho de backend foi aceito para master, você vai ter pequenas alterações que foram feitas para o backend como parte de sua revisão / aceitação automaticamente, pela mesma rota que você obtenha quaisquer outras alterações de código no mestre.

Se a ramificação de back-end precisar de muito mais trabalho e continuar a mudar ao longo de um período de tempo antes ser mesclada ao master (diga se problemas maiores forem encontrados durante a revisão), você provavelmente desejaria realizar mesclagens periódicas diretamente da ramificação de back-end para a ramificação de front-end (para que você não continue baseando todo o seu trabalho de frontend em código de backend obsoleto). Isso é fácil se você for o único desenvolvedor fazendo os dois recursos (desde que você saiba se faz algumas alterações importantes), mas mesmo se ambos os recursos acabarem sendo trabalhados em paralelo por desenvolvedores diferentes, ele deve estar bem; você só tem que ficar em comunicação (o que você precisaria de qualquer maneira, se você está trabalhando em tarefas paralelas onde alguém tem uma dependência crítica do outro).

Se acontecer que toda a ramificação do backend precisa ser abandonada e nunca será mesclada (parece que isso seria um negócio muito importante que raramente aconteceria), então você escolhe os seus commits para um novo branch saindo do mestre sem o trabalho de backend, ou você aplica commits reversos que removem todo o código de backend para o branch frontend. Mas, como posso ver, é mais provável pausar o trabalho do frontend até que você descubra o que vai substituir o backend que está descartando e depois decida o que fazer.

    
por 28.06.2017 / 07:50
fonte
2

Eu não vejo o problema aqui.

Você já tem isso sempre com sua ramificação master , que continua mudando enquanto os recursos são desenvolvidos e depois mesclados.

Assim, no seu exemplo concreto, você primeiro cria a ramificação feature_xxx_backend e desenvolve as alterações de back-end. Quando isso for feito, a filial estará pronta para revisar e será mesclada em master quando a revisão estiver concluída.

Então, simplesmente inicie outra ramificação, feature_yyy_frontend . Você provavelmente desejará se ramificar diretamente de feature_xxx_backend , para que você tenha essas mudanças já no seu branch. Em seguida, simplesmente desenvolva o recurso frontend como se o branch fosse master .

Quando a ramificação feature_xxx_backend muda, por ex. porque há coisas que surgem durante a revisão que precisam ser endereçadas, simplesmente faça essas alterações e mescle-as na ramificação feature_yyy_frontend . Então continue no ramo frontend.

Quando a revisão da ramificação de back-end for concluída, ela será mesclada em master . Neste ponto, seria aconselhável rebase a ramificação feature_yyy_frontend para master , para que os revisores precisem apenas revisar as novas mudanças que essa ramificação contribui para master e não é necessário revisar novamente as alterações feitas no back-end (que já foram aprovadas).

Isso também pode ser feito quando você tem dois, três ou mais ramos dependentes. Se você tem dois ramos de características dos quais você depende, faça um branch derivado que tenha ambos os recursos mesclados. Ramifique a partir daí, desenvolva o terceiro recurso, mescle os dois ramos ao longo do caminho quando cada um deles mudar. Quando os dois recursos estiverem prontos e mesclados ao branch derivado, faça o rebase para isso, ou se eles forem mesclados ao master, rebase para master.

Rebasing (como sugerido acima) é realmente poderoso e ajuda a manter um registro limpo das alterações, tornando as revisões muito mais fáceis.

    
por 28.06.2017 / 12:56
fonte
2

Como o Polygnome mencionou, você pode realmente mesclar sua ramificação de frontend com sua ramificação de backend em vez dos mestres. Mesmo com a configuração atual da ramificação que você tem agora, você pode simplesmente fazer:

git checkout frontend
git merge backend

ou simplesmente

git merge backend frontend

Tenha em mente que, se as alterações de back-end não forem aceitas e for necessário mais trabalho, você precisará mesclar as atualizações do back-end para o front-end para evitar conflitos. Uma vez que as alterações são aceitas no master, você pode rebase seu frontend no master para se livrar das commits de mesclagem de back-end.

Tecnicamente, você também pode fazer tudo com rebase, mas isso irá atrapalhar o histórico de commits do seu frontend. De onde eu venho, isso é considerado uma má prática. YMMV

    
por 28.06.2017 / 15:30
fonte
0

A maioria das respostas aqui descreve corretamente o processo de mesclar as mudanças da segunda ramificação para a primeira, mas elas não abordam como minimizar a quantidade de conflitos que você pode precisar resolver.

Sempre que você tiver dois conjuntos de grandes alterações que deseja analisar individualmente (como featureA e featureB ), crie um PR que NÃO esteja destinado a ser mesclado, mas reúna o feedback inicial em um PoC de featureA .

As pessoas poderão analisá-lo rapidamente (é apenas uma PoC), e o objetivo é validar o design ou a abordagem geral.

Em seguida, você pode continuar trabalhando no recurso A, criar uma solicitação de recebimento e ramificar e trabalhar no recurso B.

A grande diferença é que agora você pode esperar que featureA não mude radicalmente: o design e a abordagem já foram validados. A revisão de código e as alterações necessárias podem ser sutis e locais, em vez de "woops, você precisa de uma abordagem diferente". Isso minimizará a quantidade de trabalho que você precisa fazer posteriormente para mesclar o código featureB on featureA , independentemente do método escolhido.

    
por 03.07.2017 / 19:58
fonte

Tags