git remove merge commit do histórico

97

Meu histórico Git é assim:

História Git

Eu gostaria de esmagar os commits roxos em um único. Eu não quero vê-los nunca mais no meu log de commits.

Eu tentei fazer um git rebase -i 1, mas mesmo estando 1no branch azul (cf. figura), ainda vejo todos os commits no meu branch roxo.

Como posso remover completamente o branch roxo (do log de commit)?

Benjamin Toueg
fonte
O seu repo foi enviado para qualquer lugar que outras pessoas tenham obtido dele?
Schleis
Ambas as filiais são puramente locais.
Benjamin Toueg

Respostas:

100

Fazer git rebase -i <sha before the branches diverged>isso permitirá que você remova o commit de mesclagem e o log terá uma única linha, conforme desejado. Você também pode deletar quaisquer commits que você não deseja mais. O motivo pelo qual seu rebase não estava funcionando é que você não estava retrocedendo o suficiente.

AVISO: Você está reescrevendo a história fazendo isso. Fazer isso com alterações que foram enviadas para um repositório remoto causará problemas. Eu recomendo fazer isso apenas com commits locais.

Schleis
fonte
4
Mesmo se eu escolher um sha antes que os ramos tenham divergido, vejo todos os commits do ramo roxo -_-
Benjamin Toueg
1
Sim, então você os apaga no editor que aparece git rebasee eles serão removidos.
Schleis
4
Excluir os commits resultou na perda de todas as modificações da fusão. Mas fiz um soft reset e consegui algo exatamente como queria (o pedido não corresponde às expectativas iniciais).
Benjamin Toueg
2
esta resposta está incompleta em detalhes, de qual branch você inicia o rebase?
grgry
3
Quase certo que você não deseja 'remover' os commits. 'remover' não é uma opção no rebase, mas excluir é. se você deletar um commit, você perderá as mudanças que ele introduziu. Você quer esmagar os commits.
thecoshman
69

Começando com o repo no estado original

História original do repo

Para remover o commit de mesclagem e comprimir o branch em um único commit na linha principal

Commits comprimidos, sem commit de mesclagem

Use estes comandos (substituindo 5 e 1 pelos SHAs dos commits correspondentes):

git checkout 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git rebase HEAD master

Para manter um commit de mesclagem, mas compactar os commits de branch em um:

Commits comprimidos, commit de mesclagem retido

Use estes comandos (substituindo 5, 1 e C pelos SHAs dos commits correspondentes):

git checkout -b tempbranch 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git checkout C
git merge --no-ff tempbranch
git rebase HEAD master

Para remover o commit de mesclagem e substituí-lo por commits individuais do branch

Branch movido para linha principal, sem consolidação de mesclagem

Basta fazer (substituindo 5 pelo SHA do commit correspondente):

git rebase 5 master

E, finalmente, para remover o ramo inteiramente

Filial totalmente removida

Use este comando (substituindo C e D pelos SHAs dos commits correspondentes):

git rebase --onto C D~ master
Allen Luce
fonte
no git rebase 5 mastercaso, por que não é a ordem "ABC 1 2 3 4 5 D ..."?
Roy
1
Esse comando pega os commits que masternão têm em comum 5e os coloca no topo 5. O commit em Cnão faz parte da linhagem de 5, é o primeiro a ser movido para cima 5.
Allen Luce
2
Se você quiser terminar com "ABC 1 2 3 4 5 D ...", você pode fazer:git rebase C 5; git rebase 5 master
Allen Luce
16

Existem duas maneiras de resolver isso com base no que você deseja:

Solução 1 : remover commits roxos, preservando o histórico (caso você queira reverter)

git revert -m 1 <SHA of merge>

-m 1 especifica qual linha pai escolher

Os commits roxos ainda estarão lá na história, mas como você reverteu, você não verá o código desses commits.


Solução 2 : remova completamente os commits roxos (alteração perturbadora se o repo for compartilhado)

git rebase -i <SHA before branching out>

e deletar (remover linhas) correspondendo aos commits roxos.

Isso seria menos complicado se os commits não fossem feitos após a fusão. Confirmações adicionais aumentam a chance de conflitos durante revert/rebase.

prem
fonte
Isso não parece certo. Deixando de lado o fato de que é difícil dizer o que o postador original queria fazer com os commits roxos em primeiro lugar, se você reverter a fusão, tudo bem, isso fará um patch reverso das mudanças daquele commit e adicionará como outro commit, cancelando o commit roxo. É como 1 - 1 = 0. Mas se você então rebase os commits roxos, você deixa para trás o patch revertido, a menos que você rebase isso também. Do contrário, é como aplicar -1ao seu histórico, não 0, então você deixará para trás as mudanças que não deseja.
@Cupcake, desde que duas respostas separadas. Eu revisei a resposta para ficar menos confusa: P
prem
AFAIK não é isso que o OP está pedindo. Ele deseja manter as alterações, mas remover o ruído de seu registro. Para isso, ele precisa esmagar os commits, deletar irá remover as mudanças.
thecoshman
Verdade, parece que a pergunta original foi reformulada. Esta resposta não é para o problema de OPs.
estreia em
16

Para apenas remover um Merge Commit

Se tudo o que você deseja fazer é remover um commit de mesclagem (2) para que seja como se nunca tivesse acontecido, o comando é simplesmente o seguinte

git rebase --onto <sha of 1> <sha of 2> <blue branch>

E agora o branch roxo não está no log de commits em azul e você tem dois branches separados novamente. Você pode então esmagar o roxo de forma independente e fazer quaisquer outras manipulações que desejar sem o commit de mesclagem no caminho.

Warren
fonte
De todas as respostas, considero esta a mais direta e a mais fácil de fazer. Obrigado.
Roshambo