Como posso reverter 1 confirmação?

127

Eu tenho 2 confirmações que não forcei:

$ git status
# On branch master
# Your branch is ahead of 'faves/master' by 2 commits.

Como posso reverter meu primeiro (o mais antigo), mas manter o segundo?

 $ git log
commit 3368e1c5b8a47135a34169c885e8dd5ba01af5bb
...

commit baf8d5e7da9e41fcd37d63ae9483ee0b10bfac8e
...

Daqui:

http://friendfeed.com/harijay/742631ff/git-question-how-do-i-rollback-commit-just-want

Eu só preciso fazer:

git reset --hard baf8d5e7da9e41fcd37d63ae9483ee0b10bfac8e

Isso é?

n179911
fonte
3
Esta questão parece estar fora de tópico, porque se trata de uma ferramenta de programação. Ele pertence ao estouro de pilha.
Peter Mortensen
@PeterMortensen Concordou. Este é o escopo para SuperUser
Kolob Canyon

Respostas:

95

A maneira mais segura e provavelmente mais limpa de se fazer é se recuperar de forma interativa.

git rebase -i HEAD^^

Ou,

git rebase -i baf8d5e7da9e41fcd37d63ae9483ee0b10bfac8e^

A partir daí, você pode compactar confirmações, o que coloca uma ou mais confirmações juntas na confirmação anterior. Para excluir completamente uma confirmação do histórico, exclua a linha da lista.

Você pode reverter uma confirmação com, git revertmas ela adicionará mais mensagens de confirmação ao histórico, o que pode ser indesejável. Use o -nparâmetro para dizer ao Git para não confirmar a reversão imediatamente. Você pode refazer a interação de maneira interativa e compactá-los em uma confirmação anterior para manter as coisas limpas.

Se as duas confirmações com as quais você trabalha aqui afetam os mesmos arquivos, é possível que ocorra um conflito de mesclagem.

A redefinição do repositório com git reset --harddeve ser feita com cuidado, pois não pode ser desfeita.

O histórico de reescrita deve ser feito com cuidado.

jtimberman
fonte
Como posso excluir uma confirmação durante 'git rebase'? Existem apenas três comandos: escolher, editar, squash. Não há AFAIK de exclusão.
N179911 04/09/2009
8
apagar a linha da lista inteiramente, e ele exclui que cometem
jtimberman
quando quis reverter a mudança, não deixei vestígios dela. Se você também não deixar nenhum vestígio de sua reversão, essa é a melhor maneira de fazer isso.
Phillip Whelan
"o caminho mais seguro e provavelmente o mais limpo a seguir é fazer uma recuperação interativa" Talvez não, se você não usar o vim. Tive sorte e descobri o caminho para sair dessa bagunça. Ainda upvoting porque eu deveria aprender vim :-)
isimmons
Eu sugeriria usar rebaseo menos possível. Se você trabalha com outras pessoas, basta fazer revert.
boldnik
52

Isso se http://nakkaya.com/2009/09/24/git-delete-last-commit/ e funcionou para mim

Última confirmação Git Delete

De vez em quando, tarde da noite, quando o café acabava, eu cometi coisas que não deveria. Depois, passo os próximos 10 a 15 minutos pesquisando como remover o último commit que fiz. Então, depois da terceira vez, eu queria gravar um disco para poder me referir a ele mais tarde.

Se você cometeu lixo, mas não empurrou,

git reset --hard HEAD~1

HEAD ~ 1 é uma abreviação para o commit antes do head. Como alternativa, você pode consultar o SHA-1 do hash para o qual deseja redefinir. Observe que, ao usar --hard, quaisquer alterações nos arquivos rastreados na árvore de trabalho, uma vez que a confirmação antes do cabeçalho é perdida.

Se você não quiser apagar o trabalho que você fez, poderá usar a --softopção que excluirá a confirmação, mas todos os arquivos alterados serão deixados como "Alterações a serem confirmadas", conforme o status do git.

Agora, se você já empurrou e alguém puxou, o que geralmente é o meu caso, você não pode usar o git reset. No entanto, você pode fazer uma reversão do git,

git revert HEAD

Isso criará um novo commit que reverte tudo o que foi introduzido pelo commit acidental.

iStryker
fonte
2
Com a opção --soft, é perfeito para onde você renomeia um arquivo e acidentalmente "git commit -a" em vez de usar o "git add" primeiro.
Aaron Harun
8

Não. O git-reset --hard o trará de volta à história. O que você está procurando é git revert, que desfará qualquer confirmação.

Peltier
fonte
4
Bem, isso funciona, mas também polui o registro de confirmação. Se essas confirmações não tiverem sido enviadas / enviadas, é melhor limpá-las com uma nova análise interativa. A capacidade de alterar o histórico é uma das principais vantagens do git sobre outros sistemas de controle de versão.
knweiss 03/09/09
6

Acabei de fazer isso:

git rebase -i HEAD^^

Eu estraguei tudo, então eu fiz

git rebase --abort

Então fiz isso de novo. Então eu tive que empurrar assim:

git push origin master -f

E destruiu os commits mais recentes que o commit para o qual eu havia revertido. Trabalhou muito bem.

hamstar
fonte
4

Não, git reset --hard baf8d5eexcluirá o 3368e1ccommit e o HEAD será baf8d5eposteriormente.

Se você deseja manter a 3368e1cconfirmação e excluir a bad8d5econfirmação, a solução mais fácil é fazer uma " git rebase -i HEAD~2" (ou seja, rebase interativa das duas últimas confirmações). Este comando iniciará o editor de mensagens de confirmação e você verá uma linha para cada um dos dois últimos commit. Lá, você apenas exclui a bad8d5elinha de confirmação e salva. O git reescreverá seu histórico e o segundo commit desaparecerá.

Existem outros comandos úteis que você pode usar no editor de mensagem de commit como squash, edit, etc. rebase interativo é muito poderoso!

Não faça isso se alguém já viu esses commits (empurre ou puxe do seu repositório)!

Knweiss
fonte
1
git reset --hard {ref}

é a única maneira de desfazer um commit se houver apenas outro commit no repositório (por exemplo, commit inicial e mais 1). O restante das formas (revert, rebase) se recusa a trabalhar, pelo menos a partir do git 1.7.5.1.

Se você seguir o comando git resetcom git gc, o git excluirá completamente os dados de confirmação antigos do repositório.

rodo
fonte
1
git checkout <treeish> -- /path/to/dir

Isso trará de volta o diretório do “treeish” especificado para o / path / to / dir

lokeshpahal
fonte
0

Eu consegui isso editando manualmente os códigos de hash dos últimos commits dos arquivos HEAD dentro da pasta do repositório:

"centralRepository\refs\heads\master"
"centralRepository\refs\heads\branch2"

Antes disso, nunca consegui forçar a origem das operações UNMERGE que fiz localmente. Ele continuou dizendo que "falhou em enviar alguns árbitros" ao Repositório Central.

Leandro M
fonte