Como posso desestabilizar meus arquivos novamente depois de fazer uma confirmação local?

268

Eu executei o seguinte comando

git add <foo.java>
git commit -m "add the foo.java file"

Como posso excluir meu commit local agora e descompactar foo.java?

Se eu digitar git reset --hard, descobri que ele reverte meu modificado foo.javapara o original.

Kit Ho
fonte

Respostas:

452

git reset --soft HEAD~1deve fazer o que quiser. Depois disso, você terá as primeiras alterações no índice (visíveis com git diff --cached) e as alterações mais recentes não serão realizadas. git statusficará assim:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.java
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   foo.java
#

Você pode fazer git add foo.javae confirmar as duas alterações ao mesmo tempo.

Antti
fonte
Editei a resposta: "Alterações a serem confirmadas" têm as primeiras alterações e "alterações não preparadas para confirmação" têm as segundas alterações.
Antti
4
O que é descrito nesta resposta é realmente o que git commit --amendfaz; mas com um fluxo de trabalho muito mais complicado. Isso não responde à pergunta do OP, apesar de dar uma boa direção ( git reset).
7heo.tk
2
Teve que substituir o '^' por um '~' para fazê-lo funcionar, para que ele se parecesse com: #git reset --soft HEAD~
Shahar
3
fazer git reset --soft CABEÇA ~ 1, então git reset CABEÇA
Joko Wandiro
resposta perfeita para o que eu quero!
DeepInJava 8/02
78

Usar:

git reset HEAD^

Isso faz uma redefinição "mista" por padrão, que fará o que você pediu; coloque foo.java no unstaged, removendo a confirmação mais recente.

Ryan Stewart
fonte
2
Você se importaria de me explicar o que é redefinição "mista", redefinição "soft" e redefinição "hard"?
Kit Ho
1
O manual de redefinição do @Kit Ho - git possui excelentes descrições destes.
13132 manojlds
4
@Kit, @manojlds: O mesmo acontece com stackoverflow.com/questions/2530060/… (plugue sem vergonha)
Cascabel
5
Essa é realmente a única resposta correta . As outras duas respostas vão encenar os arquivos novamente depois de fazer um commit.
7heo.tk
git reset --softnão funcionou, mas git reset HEAD^fez
wordsforthewise
43

Para mim, o seguinte é a maneira mais legível (portanto preferível) de fazer isso:

git reset HEAD~1

Em vez de 1, pode haver qualquer número de confirmações que você deseja desestabilizar.

Andrey Deineko
fonte
39

git reset --softé justamente isso: é como git reset --hard, mas não toca nos arquivos.

wRAR
fonte
4
Essa foi a explicação mais fácil de entender que já ouvi (em apenas 11 palavras)! Obrigado!
Phreakhead #
3
Essa resposta está errada. git reset"é como git reset --hardmas não toca nos arquivos." Não git reset --soft. git reset --softpreparará as mudanças, para que você não precise adicioná-las à preparação no caso de desejá-las, mas precisará git resetdelas (sim, uma segunda vez e sem a --soft) caso contrário. Portanto, essa resposta é curta, mas incorreta.
7heo.tk
12

Para desagrupar todos os arquivos em seu último commit -

git reset HEAD~

Lavika
fonte
8

"Redefinir" é a maneira de desfazer alterações localmente. Ao confirmar, você primeiro seleciona as alterações a serem incluídas no " git add " - isso é chamado de "teste". E uma vez que as mudanças são realizadas, você as " git confirma ".

Para voltar da preparação ou confirmação, você "redefine" o HEAD. Em uma ramificação, HEAD é uma variável git que aponta para o commit mais recente. Portanto, se você encenou, mas não se comprometeu, " git reset HEAD ". Isso faz o backup para o HEAD atual, retirando as alterações do palco. É uma abreviação de " git reset --misted HEAD ~ 0 ".

Se você já efetuou o commit, o HEAD já avançou; portanto, você precisa fazer o backup para o commit anterior. Aqui você " redefine HEAD ~ 1 " ou " redefine HEAD ^ 1 " ou " redefine HEAD ~ " ou " redefine HEAD ^ " - todas as referências HEAD menos um.

Qual é o melhor símbolo, ~ ou ^? Pense no ~ til como um fluxo único - quando cada confirmação tem um pai único e há apenas uma série de alterações em sequência, você pode fazer referência ao backup usando o til, como HEAD ~ 1, HEAD ~ 2, HEAD ~ 3, para pais, avós, bisavós etc. (tecnicamente, é encontrar o primeiro pai nas gerações anteriores).

Quando há uma mesclagem, as confirmações têm mais de um pai. É quando o cursor ^ entra em jogo - você pode se lembrar porque mostra os galhos se unindo. Usando o cursor, HEAD ^ 1 seria o primeiro pai e HEAD ^ 2 seria o segundo pai de um único commit - mãe e pai, por exemplo.

Portanto, se você está retornando apenas um salto em um commit de pai único, HEAD ~ e HEAD ^ são equivalentes - você pode usar qualquer um deles.

Além disso, a redefinição pode ser --soft , --mixed ou --hard . Uma reinicialização suave apenas faz o backup da confirmação - ela redefine o HEAD, mas não verifica os arquivos da confirmação anterior, portanto todas as alterações no diretório de trabalho são preservadas. E --soft reset nem limpa o cenário (também conhecido como índice ), portanto, todos os arquivos que foram testados ainda estarão no palco.

Uma redefinição --mixed (o padrão) também não faz check-out dos arquivos da confirmação anterior, portanto todas as alterações são preservadas, mas o estágio é limpo. É por isso que um simples " git reset HEAD " desaparecerá do palco.

Um --hard reset redefine o HEAD, e limpa o cenário, mas também verifica todos os arquivos do commit anterior e, portanto, substitui as alterações.

Se você enviou o commit para um repositório remoto, a redefinição não funciona tão bem. Você pode redefinir localmente, mas quando tentar enviar para o controle remoto, o git verá que o HEAD local está atrás do HEAD no ramo remoto e se recusará a enviar. Você pode forçar o empurrão, mas o git realmente não gosta de fazer isso.

Como alternativa, você pode ocultar suas alterações, se quiser mantê-las, confira o commit anterior , retire o stash das mudanças, prepare-as, crie um novo commit e faça o push.

HieroB
fonte
+1 para a explicação detalhada da operação. IMO, esta deve ser a resposta aceita!
ISAE
2

Digamos que você queira desestabilizar as alterações até as confirmações,

Onde os hashes de confirmação são os seguintes:

  • h1
  • h2 ...
  • hn
  • hn + 1

Em seguida, execute o seguinte comando:
git reset hn

Agora o HEAD estará em hn + 1. As alterações de h1 para hn não terão etapas.

Vasantha Ganesh K
fonte