Como escolher múltiplos commits

Eu tenho dois ramos. Commit a é a cabeça de um, enquanto o outro tem b , c , d , f no topo de a . Eu quero mover c , d , f para o primeiro ramo sem cometer b . Usando a seleção de cereja, é fácil: fazer o primeiro check-out de cherry-pick, um a um c para f e rebase o segundo branch para first. Mas existe alguma maneira de escolher todas as cf em um único comando?

Aqui está uma descrição visual do cenário (obrigado JJD ):

insira a descrição da imagem aqui

O Git 1.7.2 introduziu a capacidade de selecionar uma série de commits. Das notas de lançamento :

git cherry-pick “aprendeu a escolher uma série de commits (por exemplo,” cherry-pick A..B “e” cherry-pick –stdin “), assim como” git revert “; estes não suportam o melhor controle de sequenciamento” rebase [-i] “tem, no entanto.


Incluindo comentários importantes (créditos para os respectivos autores)

Nota 1: No formulário “cherry-pick A..B”, A deve ser mais antigo que B. Se estiverem na ordem errada, o comando falhará silenciosamente. – damian

Nota 2: Além disso, isto não irá escolher A, mas sim tudo depois de A até e incluindo B. – JB Rainsberger

Nota 3: Para include A apenas digite git cherry-pick A ^ .. B – sschaef

A maneira mais simples de fazer isso é com a opção rebase para rebase . Suponha que o ramo que a corrente termina em a é chamado mybranch e este é o ramo que você deseja mover cf para.

 # checkout mybranch git checkout mybranch # reset it to f (currently includes a) git reset --hard f # rebase every commit after b and transplant it onto a git rebase --onto ab 

Ou o one-liner solicitado:

 git rebase --onto abf 

Você pode usar uma combinação serial de git rebase e git branch para aplicar um grupo de commits em outro branch. Como já foi postado por wolfc, o primeiro comando realmente copia os commits. No entanto, a alteração não é visível até você adicionar um nome de ramificação à maior parte do commit do grupo.

Por favor, abra a foto em uma nova aba …

Fluxo de trabalho

Para resumir os comandos na forma de texto:

  1. Abra o gitk como um processo independente usando o comando: gitk --all & .
  2. Execute git rebase --onto abf .
  3. Pressione F5 no gitk . Nada muda. Mas nenhuma HEAD está marcada.
  4. Execute a git branch selection
  5. Pressione F5 no gitk . O novo ramo com seus commits aparece.

Isso deve esclarecer as coisas:

  • Confirmar a é o novo destino raiz do grupo.
  • Commit b é o commit antes do primeiro commit do grupo (exclusivo).
  • Commit f é o último commit do grupo (inclusive).

Posteriormente, você poderia usar o git checkout feature && git reset --hard b para excluir os commits c até f da ramificação do feature .

Além dessa resposta, eu escrevi um post no blog que descreve os comandos em outro cenário que deve ajudar a usá-lo em geral.

Para aplicar os comentários de JB Rainsberger e sschaef para responder especificamente à pergunta … Para usar um intervalo de escolha de cereja neste exemplo:

 git checkout a git cherry-pick b..f 

ou

 git checkout a git cherry-pick c^..f 
 git rev-list --reverse b..f | xargs -n 1 git cherry-pick 
 git format-patch --full-index --binary --stdout range... | git am -3 

Se você tiver revisões seletivas para mesclar, digamos A, C, F, J de A, B, C, D, E, F, G, H, I, J comete, simplesmente use o comando abaixo:

git cherry-pick ACFJ

Na verdade, a maneira mais simples de fazer isso poderia ser

  1. salve a base de mesclagem entre as duas ramificações MERGE_BASE=$(git merge-base branch-a branch-b)
  2. avançar ou rebase o ramo mais antigo para o ramo mais novo
  3. rebaixar o ramo resultante para si mesmo, iniciando na base de mesclagem da etapa 1 e remover manualmente as confirmações que não são desejadas:

     git rebase ${SAVED_MERGE_BASE} -i 

    Alternativamente, se houver apenas alguns novos commits, pule a etapa 1 e simplesmente use

     git rebase HEAD^^^^^^^ -i 

    na primeira etapa, usando o suficiente ^ para passar da base de mesclagem.

Você verá algo assim no rebase interativo:

 pick 3139276 commit a pick c1b421d commit b pick 7204ee5 commit c pick 6ae9419 commit d pick 0152077 commit e pick 2656623 commit f 

Em seguida, remova as linhas b (e quaisquer outras que você queira)