git - ignorando confirmações específicas ao mesclar

200

Estou usando o Git há cerca de um ano e acho fantástico, mas comecei uma segunda versão do projeto e iniciei uma nova ramificação para ele. Estou lutando um pouco com a melhor maneira de lidar com as coisas daqui para frente.

Eu tenho dois ramos chamados dizer master10 (para v1) e master20 (para v2). Venho fazendo correções de erros na v1 na ramificação master10 e desenvolvendo coisas novas da master20. Sempre que faço uma correção de erro, mesclo-a na v2, verificando master20 e fazendo git merge master10. Por enquanto, tudo bem.

Agora, no entanto, fiz uma alteração na v1 que não quero na v2, mas quero continuar mesclando outras correções. Como eu digo ao Git para ignorar esse commit específico (ou um intervalo de commits), mas que daqui para frente eu ainda quero mesclar outras correções de bugs.

Eu pensei que git rebasepoderia ser o que eu precisava, mas li o documento e minha cabeça quase explodiu.

Eu acho que o que eu quero é algo como um comando "git sync" que diga ao git que agora duas ramificações estão sincronizadas e, no futuro, apenas mesclam as confirmações a partir deste ponto de sincronização.

Qualquer ajuda apreciada.

Brad Robinson
fonte

Respostas:

289

Se você deseja mesclar a maioria, mas nem todos os commits no ramo "maint" para "master", por exemplo, você pode fazer isso. Requer algum trabalho ---- como mencionado acima, o caso de uso usual é mesclar tudo de um ramo - mas às vezes acontece que você fez uma alteração em uma versão de lançamento que não deve ser integrada novamente (talvez esse código seja já foi substituído no master), então como você representa isso? Aqui vai ...

Então, vamos supor que a maint teve 5 alterações aplicadas e uma delas (maint ~ 3) não deve ser mesclada novamente no master, embora todas as outras devam ser. Você faz isso em três estágios: na verdade, mescla tudo antes desse, diga ao git para marcar maint ~ 3 como mesclado, mesmo quando não estiver, e depois mesclar o resto. A mágica é:

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

O primeiro comando mescla tudo antes sua manutenção problemática se comprometer com o mestre. A mensagem padrão do log de mesclagem explicará que você está mesclando "branch 'maint' (parte inicial)".

O segundo comando mescla a manutenção problemática ~ 3 commit, mas a opção "-s our" diz ao git para usar uma "estratégia de mesclagem" especial que, de fato, funciona simplesmente mantendo a árvore na qual você está mesclando e ignorando o commit (s). ) você está mesclando completamente. Mas ainda faz um novo commit de mesclagem com HEAD e maint ~ 3 como os pais, então o gráfico de revisão agora diz que maint ~ 3 é mesclado. Então, na verdade, você provavelmente deseja usar a opção -m para 'git merge' também, para explicar que esse commit ~ 3 está realmente sendo ignorado!

O comando final simplesmente mescla o restante da manutenção (manutenção ~ 2..maint) no mestre, para que todos sejam sincronizados novamente.

araqnid
fonte
5
Eu acho que se você precisar adiar a mesclagem desse commit, você terá poucas opções além de ignorá-lo (mesclar -s nossos) e depois aplicá-lo usando o comando cherry-pick. Uma vez que o commit está acessível a partir do master, ele não pode ser mesclado novamente. Evitar mesclar a mesma alteração duas vezes é um dos principais objetivos do git.
Araqnid 08/04/09
3
Em relação ao seu exemplo de sub-ramo: Suspeito que, depois de mesclar o sub-ramo, você esteja exatamente na mesma situação que após a segunda etapa do meu post. Criar ramificações adicionais não faz diferença para os relacionamentos de confirmação.
Araqnid 08/04/09
5
Apenas por interesse, se você deseja apenas omitir uma alteração, por que você não faria apenas uma mesclagem e depois reverteria essa alteração, em vez de realizar três mesclagens? Isso resultaria em menos conjuntos de alterações confirmados no repositório e um histórico mais explícito.
Mark Booth
3
Muitas vezes, é mais fácil nomear explicitamente os commits. Então você só precisa exibir o log de git do ramo a-ser-mesclada e observe os hashes do commit que não devem ser fundidas e o anterior - em vez de commits contando ...
zwirbeltier
14
@ MarkBooth: O commit que você deseja pular pode estar em um grande conflito com o ramo que você deseja mesclar. É mais fácil ignorá-lo em vez de consertar os conflitos e reverter essa mudança e consertá
los
39

O IMHO, a coisa mais lógica a fazer, é mesclar tudo e usar o git revert (commit_you_dont_want) para removê-lo .

Exemplo:

git merge master
git revert 12345678

Se você possui vários confirmações "a ignorar" ou deseja editar a mensagem de reversão:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

Então seu histórico pode parecer com:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

Se você tiver conflitos envolvendo SOMENTE esses "para ignorar" confirmações, você pode usar:

git merge master -X ours

Portanto, sua versão persistirá sobre a outra. Mesmo sem mensagens de erro, você ainda pode "reverter" essas confirmações indesejadas, pois elas podem ter outras alterações que não entraram em conflito e você ainda não as deseja.

Se houver conflitos envolvendo NÃO SOMENTE as confirmações de "ignorar", você deve resolvê-los manualmente e provavelmente precisará resolvê-los novamente durante a reversão.

Alexandre T.
fonte
2
Se você deseja mesclar posteriormente os commits revertidos no ramo em questão, o Git ainda os ignorará?
Anriëtte Myburgh
@ AnriëtteMyburgh Você pode reverter os compromissos de reversão para depois fundi-los em algo que você realmente não pode fazer tão facilmente com a estratégia "fundir é nosso".
Lily Chung
Obrigado, é exatamente isso que eu precisava: alguns commits mais antigos em um ramo de recursos que eu não queria no master e um monte que eu queria no master. Legal e Limpo.
Vale Trujillo
17

As confirmações incluem ascendência. Você não pode mesclar uma confirmação sem mesclar confirmações anteriores.

Você pode escolhê-los com cereja, é claro. Esse fluxo é bom quando você tem uma ramificação que está no modo de manutenção.

Dustin
fonte
1
Obrigado, escolha cereja fará o trabalho. Não é tão bom quanto o que eu esperava, mas serve.
23411 Brad Robinson
3

Uma espécie de anúncio para o meu projeto que basicamente envolve o processo descrito por @araqnid.

É uma espécie de auxiliar que apresenta o seguinte fluxo GIT:

  • há uma notificação diária / semanal sobre fusões pendentes das ramificações de manutenção nas ramificações dev / master
  • O mantenedor da filial verifica o status e decide se todas as confirmações são necessárias e as bloqueia algumas delas ou solicita que os desenvolvedores se bloqueiem. No final, o ramo de manutenção é mesclado no upsteam.

Uma citação da página do projeto:

Dependendo do fluxo de trabalho, é possível ter filiais de manutenção ou específicas do cliente junto com a filial principal. Esses ramos também são chamados de ramos LTS.

Muitas vezes, os hot fixes vão para as ramificações onde o bug foi relatado e, em seguida, a confirmação é mesclada novamente para a ramificação principal.

A prática geral é ter todas as ramificações perfeitamente sincronizadas com o mestre, ou seja, você deseja ver um delta claro entre uma ramificação específica e o mestre para entender se o mestre contém todos os recursos e correções.

No entanto, às vezes você não deseja confirmações específicas porque são específicas do cliente e não devem ser visíveis por outros usuários. Ou seu ramo principal divergiu tanto que requer uma abordagem completamente diferente para corrigir o problema, ou melhor ainda, o problema não está mais presente lá.

Também no caso de seleção de cereja do mestre para o ramo de manutenção, o commit resultante deve ser bloqueado no mestre.

Dmytro
fonte
0

Crie uma terceira ramificação para as alterações desejadas no master10, mas não no master20. Sempre considere master10 como seu "mestre", o ramo mais estável de todos. A ramificação com a qual todas as outras ramificações desejam manter sempre sincronizadas.

wilhelmtell
fonte
Eu acho que isso poderia funcionar, mas eu já entrei nesse estado, e um terceiro ramo provavelmente me confundiria ainda mais. :)
Brad Robinson
0

Em vez de revertou cherry-pickpara esse caso, você precisa que o git considere as mudanças que você está pulando como sendo mais antigas que as que você fez.

Assim:

  1. mesclar a última confirmação antes das confirmações que você deseja ignorar. Obviamente, isso mesclará todas as confirmações anteriores. git merge ccc
  2. mesclar os commits que você deseja pular. git merge fff --no-commit
  3. encenar qualquer mesclagem, desestabilizar todas as alterações e desfazer todas as alterações. (Talvez haja comandos à prova de idiotas para isso, mas eu faria essa parte em uma interface do usuário - como você sabe)
  4. complete a mesclagem vazia git merge --continue
  5. mesclar os commits APÓS aquele que você queria pular. git merge source-branch-head

Após a Etapa 4, o git considerará seu ramo mais recente que o commit, já que você já lidou com ele (escolhendo manter SUAS versões das coisas).

Jason Kleban
fonte