Como mesclar minhas alterações não confirmadas locais em outra ramificação do Git?

621

Como posso fazer o seguinte no Git?

Minha filial atual é branch1 e fiz algumas alterações locais. No entanto, agora percebo que realmente pretendia aplicar essas alterações ao branch2. Existe uma maneira de aplicar / mesclar essas alterações para que elas se tornem alterações locais na filial2 sem as comprometer na filial1?

Solsberg
fonte
2
Existe um ótimo tutorial do Git aqui no SO. É uma espécie de central para todas as perguntas do git no estouro de pilha.
Decio Lira

Respostas:

898

Como seus arquivos ainda não foram confirmados em branch1:

git stash
git checkout branch2
git stash pop

ou

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Como comentado por benjohn (consulte a git stashpágina do manual ):

Para também ocultar os arquivos atualmente não rastreados (adicionados recentemente), adicione o argumento -u, portanto:

git stash -u
VonC
fonte
2
Você é bem vindo. Mais exemplos de uso de stash em unethicalblogger.com/posts/2008/11/… .
VonC 17/02/09
2
Se você estiver procurando uma solução para o mesmo problema, mas com o TFS, a solução equivalente é arquivar suas alterações e use o TFS Power Tools para desmontar na ramificação correta usando a opção / migrate.
Xr280xr
1
Isso funcionou para mim. No entanto, eu também tive que criar uma filial local para o 'stash pop' funcionar. Faça checkout em stackoverflow.com/questions/1783405/git-checkout-remote-branch se algo semelhante estiver acontecendo com você.
mimoralea
21
Para também esconder arquivos atualmente untracked (recém-adicionado) , adicione o argumento -u, então: git stash -u.
Benjohn 24/07/2015
2
@Benjohn Bom ponto. Incluímos seu comentário na resposta para obter mais visibilidade.
VonC 24/07/2015
84

Esconderijo, confirmações temporárias e rebarbas podem ser um exagero. Se você ainda não adicionou os arquivos alterados ao índice, poderá fazer o checkout da outra ramificação.

git checkout branch2

Isso funcionará desde que nenhum arquivo que você esteja editando seja diferente entre branch1 e branch2. Isso deixará você no branch2 com as alterações de trabalho preservadas. Se eles forem diferentes, você poderá especificar que deseja mesclar suas alterações locais com as alterações introduzidas alternando ramificações com a -mopção de checkout.

git checkout -m branch2

Se você adicionou alterações ao índice, desfaça essas alterações primeiro com uma redefinição. (Isso preservará sua cópia de trabalho, apenas removerá as alterações em etapas.)

git reset
CB Bailey
fonte
3
Eu pensei que o esconderijo era "mais simples" de alguma forma, mas sua abordagem é melhor em levar em conta o diretório de trabalho em diferentes ramos. +1
VonC 17/02/09
6
Um checkout tradicional simples parecia mais adequado ao problema em questão. checkout é mais leve, apenas atualiza os arquivos que precisam ser alterados. Talvez seja mais fácil entender a abordagem do stash, ou talvez não seja óbvio o suficiente que o checkout seja 'seguro' nesse caso de uso.
22310 CB Bailey
Se checkout -mnão for "seguro" em alguma situação (talvez cause um conflito de mesclagem), o stash forneceria alguma vantagem (por exemplo, você pode soltar um stash pop)?
Craig McQueen
1
@craigMcQueen Você não pode desfazer um stash estourado, mas o stash reclamará de conflitos quando você o estourar. Você pode corrigir os conflitos e depois confirmar, mas o esconderijo original ainda está na pilha neste caso! :)
Shaun F
No caso de um conflito de mesclagem, os arquivos não são copiados como .orig?
jocull
13

Uma alternativa mais curta à abordagem de stash mencionada anteriormente seria:

Mova temporariamente as alterações para um esconderijo.

  1. git stash

Crie e alterne para um novo ramo e, em seguida, coloque o stash nele em apenas uma etapa.

  1. git stash branch new_branch_name

Então apenas adde commitas alterações para este novo ramo.

rbento
fonte
10

AVISO: Não para iniciantes do git.

Isso aparece o suficiente no meu fluxo de trabalho que quase tentei escrever um novo comando git para ele. O git stashfluxo usual é o caminho a seguir, mas é um pouco estranho. Eu costumo fazer um novo commit primeiro, pois se eu estiver analisando as alterações, todas as informações estarão frescas em minha mente e é melhor começar a git commitencontrar o que encontrei (geralmente uma correção de bug pertencente ao mestre que eu descobri enquanto trabalhava em um ramo de recursos) imediatamente.

Também é útil - se você se deparar com situações como essa muito - ter outro diretório de trabalho ao lado do atual, que sempre masterverifique a ramificação.

Então, como eu consegui isso é assim:

  1. git commit as alterações imediatamente com uma boa mensagem de confirmação.
  2. git reset HEAD~1 para desfazer o commit da ramificação atual.
  3. (opcional) continue trabalhando no recurso.

Às vezes mais tarde (de forma assíncrona) ou imediatamente em outra janela do terminal:

  1. cd my-project-master que é outro WD compartilhando o mesmo .git
  2. git reflog para encontrar a correção que acabei de fazer.
  3. git cherry-pick SHA1 do commit.

Opcionalmente (ainda assíncrono), você pode refazer o processo (ou mesclar) sua ramificação de recursos para obter a correção de bugs, geralmente quando você está prestes a enviar um PR e já limpou sua ramificação de recursos e o WD:

  1. cd my-project qual é o principal WD em que estou trabalhando.
  2. git rebase master para obter as correções.

Dessa forma, eu posso continuar trabalhando no recurso sem interrupções e não preciso me preocupar com git stashnada ou ter que limpar meu WD antes de um git checkout(e depois verificar a ramificação do recurso novamente.) E ainda ter todas as minhas correções para em mastervez de escondido no meu ramo de recursos.

IMO git stashe git checkouté uma PIA real quando você está trabalhando em um grande recurso.

chakrit
fonte
Alternativa interessante e válida para a minha resposta. +1
VonC
Você é mercurial? A my-project-masterpartilha os mesmos .gitfaz soar como ele. Por que não git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, então mais tarde (de forma assíncrona), enquanto em master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (ou até mesmo, para evitar ter que descobrir o SHA1, git rebase --onto master feature bugfixABCde onde você está atualmente. O que significa que você pode fazer isso diretamente após o git resetexposto acima feature.)
Gauthier
No entanto, o OP parece que eles não estão prontos para confirmar as alterações, nesse caso, checkout -mé apenas melhor.
Gauthier
2

Se fosse sobre alterações confirmadas, você deveria dar uma olhada no git-rebase, mas, como apontado no comentário do VonC, enquanto você está falando sobre alterações locais, o git-stash certamente seria a melhor maneira de fazer isso.

claf
fonte
Eu não entendo esta solução: ela reescreveria o histórico de confirmação do branch2 do branch1 ... por que obter todas as alterações confirmadas do branch1 no branch2 quando queremos apenas obter alterações locais não confirmadas do branch1 no branch2? ...
VonC
@VonC: concordou, neste caso, que a rebase obtém todas as alterações confirmadas desde a última mesclagem entre as ramificações na ramificação1. Não recebi o parâmetro "não confirmado" desta pergunta no início. rebase não é a boa resposta.
194
@claferri: pfew ... eu estava começando a ter dor de cabeça;) eu teria diminuído sua resposta, mas desde que eu publiquei uma, houve um "claro conflito de interesses". Com a sua postagem atualizada, não preciso votar agora. Obrigado :)
VonC 17/02/09
@VonC: da próxima vez, não hesite em votação para baixo, enquanto a minha resposta é tão errado quanto este;)
CLAF
1

As respostas dadas até o momento não são ideais, pois exigem muito trabalho desnecessário para resolver conflitos de mesclagem ou fazem muitas suposições que freqüentemente são falsas. É assim que se faz perfeitamente. O link é para o meu próprio site.

Como se comprometer com uma ramificação diferente no git

Você possui alterações não confirmadas nas my_branchquais deseja se comprometer master, sem confirmar todas as alterações my_branch.

Exemplo

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Explicação

Comece mesclando-se masterà sua filial, pois você precisará fazer isso de qualquer maneira e agora é o melhor momento para resolver qualquer conflito.

A -uopção (aka --include-untracked) em git stash -uimpede de perder arquivos untracked quando você fazer mais tarde git clean -f -ddentro master.

Depois git checkout master, é importante que você NÃO o faça git stash pop, porque precisará desse estoque mais tarde. Se você colocar o esconderijo criado em my_branche depois fazer git stashem master, você vai causar conflitos de mesclagem desnecessárias quando posteriormente se aplicam que esconderijo no my_branch.

git resetdesfaz tudo o que resulta git stash apply. Por exemplo, os arquivos que foram modificados no stash, mas não existem, mastersão testados como conflitos "excluídos por nós".

git checkout .e git clean -f -ddescarte tudo o que não foi confirmado: todas as alterações nos arquivos rastreados e todos os arquivos e diretórios não rastreados. Eles já estão salvos no stash e, se deixados master, causariam conflitos desnecessários de mesclagem ao voltar para my_branch.

O último git stash popserá baseado no original my_branche, portanto, não causará conflitos de mesclagem. No entanto, se o seu stash contiver arquivos não rastreados que você se comprometeu a dominar, o git reclamará que "Não foi possível restaurar arquivos não rastreados do stash". Para resolver este conflito, excluir esses arquivos de sua árvore de trabalho, em seguida git stash pop, git add ., e git reset.

Vladimir Kornea
fonte
2
Sua resposta não foi excluída porque estava vinculada ao seu site, mas porque era idêntica a essa outra resposta de uma conta diferente. Vejo que a outra conta tem o mesmo perfil que o seu, você está usando duas contas? Você pode mesclar as duas contas. Além disso, sinalize um mod para explicar a situação e você poderá obter sua resposta original (com o voto positivo) anulado.
1
Você não pode mantê-los separados se eles estão fundidas, mas você está autorizado a ter várias contas, contanto que você não usá-los para cometer votar fraude (ou tê-los interagir uns com os outros em geral). Explique sua situação a um mod. Além disso, a exclusão foi um erro honesto. Como você esperava que alguém dissesse que estava usando duas contas diferentes?
3
Você precisa sinalizar sua postagem e usar a opção Outros para chamar a atenção de um mod. Eles não prestarão atenção quando você editar sua resposta excluída. Eu já sinalizei suas postagens para atenção modesta, mas elas são muito ocupadas, portanto, seja paciente, elas poderão contatá-lo eventualmente.
1
Não poste conteúdo duplicado, principalmente de contas diferentes. Vote ou sinalize para fechar como duplicado se duas perguntas forem iguais.
Bill the Lizard