Git: erro “Não é possível 'esmagar' sem um commit anterior” durante o rebase

95

Tenho o seguinte no texto de tarefas de git rebase -i HEAD~2:

pick 56bcce7 Closes #2774
pick e43ceba Lint.py: Replace deprecated link

# Rebase 684f917..e43ceba onto 684f917 (2 command(s))
#
...

Agora, quando tento esmagar o primeiro ( 56bcce7) e escolher o segundo adicionando "s" antes do primeiro, recebo o seguinte erro:

Cannot 'squash' without a previous commit

Alguém pode me explicar o que significa e como faço isso?

Eu quero esmagar o primeiro commit ( 56bcce7) e "selecionar e reformular" o segundo ( e43ceba) commit

Dawny33
fonte
1
Altere HEAD ~ 2 para HEAD ~ 3 se você realmente deseja esmagar.
ElpieKay de
1
E possivelmente use --root, se HEAD ~ 2 for seu primeiro commit: stackoverflow.com/a/598788/2444812
Sybille Peters

Respostas:

79

O rebase interativo apresenta os commits na ordem reversa daquela com a qual você está acostumado git log. git rebase -ireproduz os commits selecionados na ordem exata (de cima para baixo) em que estão listados no arquivo de instruções de rebase salvo. Ao fazer o squashing, o commit selecionado para squashing é combinado com o commit que o precede na lista (editada), ou seja, o commit da linha anterior. No seu caso - não há commit anterior para 56bcce7. Você tem que fazer um dos seguintes

  • git rebase -i HEAD~3(se você quer esmagar 56bcce7a 684f917)
  • Se você quer dizer para combinar 56bcce7com e43ceba, e e43cebanão depende 56bcce7, então simplesmente reordená-los:

    r e43ceba Lint.py: Replace deprecated link
    s 56bcce7 Closes #2774
    

    ATUALIZAÇÃO : a resposta de Gus abaixo sugere uma maneira melhor de fazer o mesmo, sem reordenar os dois commits:

    r 56bcce7 Closes #2774
    s e43ceba Lint.py: Replace deprecated link
    

    Isso irá esmagar / mesclar os dois commits em um. Quando o rebase interativo solicitar uma mensagem de confirmação reformulada para 56bcce7, forneça a mensagem de confirmação que descreve a união de 56bcce7e e43ceba.

Leon
fonte
1
Quero esmagar 56bcce7 em e43ceba. Então, como faço a Etapa 1 aqui?
Dawny33 de
82

Tive um problema semelhante, que resolvi da seguinte maneira:

Este é o grupo de commit que eu queria esmagar:

1 s 01cc5a08 Removes open div
2 s a2b6eecf Restores old fonts
3 s 603479ff Cleans left out div
4 pick 5afdbc33 Update: show logo on landing page
5 s 04c1cb13 change version of dev and prod from 1 to 2
6 s bbe6a8f8 Update: show logo on landing page if they have one
7 s c0d6008a Adds check for C users

Como você pode ver, eu não queria. 4, mas 1, 2 e 3 não tinham nenhum compromisso anterior para esmagar . Portanto, não é possível 'esmagar' sem um erro de confirmação anterior .

Minha solução foi usar a ropção de# r, reword = use commit, but edit the commit message

Então, minha lista de commits era assim:

1 r 01cc5a08 Removes open div
2 s a2b6eecf Restores old fonts
3 s 603479ff Cleans left out div
4 s 5afdbc33 Update: show logo on landing page
5 s 04c1cb13 change version of dev and prod from 1 to 2
6 s bbe6a8f8 Update: show logo on landing page if they have one
7 s c0d6008a Adds check for C users

Depois de salvar, o shell interativo me pediu para reformular o commit escolhido.

Depois disso, meu log de commits resultou em um único commit que resultou em um histórico de commit mais limpo.

Gus
fonte
2
como eu, se você obteve um erro porque não escolheu nenhum commit para reescrever ou escolher e obter o erro mencionado (em questão), você precisará fazer git rebase --edit-todoe corrigir referindo esta resposta e então fazergit rebase --continue
velho monge
Esta resposta foi concisa e
direta
16

Eu tive esse problema e a razão pela qual isso aconteceu no meu caso é que você não pode esmagar commits mais antigos em um novo commit. Aqui está um exemplo, digamos que você tenha 3 commits:

1 pick 01mn9h78 The lastest commit
2 pick a2b6pcfr A commit before the latest
3 pick 093479uf An old commit i made a while back

Agora, se você disser git rebase -i HEAD~3e fizer algo como

1 pick 01mn9h78 The lastest commit
2 s a2b6pcfr A commit before the latest
3 s 093479uf An old commit i made a while back

Isso resultará no erro:

erro: não é possível 'esmagar' sem um commit anterior. Você pode corrigir isso com 'git rebase --edit-todo' e então executar 'git rebase --continue'. Ou você pode abortar o rebase com 'git rebase --abort'.

Solução:

Ao esmagar os commits, você deve esmagar os commits recentes nos antigos e não vice-versa, portanto, no exemplo, será algo assim:

1 s 01mn9h78 The lastest commit
2 s a2b6pcfr A commit before the latest
3 pick 093479uf An old commit i made a while back

Isso vai funcionar bem, caso você queira todas as suas mensagens de commit, eu sugeriria correção em vez de squash .

DvixExtract
fonte
5
Obrigado - eu não reprimo os commits com frequência e o conselho para escolher o commit mais antigo é o que me ajudou a superar um erro git inútil.
0x574F4F54
2

Squash com a lógica reversa . Você poderá selecionar a mensagem de confirmação desejada na etapa posterior.

  • picko primeiro commit para o qual você não quer a mensagem de commit.
  • squashou fixupo (s) commit (s) que você deseja mesclar, até aquele que contém a mensagem de commit que você realmente queria.
pick 56bcce7 Closes #2774
squash e43ceba Lint.py: Replace deprecated link
  • confirme a mudança ( :x)
  • apague a (s) mensagem (ns) de commit que você não quer e deixe apenas a mensagem do commit que você deseja (neste caso Lint.py: Replace deprecated link:).
  • confirme a escolha ( :x)

Espero que esteja mais claro para alguém ✌🏽

Kamafeather
fonte
1

Será melhor apenas dizer no editor interativo contendo os commits, git sempre squash de baixo para cima e deve-se deixar uma entrada "pick" no topo para receber os squashes de baixo.

ekyu88
fonte
1

Acabei de tentar essa abordagem.

git log -n3

Isso mostraria os últimos 3 commits que me dariam uma idéia de qual é o último commit e qual foi anteriormente. Agora declarado rebase,

git rebase -i HEAD ~ 3

Escolha o último commit além do qual precisamos esmagar os outros dois. O ID do commit que é escolhido como commit básico seria como,

escolher commit_id

Para os outros dois IDs de commit, altere-os para,

squash commit_id

ou simplesmente,

s commit_id

Tom Taylor
fonte
0

Eu também já encontrei este problema agora, que é apenas descuido. Você pode resolver o problema como a seguir: quando você tenta esmagar o primeiro (56bcce7) e escolhe o segundo, você deve adicionar "s" antes da segunda linha, mas não o primeiro. você também pode consultar o próximo site: http://backlogtool.com/git-guide/en/stepup/stepup7_5.html

user8073722
fonte
1
Oi ! Seria melhor se você der uma olhada em Como criar um exemplo mínimo, completo e verificável para esforços futuros no estouro de pilha. -Obrigado
Momin