Eu gostaria de mudar para um commit específico, não para um HEAD do outro ramo:
A --- B --- C master
\
\-- D topic
para
A --- B --- C master
\
\-- D topic
ao invés de
A --- B --- C master
\
\-- D topic
Como posso conseguir isso?
git
version-control
rebase
git-rebase
Ondra Žižka
fonte
fonte
git checkout B
antes de executargit rebase
?rebase
comando são o que importa.Respostas:
Você pode evitar o uso do parâmetro --onto criando uma ramificação temporária no commit que você gosta e, em seguida, use rebase na sua forma simples:
fonte
git rebase temp
(quando no grupo ) desiste de "Os grupos de ramificações atuais estão atualizados".git rebase --onto <target> <from> <to>
para especificar o <from> commit.Você pode até adotar uma abordagem direta:
fonte
topic
ecommitB
.It works by going to the common ancestor of the two branches (the one you’re on and the one you’re rebasing onto), getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn.
tentei novamente agora e parecia funcionar muito bem.m > n
.Use a opção "para":
fonte
D
eD^
seria hash do último e penúltimo commit de "topic"?git rebase --onto <new-parent> <old-parent>
. Consulte Definindo o ponteiro do git parent para um pai diferente . No seu caso, <new-parent> é B e <old-parent> é A.git rebase --onto <commit-ID> master
git rebase --onto master <commit-ID-of-old-parent>
e para OPgit rebase --onto B A
.O comentário de jsz acima me salvou muito, então aqui está um destinatário passo a passo com base nele que eu tenho usado para rebase / mover qualquer commit sobre qualquer outro commit:
git rebase --onto <new parent> <old parent>
No exemplo acima, é tão simples quanto:
fonte
git rebase --onto B master
, veja minha resposta para uma explicação mais completa.Tópico Solução
O comando correto para responder à pergunta postada pode ser um dos seguintes (supondo que a ramificação
topic
já esteja com check-out):Se
topic
não estiver marcado, basta anexartopic
ao comando (exceto o último) da seguinte forma:Como alternativa, verifique primeiro o ramo com:
Rebase qualquer sequência de confirmações para uma confirmação de destino
A forma básica do comando que precisamos, extraída da documentação, é:
<Branch>
é opcional e tudo o que faz é fazer check-out da ramificação especificada antes de executar o restante do comando. Se você já fez check-out da ramificação que deseja refazer a recuperação, não precisa disso. Observe que você deve ter especificado<Upstream>
para especificar<Branch>
ou o git pensará que você está especificando<Upstream>
.<Target>
é o commit ao qual anexaremos nossa cadeia de commits. Ao fornecer um nome de filial, você está simplesmente especificando o commit principal dessa filial.<Target>
pode ser qualquer confirmação que não esteja contida na cadeia de confirmações que está sendo movida. Por exemplo:Para mover todo o ramo de funcionalidade, você não pode selecionar
X
,Y
,Z
, oufeature
como o<Target>
desde os todos são commits dentro do grupo que está sendo movido.<Upstream>
é especial porque pode significar duas coisas diferentes. Se for um commit que é um ancestral do ramo com check-out, ele servirá como ponto de corte. No exemplo que eu forneci, isso seria qualquer coisa que não éC
,D
oumaster
. Todas as confirmações depois<Upstream>
até o chefe da ramificação com check-out são as que serão movidas.No entanto, se
<Upstream>
não for um ancestral, o git fará o backup da cadeia a partir do commit especificado até que encontre um ancestral comum com o ramo com check-out (e interrompa se não conseguir encontrar um). No nosso caso, um<Upstream>
dosB
,C
,D
, oumaster
tudo vai resultar em comprometerB
servindo como ponto de corte.<Upstream>
é ele próprio um comando opcional e, se não for especificado, o git examinará o pai do ramo com check-out equivalente à entradamaster
.Agora que o git selecionou os commits que serão cortados e movidos, aplica-os para
<Target>
, ignorando os que já estão aplicados ao alvo.Exemplos e resultados interessantes
Usando este ponto de partida:
git rebase --onto D A feature
Será aplicada commits
B
,C
,X
,Y
,Z
para cometerD
e acabam pulandoB
eC
porque eles já foram aplicadas.git rebase --onto C X feature
Aplicará confirmações
Y
eZ
confirmaçõesC
, excluindo efetivamente as confirmaçõesX
fonte
Uma solução mais simples é
git rebase <SHA1 of B> topic
. Isso funciona independentemente de onde vocêHEAD
estiver.Podemos confirmar esse comportamento no git rebase doc
Você pode estar pensando o que acontecerá se eu mencionar SHA1
topic
também no comando acima?git rebase <SHA1 of B> <SHA1 of topic>
Isso também funcionará, mas a reorganização não fará
Topic
sentido para uma nova ramificação criada eHEAD
estará no estado desanexado. Portanto, a partir daqui, você deve excluir manualmente o antigoTopic
e criar uma nova referência de ramificação em uma nova ramificação criada por rebase.fonte
Eu usei uma mistura de soluções descritas acima:
Achei muito mais fácil ler e entender. A solução aceita levou-me a um conflito de mesclagem (com preguiça de corrigir manualmente):
fonte
Como o rebaseamento é tão fundamental, aqui está uma expansão da resposta de Nestor Milyaev . A combinação dos comentários de jsz e Simon South da resposta de Adam Dymitruk produz esse comando que funciona no
topic
ramo, independentemente de ele semaster
ramificar no commit do ramoA
ouC
:Observe que o último argumento é necessário (caso contrário, ele rebobina sua ramificação para confirmar
B
).Exemplos:
Portanto, o último comando é o que eu normalmente uso.
fonte
Existe outra maneira de fazer isso ou se você deseja voltar para mais do que apenas um commit.
Aqui está um exemplo para retornar ao
n
número de confirmações:Para o bem desta pergunta, isso também pode ser feito:
O comando funciona perfeitamente
git version 2.7.4
. Não testei em nenhuma outra versão.fonte