git stash -> mescla alterações ocultas com as alterações atuais


187

Fiz algumas alterações no meu ramo e percebi que esqueci que havia escondido outras alterações necessárias no referido ramo. O que eu quero é uma maneira de mesclar minhas alterações ocultas com as alterações atuais.

Existe uma maneira de fazer isso?

É mais por conveniência. Acabei desistindo e comprometendo primeiro minhas alterações atuais, depois minhas ocultas, mas eu preferia colocá-las de uma só vez.


Provavelmente duplicada de stackoverflow.com/q/1360712/72178
ks1322

A resposta de Josué deve ser a resposta aceita. Este post do stackoverflow é o primeiro link do google para esta pergunta, dê a resposta certa para a internet!
Jérôme

Respostas:


272

Acabei de descobrir que, se suas alterações não confirmadas forem adicionadas ao índice (ou seja, "preparado", usando git add ...), então git stash apply(e, presumivelmente, git stash pop) fará realmente uma mesclagem adequada. Se não houver conflitos, você é de ouro. Caso contrário, resolva-os como de costume com git mergetool, ou manualmente, com um editor.

Para deixar claro, é desse processo que estou falando:

mkdir test-repo && cd test-repo && git init
echo test > test.txt
git add test.txt && git commit -m "Initial version"

# here's the interesting part:

# make a local change and stash it:
echo test2 > test.txt
git stash

# make a different local change:
echo test3 > test.txt

# try to apply the previous changes:
git stash apply
# git complains "Cannot apply to a dirty working tree, please stage your changes"

# add "test3" changes to the index, then re-try the stash:
git add test.txt
git stash apply
# git says: "Auto-merging test.txt"
# git says: "CONFLICT (content): Merge conflict in test.txt"

... o que provavelmente é o que você está procurando.


tl; dr

Corra git addprimeiro.


8
Um truque, mas, ei, funciona e parece ser a única maneira de fazer isso. Eu gostaria que houvesse git stash apply --forceou algo assim.
precisa

13
Na verdade, não é um hack - é uma melhoria sobre o que você deseja, pois é possível reverter facilmente para as alterações no índice.
Hoffmanc

2
Uau, esse comportamento é realmente pretendido pelo git?
Edi9999

9
Eu não acho que exista algo "pretendido" pelo git. Meu palpite é que agora qualquer coisa que o git faz isso acontece por acaso.
Profpatsch

5
Esta é a solução perfeita. Eu apenas fiz git add ., git stash applye depois git resetaplicar o stash para as minhas alterações de trabalho e fusão sem ter que fazer commits.
Stephen Smith

70

Em execução git stash popou git stash applyé essencialmente uma mesclagem. Você não precisaria confirmar suas alterações atuais, a menos que os arquivos alterados no stash também sejam alterados na cópia de trabalho; nesse caso, você teria visto esta mensagem de erro:

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Nesse caso, você não pode aplicar o estoque às suas alterações atuais em uma única etapa. Você pode confirmar as alterações, aplicar o stash, confirmar novamente e esmagar essas duas confirmações usando git rebasese você realmente não quiser duas confirmações, mas isso pode causar mais problemas do que vale a pena.


1
Recebi essa mensagem - as alterações não entram em conflito, mas compartilham os mesmos arquivos, por aí usando stashes / apply's?
Bemis

1
Desculpe, foi isso que eu quis dizer com "conflitos de mesclagem", mas essa foi uma má escolha de palavras. Eu acho que essa mensagem de erro é bastante final: se os arquivos alterados na cópia de trabalho também forem alterados no stash, você não poderá aplicá-lo. Atualizei minha resposta com uma possível solução alternativa.
Brandan

3
Eu não consideraria isso uma resposta em todos os casos. Você pode ter ocultado apenas parte de um conjunto de alterações em um arquivo específico porque queria testar algo durante o desenvolvimento. E você pode não querer confirmar o conteúdo atual do arquivo neste momento (ou nem todo), pois é WIP. É um verdadeiro problema com git que as mudanças escondidas não podem ser fundidas ao ramo atual
Thomas Watson

21
A resposta de Joshua Warner deve ser marcada como correta. Para mesclar um stash, prepare suas alterações, aplique o stash, lide com quaisquer conflitos e, em seguida (se desejado), desinstale as alterações.
Vroo

4
"Você pode confirmar as alterações, aplicar o stash, confirmar novamente e compactar esses dois commits usando git rebase se você realmente não quiser dois commits, mas isso pode causar mais problemas do que vale a pena." Em vez disso, você pode fazer: Confirmar as alterações, aplicar a ocultação e, em seguida git commit --amend.
gabe

27

O que eu quero é uma maneira de mesclar minhas alterações ocultas com as alterações atuais

Aqui está outra opção para fazer isso:

git stash show -p|git apply
git stash drop

git stash show -pmostrará o patch do último stash salvo. git applyirá aplicá-lo. Após a fusão, o stash mesclado pode ser descartado git stash drop.


1
Obrigado por isso - não sei por git stash popque não faz isso apenas nos casos em que a mesclagem se aplica
corretamente

Versão estendida: git stash show -p --no-color | git apply --3way( --3way= volte à mesclagem de 3 vias se o patch falhar).
DmitrySandalov

Mas git stash show -pcria uma diferença entre o conteúdo oculto e a confirmação quando a entrada stash foi criada . Portanto, isso substituirá o arquivo de trabalho que o OP fez.
Paul F. Wood

Por que substituir? O diff produzido com git stash show -pserá mesclado por git apply, se possível sem conflitos.
ks1322 16/02

1

O jeito que eu faço isso é com git addisso primeiro então git stash apply <stash code>. É a maneira mais simples.


4
Como isso não é uma cópia exata da resposta aceita?
RomainValeri 14/03/19

0

Conforme sugerido por @Brandan, aqui está o que eu precisava fazer para me locomover

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Siga este processo:

git status  # local changes to `file`
git stash list  # further changes to `file` we want to merge
git commit -m "WIP" file
git stash pop
git commit -m "WIP2" file
git rebase -i HEAD^^  # I always use interactive rebase -- I'm sure you could do this in a single command with the simplicity of this process -- basically squash HEAD into HEAD^
# mark the second commit to squash into the first using your EDITOR
git reset HEAD^

E você ficará com alterações locais totalmente mescladas em file, pronto para realizar mais trabalhos / limpeza ou fazer uma única confirmação válida. Ou, se você souber que o conteúdo mesclado fileestará correto, escreva uma mensagem apropriada e pule git reset HEAD^.


0

Pode ser que não seja a pior idéia de mesclar (via difftool) de ... sim ... um ramo!

> current_branch=$(git status | head -n1 | cut -d' ' -f3)
> stash_branch="$current_branch-stash-$(date +%yy%mm%dd-%Hh%M)"
> git stash branch $stash_branch
> git checkout $current_branch
> git difftool $stash_branch

0

você pode facilmente

  1. Confirme suas alterações atuais
  2. Retire o stash do seu esconderijo e resolva conflitos
  3. Confirmar alterações do stash
  4. Redefinição suave para confirmar de onde você está vindo (última confirmação correta)

-1

Outra opção é fazer outro "git stash" das alterações locais não confirmadas e combinar os dois git stash. Infelizmente, o git parece não ter uma maneira de combinar facilmente dois esconderijos. Portanto, uma opção é criar dois arquivos .diff e aplicá-los - pelo menos não é um commit extra e não envolve um processo de dez etapas: |

Como: https://stackoverflow.com/a/9658688/32453


Isso transforma o problema de aplicar um diff em um problema de aplicar dois diffs. Além disso, a solução aceita não envolve uma confirmação, apenas um estágio e é apenas um único comando (git add). (Eu não sou o downvoter.)
Eike

Para mim, pelo menos, parece mais simples, menos mágica de vodu ... felicidades!
Rogerdpack #
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.