Git: crie uma ramificação a partir de alterações não faseadas / não confirmadas no mestre

991

Contexto: estou trabalhando no master adicionando um recurso simples. Depois de alguns minutos, percebo que não era tão simples e deveria ter sido melhor trabalhar em um novo ramo.

Isso sempre acontece comigo e não tenho idéia de como alternar para outro ramo e levar todas essas alterações não confirmadas comigo, deixando o ramo mestre limpo. Eu git stash && git stash branch new_branchsimplesmente faria isso, mas é o que eu recebo:

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

~/test $ echo "hello!" > testing 

~/test $ git status
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

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

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

Você sabe se existe alguma maneira de conseguir isso?

knoopx
fonte
1
Embora exista uma solução mais simples para o seu problema, você poderia especificar em qual resultado o resultado difere do que queria?
Gauthier
2
ao fazer o acima ou as respostas na parte inferior, as alterações não confirmadas estão no mestre e no novo ramo. Eu quero que eles apenas no novo ramo, para que eu possa fazer o checkout mestre e trabalhar em outra coisa sem que essas mudanças flutuando
knoopx
1
veja minha resposta editada. Você precisa confirmar suas alterações locais na nova ramificação se quiser fazer checkout de um mestre limpo. Alterações locais são apenas as diferenças entre o HEAD atual e seus arquivos em disco. Essas alterações nos arquivos locais não são versionadas; você precisa dizer ao git para salvá-las em algum lugar, se quiser recuperá-las posteriormente.
quer

Respostas:

1207

Não há necessidade de esconder.

git checkout -b new_branch_name

não toca nas alterações locais. Ele apenas cria a ramificação a partir do HEAD atual e define o HEAD lá. Então eu acho que é isso que você quer.

--- Edite para explicar o resultado do mestre de checkout ---

Você está confuso porque checkout masternão descarta suas alterações?

Como as alterações são apenas locais, o git não deseja que você as perca com muita facilidade. Ao alterar a ramificação, o git não substitui as alterações locais. O resultado do seu checkout masteré:

M   testing

, o que significa que seus arquivos de trabalho não estão limpos. O git mudou o HEAD, mas não substituiu os arquivos locais. É por isso que seu último status ainda mostra as alterações locais, embora você esteja ativo master.

Se você realmente deseja descartar as alterações locais, é necessário forçar a finalização da compra -f.

git checkout master -f

Como suas alterações nunca foram confirmadas, você as perderia.

Tente retornar ao seu ramo, confirme as alterações e faça o checkout do master novamente.

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

Você deve receber uma Mmensagem após o primeiro check-out, mas não mais após o checkout mastere não git statusdeve exibir arquivos modificados.

--- Edite para esclarecer a confusão sobre o diretório de trabalho (arquivos locais) ---

Em resposta ao seu primeiro comentário, as alterações locais são apenas ... bem, locais. O Git não os salva automaticamente, você deve pedir para salvá-los para mais tarde. Se você fizer alterações e não as confirmar ou ocultar explicitamente, o git não as fará a versão. Se você alterar HEAD ( checkout master), as alterações locais não serão substituídas desde que não sejam salvas.

Gauthier
fonte
32
A coisa confusa aqui é que a página de manual do git afirma que git checkout“Atualiza os arquivos na árvore de trabalho para corresponder à versão no índice ou na árvore especificada.”. Isso pressupõe que suas alterações no seu sistema de arquivos serão GONE posteriormente. Sem chance de recuperá-los. Mesmo se você disser que não, isso ainda deixa um sentimento muito ruim. Eu não confio esta em tudo . A documentação é realmente ruim ou o comportamento padrão do git é realmente perigoso. Não é necessário confiar em alguma heurística "automagica" para detectar que, nesse caso, você não deseja perder suas alterações.
Evi1M4chine
16
Se você estiver verificando uma confirmação que substituirá as alterações locais (se o histórico entre a confirmação atual e a confirmação de destino tocar nos arquivos modificados localmente), o git se recusa. Somente se checkoutnão entrar em conflito com as alterações locais, o checkout funcionará e deixará as alterações locais em paz. No entanto, entendo o mau pressentimento, a página de manual talvez deva dizer "Atualiza arquivos não modificados na árvore de trabalho". Por outro lado, o Git não facilita demais a perda de alterações locais. git checkoutdeixa suas alterações locais em paz ou recusa se houver um conflito.
Gauthier
1
bem, como eu faria o checkout para outro ramo sem trazer as alterações locais para lá?
アレックス
5
@Alex git checkout <other_branch> -f. Você perderá suas alterações locais sem aviso prévio.
Gauthier
2
@ Evi1M4chine O primeiro. A documentação está muito ruim.
Qwertie 17/04
62

Tentar:

git stash
git checkout -b new-branch
git stash apply
Grant Limberg
fonte
6
Isso é diferente de apenas fazer 'git checkout -b new-branch' por si só?
Adrian Mouat
Eu não acho que foi quando a resposta foi originalmente escrita, mas eu posso estar errado. Infelizmente, devido às minhas circunstâncias de trabalho, tenho usado o forforce nos últimos anos, por isso não posso atestar sua precisão agora.
22813 Grant Limberg
6
Ou, em vez das duas últimas etapas: git branch esconderijo novo ramo
rethab
1
git stash de não é mais necessária
kory
Quando você já possui uma ramificação onde deseja colocar todas as suas coisas, o stash faz sentido para mim: (Eventualmente git fetch --all; para obter a ramificação remota na origem) git stash; git checkout <existing-branch>; aplicar git stash;
Paolof76
24

Duas coisas que você pode fazer:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

ou

git stash -u
git branch sillyname stash@{0}

( git checkout -<- o traço é um atalho para o ramo anterior em que você estava)

( git stash -u<- -usignifica que ele também leva alterações sem etapas)

Pylinux
fonte
7

Se você estiver usando o cliente GitHub Windows (como eu sou) e estiver em uma situação de alterações não confirmadas que deseja mover para uma nova ramificação, basta "Criar uma nova ramificação" através do cliente GitHub. Ele mudará para o ramo recém-criado e preservará suas alterações.

insira a descrição da imagem aqui

Tod Birdsall
fonte
que esconde as alterações antes de criar o novo ramo para que ele não mantê-los (versão 223 no Mac OS)
Fernando Gallego
2

Se você deseja que suas alterações não confirmadas atuais na ramificação atual sejam movidas para uma nova ramificação, use o comando a seguir para criar uma nova ramificação e copiar as alterações não confirmadas automaticamente.

git checkout -b branch_name

Isso criará um novo ramo a partir do seu ramo atual (supondo que seja mestre), copie as alterações não confirmadas e mude para o novo ramo.

Confirme suas alterações na nova ramificação.

git commit -m "First commit"

Como uma nova ramificação é criada, antes de enviá-la para remota, é necessário configurar o upstream. Use o comando abaixo para configurar o upstream e envie-o para remoto.

git push --set-upstream origin feature/feature/NEWBRANCH

Depois de pressionar este comando, um novo ramo será criado no controle remoto e seu novo ramo local será enviado para o controle remoto.

Agora, se você quiser jogar fora suas alterações não confirmadas da ramificação principal, use:

git checkout master -f

Isso descartará quaisquer alterações locais não confirmadas na finalização da compra.

Maverick
fonte
Como essa resposta difere da aceita?
kometen
Embora exista alguma sobreposição com a resposta aceita, isso fornece um guia passo a passo simples e também inclui as operações necessárias para enviar uma nova filial remotamente. Simples, claro e útil.
Kjartan
Esta resposta é clara e me ajudou muito.
Vadim
0

No mais recente cliente GitHub para Windows , se você tiver alterações não confirmadas, escolha criar uma nova ramificação.
Ele pergunta como lidar com esse cenário exato:

insira a descrição da imagem aqui

O mesmo se aplica se você simplesmente alternar a ramificação também.

Jerry Dodge
fonte