Fiz algumas alterações no meu ramo principal e quero trazê-las para montante. quando escolho as seguintes confirmações, no entanto, fico preso no fd9f578 onde o git diz:
$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.
O que o git está tentando me dizer e é a escolha certa para usar aqui? O ramo mestre inclui alterações nos arquivos que foram modificados no ramo upstream, portanto, tenho certeza de que haverá alguns conflitos de mesclagem, mas esses não são ruins demais para corrigir. Eu sei quais mudanças são necessárias onde.
Esses são os commits que eu quero trazer para cima.
e7d4cff added some comments...
23e6d2a moved static strings...
44cc65a incorporated test ...
40b83d5 whoops delete whitspace...
24f8a50 implemented global.c...
43651c3 cleaned up ...
068b2fe cleaned up version.c ...
fd9f578 Merge branch 'master' of ssh://extgit/git/sessions_common
4172caa cleaned up comments in sessions.c ...
fonte
git rebase
- é como uma mesclagem, mas, em vez de integrar dois galhos, transplanta um para sentar em cima do outro.git show
e similares).git reset --hard HEAD@{1}
para recuperar seu commit ausente.git reset
não se restringe a retroceder na história.git checkout -b mybranch HEAD@{1}
também funcionaria.git merge
pode ter consequências não intencionais. Esse comando adicionará todas as outras confirmações (mais antigas) existentes na ramificação pai. Geralmente, as pessoas escolhem escolher cereja, porque não querem que os outros comprometam. Verifique se está implementando apenas as alterações desejadas!-m
significa o número pai.No documento git:
Por exemplo, se sua árvore de confirmação for como abaixo:
então
git cherry-pick E
produzirá o problema que você enfrentou.git cherry-pick E -m 1
significa usarD-E
, enquantogit cherry-pick E -m 2
significa usarB-C-E
.fonte
A resposta do @ Borealid está correta, mas suponha que você não se preocupe em preservar o histórico exato de mesclagem de um ramo e apenas queira escolher uma versão linearizada dele. Aqui está uma maneira fácil e segura de fazer isso:
Estado inicial: você está no ramo
X
e deseja escolher os commitsY..Z
.git checkout -b tempZ Z
git rebase Y
git checkout -b newX X
git cherry-pick Y..tempZ
git branch -D tempZ
O que isso faz é criar uma ramificação
tempZ
baseada emZ
, mas com o histórico a partir deY
linearizado, e depois selecioná-lo em uma cópia deX
chamadanewX
. (É mais seguro fazer isso em uma nova ramificação, em vez de sofrer mutaçãoX
.) É claro que pode haver conflitos na etapa 4, que você precisará resolver da maneira usual (cherry-pick
funciona muito parecidorebase
com esse aspecto). Finalmente, ele exclui atempZ
ramificação temporária .Se a etapa 2 exibir a mensagem "O tempZ do ramo atual está atualizado", ele
Y..Z
já era linear, então ignore essa mensagem e continue com as etapas 3 em diante.Em seguida, revise
newX
e veja se isso fez o que você queria.(Nota: isso não é o mesmo que um simples
git rebase X
quando está no ramoZ
, porque não depende de forma alguma do relacionamento entreX
eY
; pode haver confirmações entre o ancestral comum e oY
que você não desejava.)fonte
git rebase Y
dizCurrent branch tempZ is up to date
Y..Z
já era linear. Então você pode ignorar essa mensagem e prosseguir com os passos 3 e 4.Simplificar. Escolha a cereja dos commits. Não escolha a fusão.
Aqui está uma reescrita da resposta aceita que idealmente esclarece as vantagens / riscos de possíveis abordagens:
Você está tentando escolher fd9f578, que foi uma fusão com dois pais.
Em vez de escolher uma mesclagem de cereja, a coisa mais simples é escolher a confirmação (ões) que você realmente deseja de cada ramificação na mesclagem.
Como você já mesclou, é provável que todos os commits desejados estejam na sua lista. Escolha-os diretamente e você não precisa mexer no commit da mesclagem.
explicação
A maneira como uma seleção de cereja funciona é pegando o diff que um conjunto de alterações representa (a diferença entre a árvore de trabalho nesse ponto e a árvore de trabalho de seu pai) e aplicando o conjunto de alterações à sua ramificação atual.
Se um commit tiver dois ou mais pais, como é o caso de uma mesclagem, esse commit também representará dois ou mais diffs. O erro ocorre devido à incerteza sobre a qual diff deve ser aplicada.
alternativas
Se você determinar que precisa incluir a mesclagem versus a seleção de cereja dos commits relacionados, você tem duas opções:
(Mais complicado e obscuro; também descarta o histórico), você pode indicar qual pai ou mãe deve aplicar.
Use a
-m
opção para fazer isso. Por exemplo,git cherry-pick -m 1 fd9f578
usará o primeiro pai listado na mesclagem como base.Considere também que, quando você escolhe uma confirmação de mesclagem, ele recolhe todas as alterações feitas no pai que você não especificou
-m
nessa confirmação . Você perde toda a história deles e junta todas as suas diferenças. Sua chamada.(Mais simples e mais familiar; preserva a história) que você pode usar em
git merge
vez degit cherry-pick
.git merge
, ele tentará aplicar todas as confirmações existentes na ramificação que você está mesclando e listá-las individualmente em seu log do git.fonte
A simplificação do método @Daira Hopwood é boa para escolher um único commit. Não precisa de ramificações temporárias.
No caso do autor:
então faça:
fonte