Como faço para excluir confirmações não-empurradas do git?

948

Eu acidentalmente comprometido com o ramo errado. Como faço para excluir essa confirmação?

NullVoxPopuli
fonte

Respostas:

1811

Exclua a confirmação mais recente, mantendo o trabalho que você fez:

git reset --soft HEAD~1

Exclua a confirmação mais recente, destruindo o trabalho que você fez:

git reset --hard HEAD~1
dbyrne
fonte
13
certificar-se de cabeça está apontando para o ramo .. (verificá-la primeiro)
Frank Schwieterman
128
E certifique-se CABEÇA ~ 1 é a cometer ... Você também pode fazergit reset --hard origin
Daenyth
13
O pensamento git remotelista a origem para mim, git reset --hard origindiz fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. Por quê?
trss
7
Isso é incrível. Acabei de salvar minha vida.
NinjaBoy 02/09
2
git reset HEAD~1também manterá todas as suas alterações, mas o deixará com um índice vazio, em vez de manter tudo (como a --softopção faria).
Holloway
139

Eu me pergunto por que a melhor resposta que eu encontrei é apenas nos comentários! ( por Daenyth com 86 votos a favor )

git reset --hard origin

Este comando sincronizará o repositório local com o repositório remoto, livrando-se de todas as alterações feitas no seu local. Você também pode fazer o seguinte para buscar o ramo exato que possui na origem.

git reset --hard origin/<branch>
Ashkan Sirous
fonte
16
Obrigado por isso, expandindo a explicação um pouco: para um ramo específico:git reset --hard origin/<branch>
Cleary
4
Ou git reset --soft origin/<branch>, se você quiser se livrar da confirmação, mas mantenha o trabalho local.
Riverhorse
1
eu recebo fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., você precisa especificar o ramo como:git reset --hard origin/feature/my-cool-stuff
Kip
Brilhante! Isso realmente funciona, ao contrário da resposta "aceita", que apenas retira a cabeça e deixa você pendurado.
mae
55

Não exclua: apenas uma confirmação git cherry-pické suficiente.

Mas se você teve vários commits no branch errado, é aí que git rebase --ontobrilha:

Suponha que você tenha o seguinte:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, então você pode marcar mastere movê-lo para onde você deseja estar:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, redefina o ramo onde deveria estar:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

e, finalmente, mova seus commits (reaplique-os, fazendo realmente novos commits)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch
VonC
fonte
infelizmente, essa não era a questão.
usar o seguinte código
1
@KatariaA Essa é uma alternativa válida para excluir a confirmação feita na ramificação errada e ajudará outras pessoas na mesma situação (boa confirmação feita na ramificação errada).
VonC 21/02/19
14

Faça git rebase -i FAR_ENOUGH_BACKe solte a linha do commit que você não deseja.

Hank Gay
fonte
6

Se você deseja mover esse commit para outro ramo, obtenha o SHA do commit em questão

git rev-parse HEAD

Em seguida, alterne o ramo atual

git checkout other-branch

E cherry-picko compromisso deother-branch

git cherry-pick <sha-of-the-commit>
Alexander Groß
fonte
Da minha experiência, isso não desfaz o commit do ramo original, necessitando do git reset --hard HEAD~1posterior. Eu acho que usar a reset --softtroca de ramificações e confirmar novamente teria economizado trabalho extra. Então, novamente, eu estava usando o SourceTree para fazer a maioria das minhas coisas básicas, apenas alinhando-o com isso após o meu erro.
Jsopi # 30/15
3

Para sua referência, acredito que você pode "cortar com força" as confirmações de sua ramificação atual, não apenas com git reset --hard, mas também com o seguinte comando:

git checkout -B <branch-name> <SHA>

De fato, se você não se importa com o check-out, pode definir o ramo para o que quiser com:

git branch -f <branch-name> <SHA>

Essa seria uma maneira programática de remover confirmações de uma ramificação, por exemplo, para copiar novas confirmações para ela (usando rebase).

Suponha que você tenha uma ramificação desconectada do mestre porque você pegou fontes de algum outro local e as despejou na ramificação.

Agora você tem um ramo no qual aplicou alterações, vamos chamá-lo de "tópico".

Agora você criará uma duplicata do seu ramo de tópico e depois o rebatizará no dump do código-fonte que está localizado no ramo "dump":

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Agora, suas alterações são reaplicadas no ramo topic_duplicate, com base no ponto inicial de "dump", mas apenas nos commits que ocorreram desde o "master". Portanto, suas alterações desde o mestre agora são reaplicadas em cima de "dump", mas o resultado acaba em "topic_duplicate".

Você pode substituir "dump" por "topic_duplicate" fazendo o seguinte:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

Ou com

git branch -M topic_duplicate dump

Ou apenas descartando o lixo

git branch -D dump

Talvez você também possa escolher depois de limpar o atual "topic_duplicate".

O que estou tentando dizer é que, se você deseja atualizar o ramo "duplicado" atual com base em um ancestral diferente, você deve primeiro excluir os commits "cherrypicked" anteriormente fazendo um git reset --hard <last-commit-to-retain>ou git branch -f topic_duplicate <last-commit-to-retain>e depois copiando os outros commits over (a partir do main ramificação de tópico) rebasing ou cherry-picking.

A rebasagem funciona apenas em uma ramificação que já possui confirmações, portanto, você deve duplicar sua ramificação de tópico sempre que desejar fazer isso.

Cherrypicking é muito mais fácil:

git cherry-pick master..topic

Portanto, toda a sequência se resume a:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Quando o seu ramo duplicado de tópico tiver sido retirado. Isso removeria confirmações escolhidas anteriormente pela cereja do duplicado atual e apenas reaplicaria todas as alterações que aconteciam no "tópico", além do seu "despejo" atual (ancestral diferente). Parece uma maneira razoavelmente conveniente de basear seu desenvolvimento no mestre upstream "real" enquanto usa um mestre "downstream" diferente para verificar se suas alterações locais também se aplicam a isso. Como alternativa, você pode gerar um diff e aplicá-lo fora de qualquer árvore de fontes Git. Mas, dessa maneira, você pode manter uma versão modificada (corrigida) atualizada, baseada na versão da sua distribuição enquanto o seu desenvolvimento real é contra o verdadeiro mestre upstream.

Então, apenas para demonstrar:

  • redefinir fará sua ramificação apontar para uma confirmação diferente (--hard também verifica a confirmação anterior, --soft mantém arquivos adicionados no índice (que seriam confirmados se você confirmar novamente) e o padrão (--mixed) não será verifique o commit anterior (limpando as alterações locais), mas ele limpará o índice (nada foi adicionado para o commit ainda)
  • você pode apenas forçar um ramo a apontar para um commit diferente
  • você pode fazer isso enquanto verifica imediatamente esse commit também
  • rebasing funciona em confirmações presentes em sua filial atual
  • colheita de cereja significa copiar de um ramo diferente

Espero que isso ajude alguém. Eu pretendia reescrever isso, mas não posso gerenciar agora. Saudações.

Xennex81
fonte
0

O comando a seguir funcionou para mim, todas as alterações confirmadas locais são descartadas e o local é redefinido para o mesmo que origem remota / ramificação mestre.

origem do git reset --hard

Atul Sureka
fonte