Como reverter aplicar um esconderijo?


233

Tenho um pequeno patch guardado no meu esconderijo git. Eu apliquei na minha cópia de trabalho usando git stash apply. Agora, eu gostaria de fazer o backup dessas alterações aplicando o patch inversamente (como o que git revertfaria, mas contra o esconderijo).

Alguém sabe como fazer isso?

Esclarecimento: Há outras alterações na minha cópia de trabalho. Meu caso particular é difícil de descrever, mas você pode imaginar algum código experimental ou de depuração que esteja no esconderijo. Agora está misturado em minha cópia de trabalho com outras alterações e eu gostaria de ver o efeito com e sem as alterações do estoque.

Atualmente, não parece que o stash suporte isso, mas um git stash apply --reverseseria um recurso interessante.


1
Não é possível apenas criar um patch invertido diferindo entre a revisão atual e a anterior? E depois aplicar esse?
Ralphtheninja 19/06/09

Existem alterações na árvore de trabalho que não sejam o stash aplicado?
Greg Bacon

Adicionando isso aqui, ... era para ser uma pergunta freqüente, não uma pergunta ... stackoverflow.com/questions/59973103/…
Don Thomas Boyle

Respostas:


188

De acordo com a página de manual do git-stash , "Um stash é representado como um commit cuja árvore registra o estado do diretório de trabalho e seu primeiro pai é o commit no HEADmomento em que o stash foi criado" e git stash show -pfornece "as alterações registradas no stash como uma diferença entre o estado stashed e seu pai original.

Para manter intactas as outras alterações, use git stash show -p | patch --reverseo seguinte:

$ git init
Initialized empty Git repository in /tmp/repo/.git/

$ echo Hello, world >messages

$ git add messages

$ git commit -am 'Initial commit'
[master (root-commit)]: created 1ff2478: "Initial commit"
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 messages

$ echo Hello again >>messages

$ git stash

$ git status
# On branch master
nothing to commit (working directory clean)

$ git stash apply
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   messages
#
no changes added to commit (use "git add" and/or "git commit -a")

$ echo Howdy all >>messages

$ git diff
diff --git a/messages b/messages
index a5c1966..eade523 100644
--- a/messages
+++ b/messages
@@ -1 +1,3 @@
 Hello, world
+Hello again
+Howdy all

$ git stash show -p | patch --reverse
patching file messages
Hunk #1 succeeded at 1 with fuzz 1.

$ git diff
diff --git a/messages b/messages
index a5c1966..364fc91 100644
--- a/messages
+++ b/messages
@@ -1 +1,2 @@
 Hello, world
+Howdy all

Editar:

Uma leve melhoria para isso é usar git applyno lugar do patch:

git stash show -p | git apply --reverse

Como alternativa, você também pode usar git apply -Rcomo abreviação de git apply --reverse.

Ultimamente tenho achado isso realmente útil ...


2
Incrível, obrigado. Parece que esse pode ser um bom recurso para esconderijo.
Pat Notz 21/06/2009

5
Sim, git apply -Ré uma melhoria, pelo menos para mim na minha caixa de janelas com o git bash, pois patch --reversetive problemas para localizar o arquivo a ser corrigido (nenhuma pista real de por que a alternativa funcionou). +1 e boa explicação
hakre

não seria melhor adicionar --indexassim git stash show -p | git apply --reverse --index. Como você não precisa mais adicionar no índice as alterações que são revertidas.
precisa saber é o seguinte

3
@ Greg Bacon, hey, eu tentei ir através do script que você delineado, mas o patch falhou quando eu corria git stash show -p | git apply -R -vcom a mensagem: Checking patch messages... error: while searching for: Hello, world Hello again error: patch failed: messages:1. Você sabe o que pode estar errado?
Max Koretskyi

5
Eu recebo erro: remendo falhou: /src/filename.java:46 erro: remendo src / filename.java não se aplica
Tim Boland

83

git stash[save]pega seu estado de diretório de trabalho e seu estado de índice e os esconde, definindo o índice e a área de trabalho para a HEADversão.

git stash applyrecupera essas alterações, portanto as git reset --hardremove novamente.

git stash poprecupera essas alterações e remove as alterações armazenadas no topo, git stash [save]retornando ao estado anterior (pré-pop) nesse caso.


82
git checkout -f

removerá quaisquer alterações sem confirmação.


4
obrigado, você me ajuda de uma mudança gradual que não foi aplicada.
Fa.Shapouri

1
Isso era muito mais simples
Mark A

Isso foi demais!
Kiran Sk

22

A página de manual do git V1 tinha uma referência sobre a não aplicação de um stash. O trecho está abaixo.

A página do manual git V2 mais recente não inclui nenhuma referência à desinstalação de um stash, mas o abaixo ainda funciona bem

Removendo a Aplicação de uma Stash Em alguns cenários de casos de uso, você pode aplicar alterações ocultas, faça algum trabalho, mas depois aplique as alterações que originalmente vieram do stash. O Git não fornece um comando de remoção de aplicação do stash, mas é possível obter o efeito simplesmente recuperando o patch associado a um stash e aplicando-o ao contrário:

$ git stash show -p stash@{0} | git apply -R

Novamente, se você não especificar um stash, o Git assumirá o stash mais recente:

$ git stash show -p | git apply -R

Você pode criar um alias e efetivamente adicionar um comando stash-unapply ao seu Git. Por exemplo:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply

1
Por qualquer motivo, esta seção útil que você vinculou " Desaplicando um Stash" foi removida da 2ª versão - A versão mais recente agora é 2.1.146, 2019-04-15 - deste livro V2- Git Tools - Stashing and Cleaning . Pode ser porque os autores pensam que há uma maneira melhor de fazer isso que eu não consigo encontrar.
Nad Alaba

@NadAlaba graças a cabeça para cima, ter atualizado a resposta para fazer a anotação na diferença entre v1 e v2 ... estranho os autores git removido a seção sobre-aplicação un um esconderijo
Choco Smith

13

Isso está muito atrasado, mas se eu interpretar o problema corretamente, encontrei uma solução simples, observe, esta é uma explicação em minha própria terminologia:

git stash [save] salvará as alterações atuais e definirá sua ramificação atual como "estado limpo"

git stash list dá algo como: stash@{0}: On develop: saved testing-stuff

git apply stash@{0}definirá o ramo atual como antes stash [save]

git checkout .Definirá o ramo atual como depois stash [save]

O código salvo no stash não é perdido, pode ser encontrado git apply stash@{0}novamente.

De qualquer forma, isso funcionou para mim!


Só para ter certeza, apliquei uma git stash apply --reverseprimeira e depois simplesmente voltei a git stash apply stash@{x}gostar de você mencionar. Trabalhou sem problemas.
Carlos Garcia

3

Como reverter aplicar um esconderijo?

Além do que os outros mencionaram, a maneira mais fácil é fazer primeiro

git reset HEAD

e depois efetue o check-out de todas as alterações locais

git checkout . 

Essa é de longe a maneira mais fácil, desde que você não tenha absolutamente nenhum trabalho local que queira salvar. Se você aplicou o stash errado a uma ramificação ou encontrou conflitos de mesclagem que não deseja resolver, esta é a maneira rápida e fácil de desfazê-la, revertendo completamente o conjunto de trabalho para a confirmação mais recente da ramificação.
Shadoninja 6/04

2

Além da resposta do @Greg Bacon, no caso de arquivos binários serem adicionados ao índice e fazer parte do stash usando

git stash show -p | git apply --reverse

pode resultar em

error: cannot apply binary patch to '<YOUR_NEW_FILE>' without full index line
error: <YOUR_NEW_FILE>: patch does not apply

A adição --binaryresolve o problema, mas infelizmente ainda não descobrimos o porquê.

 git stash show -p --binary | git apply --reverse

1

Você pode seguir a imagem que eu compartilhei para descompactar se você tocar acidentalmente em stashing.


0

Isso é um acréscimo às respostas acima, mas adiciona uma pesquisa ao stash git com base na mensagem, pois o número do stash pode mudar quando novos stash são salvos. Eu escrevi algumas funções do bash:

apply(){
  if [ "$1" ]; then
    git stash apply `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"`
  fi
}
remove(){
  if [ "$1" ]; then
    git stash show -p `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"` | git apply -R
    git status
  fi
}
  1. Criar stash com nome (mensagem) $ git stash save "my stash"
  2. Para aplicar o nome $ apply "my stash"
  3. Para remover o stash nomeado $ remove "my stash"
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.