Em um repositório local, acabei de executar git cherry-pick SHA
sem conflitos ou problemas. Então percebi que não queria fazer o que acabei de fazer. Eu não empurrei isso para lugar nenhum.
Como posso remover apenas esta escolha certa?
Eu gostaria de saber se existe uma maneira de fazer isso:
- quando eu tenho outras mudanças locais
- quando eu não tenho outras mudanças locais
De preferência com um comando para ambos os casos, se possível.
Para desfazer seu último commit, simplesmente faça
git reset --hard HEAD~
.Editar : esta resposta se aplica a uma versão anterior da pergunta que não menciona a preservação das mudanças locais; a resposta aceita de Tim é de fato a correta. Agradecimentos a qwertzguy pelo aviso.
fonte
HEAD
) é mais robusto: considere o caso infeliz em quehead
é o nome de uma referência existente.Se possível, evite reinicializações forçadas. Reinicializações rígidas são uma das poucas operações destrutivas no git. Felizmente, você pode desfazer uma seleção seletiva sem reinicializações e evitar qualquer coisa destrutiva.
Observe o hash da escolha que deseja desfazer, digamos que seja
${bad_cherrypick}
. Faça umgit revert ${bad_cherrypick}
. Agora, o conteúdo de sua árvore de trabalho é o mesmo antes de sua escolha ruim.Repita o seu
git cherry-pick ${wanted_commit}
e quando estiver satisfeito com a nova escolha, faça umgit rebase -i ${bad_cherrypick}~1
. Durante o rebase, exclua ambos${bad_cherrypick}
e sua reversão correspondente.O branch em que você está trabalhando terá apenas uma boa escolha. Sem necessidade de redefinições!
fonte
git reflog
pode vir em seu socorro.Digite-o em seu console e você obterá uma lista de seu histórico de git junto com SHA-1 que os representa.
Basta verificar qualquer SHA-1 para o qual deseja reverter
Antes de responder vamos adicionar alguns antecedentes, explicando o que é isso
HEAD
.First of all what is HEAD?
HEAD
é simplesmente uma referência ao commit atual (mais recente) no branch atual.Só pode haver um
HEAD
em um determinado momento. (excluindogit worktree
)O conteúdo de
HEAD
é armazenado dentro.git/HEAD
e contém os 40 bytes SHA-1 do commit atual.detached HEAD
Se você não estiver no último commit - o que significa que
HEAD
está apontando para um commit anterior no histórico, é chamadodetached HEAD
.Na linha de comando, será semelhante a este - SHA-1 em vez do nome do branch, pois o
HEAD
não está apontando para a ponta do branch atualAlgumas opções sobre como recuperar de um HEAD separado:
git checkout
Isso fará o checkout de um novo branch apontando para o commit desejado.
Este comando fará checkout para um determinado commit.
Neste ponto, você pode criar uma ramificação e começar a trabalhar a partir deste ponto.
git reflog
Você sempre pode usar o
reflog
também.git reflog
irá exibir qualquer mudança que atualizou oHEAD
e verificar a entrada de reflog desejada irá definir oHEAD
retorno para este commit.Cada vez que o HEAD é modificado, haverá uma nova entrada no
reflog
Isso o levará de volta ao commit desejado
git reset --hard <commit_id>
"Mova" seu HEAD de volta para o commit desejado.
você também pode usar o
git rebase --no-autostash
.git revert <sha-1>
"Desfazer" o commit ou intervalo de commit fornecidos.
O comando reset irá "desfazer" quaisquer mudanças feitas no commit fornecido.
Um novo commit com o patch undo será confirmado enquanto o commit original também permanecerá no histórico.
Este esquema ilustra qual comando faz o quê.
Como você pode ver lá,
reset && checkout
modifique oHEAD
.fonte
git reset --hard
Diante do mesmo problema, descobri que se você se comprometeu e / ou fez push para remoto desde sua escolha bem-sucedida e deseja removê-lo, você pode encontrar o SHA da escolha certa executando:
git log --graph --decorate --oneline
Então, (depois de usar
:wq
para sair do log), você pode remover a escolha certa usandogit rebase -p --onto YOUR_SHA_HERE^ YOUR_SHA_HERE
onde
YOUR_SHA_HERE
é igual ao SHA de 40 ou 7 caracteres abreviado do commit escolhido a dedo.No início, você não poderá enviar suas alterações porque seu repo remoto e seu repo local terão históricos de commits diferentes. Você pode forçar seus commits locais a substituir o que está em seu controle remoto usando
git push --force origin YOUR_REPO_NAME
(Eu adaptei esta solução de Seth Robertson : Consulte "Removendo um commit inteiro.")
fonte
Um comando e não usa o
git reset
comando destrutivo :GIT_SEQUENCE_EDITOR="sed -i 's/pick/d/'" git rebase -i HEAD~ --autostash
Ele simplesmente descarta o commit, colocando você de volta exatamente no estado anterior à escolha seletiva, mesmo que você tenha alterações locais.
fonte
git reset HEAD^
faz?git reset
desfaz a ação de confirmação sem eliminar nenhuma das alterações. Recomendo que você leia git-scm.com/docs/git-reset . A questão do OP é desfazer uma escolha seletiva. Tente os dois comandos, o meu o colocará de volta no estado exato em que estava antes da escolha certa.git reset
irá bagunçar sua árvore de trabalho à medida que deixa as mudanças selecionadas e elas se tornam indistinguíveis de suas mudanças locais pré-existentes.reset --hard
. Não deixa alteraçõesgit reset --hard
é um comando destrutivo que também removerá mudanças locais não relacionadas e fará isso de uma forma irrecuperável! Portanto, não foi isso que o OP pediu.sed
comando está fazendo, como isso difere de fazer manualmente e o que--autostash
faz.