Estou tentando mesclar 2 commits em 1, então segui “squashing commits with rebase” do git ready .
Eu corri
git rebase --interactive HEAD~2
No editor resultante, mudo pick
para squash
e, em seguida, salve-saia, mas a rebase falha com o erro
Não é possível 'squash' sem uma confirmação anterior
Agora que minha árvore de trabalho atingiu esse estado, estou tendo problemas para me recuperar.
O comando git rebase --interactive HEAD~2
falha com:
O rebase interativo já foi iniciado
e git rebase --continue
falha com
Não é possível 'squash' sem uma confirmação anterior
Respostas:
Sumário
A mensagem de erro
significa que você provavelmente tentou "esmagar para baixo". O Git sempre coloca uma confirmação mais recente em uma confirmação mais antiga ou "para cima", conforme exibido na lista de tarefas de rebase interativa, ou seja, em uma confirmação na linha anterior. Alterar o comando na primeira linha da sua lista de tarefas
squash
sempre produzirá esse erro, pois não há nada para o primeiro commit ser compactado.O conserto
Primeiro volte para onde você começou
Diga que sua história é
Ou seja, a foi o primeiro commit, depois b e finalmente c. Depois de confirmar c, decidimos esmagar bec juntos:
(Nota: A execução
git log
direciona sua saída para um pager,less
por padrão na maioria das plataformas. Para sair do pager e retornar ao prompt de comando, pressione aq
tecla.)A execução
git rebase --interactive HEAD~2
fornece um editor com(Observe que esta lista de tarefas está na ordem inversa em comparação com a saída de
git log
.)Alterar b's
pick
parasquash
resultará no erro que você viu, mas, em vez disso, você esmaga c em b (confirmação mais recente na mais antiga ou “esmaga para cima”) alterando a lista de tarefas parae salvar seu editor, você receberá outro editor cujo conteúdo é
Quando você salva e sai, o conteúdo do arquivo editado se torna uma mensagem de confirmação da nova confirmação combinada:
Nota sobre como reescrever o histórico
O rebase interativo reescreve o histórico. Tentar enviar para um controle remoto que contém o histórico antigo falhará porque não é um avanço rápido.
Se a ramificação que você reformulou for uma ramificação de tópico ou recurso na qual você está trabalhando sozinho , não é grande coisa. Enviar para outro repositório exigirá a
--force
opção ou, alternativamente, você poderá, dependendo das permissões do repositório remoto, primeiro excluir a ramificação antiga e depois enviar a versão rebaseada. Exemplos desses comandos que potencialmente destruirão o trabalho estão fora do escopo desta resposta.Reescrever o histórico já publicado em uma ramificação na qual você está trabalhando com outras pessoas sem uma boa razão, como deixar uma senha ou outros detalhes sensíveis forçar o trabalho de seus colaboradores e é antissocial e incomodará outros desenvolvedores. A seção “Recuperando de uma rebase upstream” na
git rebase
documentação explica, com ênfase adicional.fonte
git log hashoftheoldcommit
e deu certo, mas eu estava curioso para ver umgit log --graph
com todos esses commits inacessíveis incluídoSe houver várias confirmações, você pode usar
git rebase -i
para esmagar duas confirmações em uma.Se houver apenas duas confirmações que você deseja mesclar e elas forem as "duas mais recentes", os seguintes comandos poderão ser usados para combinar as duas confirmações em uma:
fonte
git reset --soft HEAD~10
, onde 10 é o número de confirmações que você deseja mesclar.HEAD
usandogit reset --soft 47b5c5...
onde47b5c5...
está o ID SHA1 do commit.Rebase: você não precisará disso:
Uma maneira mais simples para o cenário mais frequente.
Na maioria dos casos:
Na verdade, se tudo o que você deseja é simplesmente combinar vários commits recentes em um, mas não precisa
drop
,reword
e outro trabalho de rebase.você pode simplesmente fazer:
~n
é o número de commits para suavemente un-commit (ou seja~1
,~2
...)Em seguida, use o seguinte comando para modificar a mensagem de confirmação.
que é praticamente o mesmo que um longo intervalo de
squash
e umpick
.E funciona para n confirmações, mas não apenas duas confirmações, conforme a resposta acima solicitada.
fonte
~n
é o número de commits para suavemente un-commit (ou seja~1
,~2
...)n
últimas confirmações, masn
confirmar no meio? Posso fazer isso facilmente?git rebase -i
é o que você precisa para fazer osquash
trabalho. @chumakoffn
os commits mais recentes em um, primeiro usogit reset --soft @~m
, ondem = n - 1
Primeiro você deve verificar quantas confirmações possui:
Existem dois status:
Uma é que existem apenas dois commits:
Por exemplo:
(Nesse caso, você não pode usar o git rebase para fazer), você precisa fazer o seguinte.
Outra é que existem mais de dois commits; você deseja mesclar commit C e D.
Por exemplo:
(sob essa condição, você pode usar o git rebase)
E do que usar "squash" para fazer. O resto é muito fácil. Se você ainda não sabe, leia http://zerodie.github.io/blog/2012/01/19/git-rebase-i/
fonte
git push -f origin master
pode ser necessário.Supondo que você estivesse em seu próprio ramo de tópico. Se você deseja mesclar os dois últimos commits em um e parecer um herói, ramifique o commit pouco antes de fazer os dois últimos commits.
Em seguida, o squash confirma o outro ramo neste novo ramo:
Isso trará as mudanças, mas não as comprometerá. Então, apenas os comprometa e pronto.
Agora você pode mesclar esse novo ramo de tópico novamente no ramo principal.
fonte
a
ec
precisa ser mesclada e mantidab
como está.git checkout -b combine-last-two-commits "HEAD^2"
) na versão 2.17 do git, recebo um erro:fatal: 'HEAD^2' is not a commit and a branch 'combine-last-two-commits' cannot be created from it
você pode cancelar o rebase com
e quando você executa o comando rebase interativo novamente, o 'squash; commit deve estar abaixo do pick commit na lista
fonte
Eu costumo usar o git reset --mixed para reverter uma versão base antes de vários commits que você deseja mesclar, então eu faço um novo commit, para que o seu commit seja mais recente, garanta que a sua versão seja HEAD depois de enviar para o servidor.
Se eu quiser mesclar a cabeça dois commits em um, primeiro eu uso:
"249cf9392da197573a17c8426c282" era a terceira versão, também é a sua versão base antes de mesclar, depois disso, faço um novo commit:
É tudo, a esperança é outro caminho para todos.
FYI, de
git reset --help
:fonte
$ git rebase --abort
Execute esse código a qualquer momento, se você quiser desfazer o git rebase
$ git rebase -i HEAD~2
Reaplicar os últimos dois commits. O comando acima abrirá um editor de código
After: wq você estará no modo rebase ativo
Nota : Você receberá outro editor se não houver mensagens de aviso / erro. Se houver um erro ou aviso de que outro editor não será exibido, você pode abortar executando
$ git rebase --abort
se encontrar um erro ou aviso, caso contrário, continue executando$ git rebase --continue
Você verá sua 2 mensagem de confirmação. Escolha uma ou escreva sua própria mensagem de confirmação, salve e saia [: wq]
Nota 2: pode ser necessário forçar o envio de alterações ao repositório remoto se você executar o comando rebase
$ git push -f
$ git push -f origin master
fonte
git push -f origin/master
é o que outras respostas estão faltando. +1Desde que eu uso
git cherry-pick
quase tudo, para mim é natural fazê-lo mesmo aqui.Como fiz o
branchX
check-out e há dois commits na ponta, dos quais desejo criar um commit combinando seu conteúdo, faço o seguinte:Se eu quiser atualizar
branchX
também (e acho que esse é o lado negativo deste método), também tenho que:fonte
Se o seu ramo principal se
git log
parece com o seguinte:e você deseja mesclar as duas confirmações principais, siga estas etapas simples:
git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e
. (Resolva conflitos, se houver)git commit --amend
.É isso aí. Você pode enviar esta versão mesclada na ramificação "fusões-confirmações", se desejar.
Além disso, você pode descartar as duas confirmações consecutivas em sua ramificação mestre agora. Atualize seu ramo principal como:
fonte
Se você deseja combinar as duas confirmações mais recentes e usar apenas a mensagem da confirmação mais antiga, pode automatizar o processo usando
expect
.Eu assumo:
Eu testei com
git version 2.14.3 (Apple Git-98)
.fonte
expect
não é descrito.expect
.