Como substituir a filial local por filial remota inteiramente no Git?

779

Eu tenho dois ramos:

  1. filial local (aquela com quem trabalho)
  2. filial remota (pública, apenas confirmações bem testadas vão para lá)

Recentemente, eu estraguei seriamente minha filial local.

Como eu substituiria totalmente a filial local pela remota, para poder continuar meu trabalho de onde a filial remota está agora?

Eu já procurei no SO e fazer check-out localmente na filial remota não tem nenhum efeito.

YemSalat
fonte
1
Sei que a resposta aceita tem 1280 votos positivos, mas você deve realmente considerar alterar a resposta aceita por @TTT.
Jamie

Respostas:

1289
  1. Verifique se você verificou o ramo que está substituindo (no comentário de Zoltán ).
  2. Supondo que o mestre seja o ramo local que você está substituindo e que "origem / mestre" seja o ramo remoto para o qual você deseja redefinir:

    git reset --hard origin/master
    

Isso atualiza sua ramificação HEAD local para ter a mesma revisão que origem / mestre e --hardsincronizará essa alteração também no índice e na área de trabalho.

araqnid
fonte
4
Obrigado pela sua sugestão, eu estou com tanto medo de usar --hard e --force já, então escolhi a solução que não as usa.
YemSalat 9/02/12
13
@ KonstantinLevin: ah sim, o nome dessas opções é bastante irritante. git resetpor padrão, irá apontar novamente sua ramificação atual e sincronizar o índice. --softpulará a atualização do índice, --hardtambém sincronizará o espaço de trabalho. A minha própria experiência está usando --harda maior parte do tempo, exceto quando eu quiser desfazer cometer o último (que é apenas git reset HEAD^)
araqnid
9
Depois de ter mais experiência com o git, estou convencido de que é uma solução melhor, obrigado.
perfil completo de YemSalat
24
provavelmente você precisará buscar primeiro:git fetch origin remote_branch
b1r3k 30/07
53
Você deve observar que isso substituirá a ramificação em que você está atualmente com o conteúdo do master . Portanto, se você estiver em, por exemplo, um ramo de recurso, ele substituirá todos os seus commits por master, portanto, verifique o ramo que você está substituindo primeiro.
Zoltán
218

Isso é tão fácil quanto três etapas:

  1. Exclua sua filial local: git branch -d local_branch
  2. Busque a ramificação remota mais recente: git fetch origin remote_branch
  3. Reconstrua a filial local com base na remota: git checkout -b local_branch origin/remote_branch
Adam Smith
fonte
7
Na verdade, o que @araqnid disse é certo e mais conciso. Eu testei e você pode tentar também.
Adamsmith
Uau, o git checkout -b local_branch origin / remote_branch é ótimo! Eu sempre fazia isso em dois comandos separados. obrigado!
22413 Kendepelchin
11
Pode ser necessário fazer git branch -D local_branchna primeira etapa se sua ramificação não for mesclada.
Szeryf
obrigado, tive dificuldade ao usar o gitflow, depois de publicar um ramo e depois finalizá-lo, eu queria ir para o ramo excluído, e sua solução foi a única que funcionou, o pull parece não funcionar .. ou eu tenho não usá-lo bem #
0100 Decebal
2
devemos garantir que o ramo atual não seja o que deve ser excluído.
a_secenthusiast
43
git branch -D <branch-name>
git fetch <remote> <branch-name>
git checkout -b <branch-name> --track <remote>/<branch-name>
Sailesh
fonte
O que a parte --track faz?
eonist
3
@ GitSync, é isso que git help branchdiz --track. When creating a new branch, set up branch.<name>.remote and branch.<name>.merge configuration entries to mark the start-point branch as "upstream" from the new branch. This configuration will tell git to show the relationship between the two branches in git status and git branch -v. Furthermore, it directs git pull without arguments to pull from the upstream when the new branch is checked out. Corrigi este comando na resposta. Obrigado por levantar o ponto.
Sailesh
Assim, em termos leigos: ele adiciona a URL remota ao novo ramo. Então eles estão sincronizados para sempre. Por assim dizer.
eonist
2
Você pode dizer que é apenas por conveniência. Se o fizer git status, ele informará se o seu ramo local está à frente ou atrás do ramo remoto, se você os tiver associado. Além disso, você pode fazer git pull(ou push) em vez de completo, git pull <remote> <branch>se você já configurou sua filial para rastrear <remote/branch>.
Sailesh
22

Substitua tudo pelo ramo remoto; mas apenas a partir do mesmo commit sua filial local está ativada:

git reset --hard origin/some-branch

OU , obtenha as últimas da filial remota e substitua tudo:

git fetch origin some-branch
git reset --hard FETCH_HEAD

Como um aparte, se necessário, você pode eliminar arquivos e diretórios não rastreados que ainda não foram confirmados:

git clean -fd
um pouco menos
fonte
O git cleancomando fez isso por mim. git reset hard origin/masternão limpe os arquivos não rastreados. Obrigado!
Mornor
9

A maneira mais segura e completa de substituir a filial local atual pelo controle remoto:

git stash
git merge --abort
git rebase --abort
git branch -M yourBranch replaced_yourBranch
git fetch origin yourBranch:yourBranch
git checkout yourBranch

A stashlinha salva as alterações que você não confirmou. A branchlinha move sua ramificação para um nome diferente, liberando o nome original. A fetchlinha recupera a cópia mais recente do controle remoto. ocheckout linha recria a ramificação original como uma ramificação de rastreamento.

Ou como uma função bash:

replaceWithRemote() {
    yourBranch=${1:-`git rev-parse --abbrev-ref HEAD`}
    git stash
    git merge --abort
    git rebase --abort
    git branch -M ${yourBranch} replaced_${yourBranch}_`git rev-parse --short HEAD`
    git fetch origin ${yourBranch}:${yourBranch}
    git checkout ${yourBranch}
}

que renomeia a ramificação atual para algo como replace_master_98d258f.

Joshua S
fonte
Pode querer incluir git stash popnesse fluxo de trabalho. Se você deseja reaplicar seus arquivos escondidos.
eonist
O que você faz com galhos escondidos? Receio que ele apareça novamente em algum lugar no futuro, muito tempo depois que eu esqueci o que era.
Scott Biggs
1
@ScottBiggs Se você deseja remover a ramificação escondida, use "git stash clear".
Mark A. Durham
5

Estou meio surpreso que ninguém tenha mencionado isso ainda; Eu uso quase todos os dias:

git reset --hard @{u}

Basicamente, @{u}é apenas uma abreviação para o ramo upstream que seu ramo atual está rastreando. Por exemplo, isso normalmente equivale a origin/[my-current-branch-name]. É legal porque é independente de ramo.

Certifique-se de git fetchprimeiro obter a cópia mais recente da filial remota.

TTT
fonte
1
que parece muito bom, cansei de copiar e colar o nome do ramo para redefinir!
pedroct92 29/04
1
Eu tive alguns casos em que adicionei respostas a perguntas antigas, e minhas respostas chegaram à liderança. Espero que este faça.
Jamie
3

Isso pode ser feito de várias maneiras, continuando a editar essa resposta para espalhar uma melhor perspectiva de conhecimento.

1) Redefinir com força

Se você estiver trabalhando a partir da ramificação de desenvolvimento remoto, poderá redefinir HEAD para a última confirmação na ramificação remota, conforme abaixo:

git reset --hard origin/develop

2) Exclua a ramificação atual e faça o checkout novamente no repositório remoto

Considerando que você está trabalhando no ramo de desenvolvimento no repositório local, que é sincronizado com o ramo remoto / de desenvolvimento, você pode fazer o seguinte:

git branch -D develop
git checkout -b develop origin/develop

3) Interromper mesclagem

Se você estiver no meio de uma mesclagem incorreta (feita erroneamente com ramificação incorreta) e quiser evitar a mesclagem, volte para a ramificação mais recente, como abaixo:

git merge --abort

4) Abortar rebase

Se você estiver entre uma nova recuperação incorreta, poderá anular a solicitação de nova recuperação, conforme abaixo:

git rebase --abort
Amit Kaneria
fonte
2

Você pode fazer o que o @Hugo da @Laurent disse, ou pode usar git rebasepara excluir os commits que deseja se livrar, se souber quais. Eu costumo usar git rebase -i head~N(onde N é um número, permitindo que você manipule os últimos N commit) para esse tipo de operações.

ksol
fonte
Na verdade, foi o comando 'git rebase' que estragou tudo, depois algumas mesclagens forçadas e redefinições rígidas.
YemSalat 9/02/12
2

A resposta selecionada está absolutamente correta , no entanto, não me deixou com as últimas commit / pushes ...

Então para mim:

git reset --hard dev/jobmanager-tools
git pull  ( did not work as git was not sure what branch i wanted)

Como sei que quero definir temporariamente minha ramificação upstream por algumas semanas para uma ramificação específica (a mesma que mudei / fiz check-out anteriormente e fiz uma redefinição definitiva)

Então, depois de redefinir

git branch --set-upstream-to=origin/dev/jobmanager-tools
git pull
git status    ( says--> on branch  dev/jobmanager-tools 
Tom Stickel
fonte
1

Se você deseja atualizar o ramo que não está atualmente com check-out, você pode:

git fetch -f origin rbranch:lbranch
kqr
fonte
0

Conforme fornecido na explicação escolhida, o git reset é bom. Hoje em dia, porém, geralmente usamos submódulos: repositórios dentro de repositórios. Por exemplo, se você usa o ZF3 e o jQuery em seu projeto, provavelmente deseja que eles sejam clonados em seus repositórios originais. Nesse caso, o git reset não é suficiente. Precisamos atualizar os submódulos para a versão exata definida em nosso repositório:

git checkout master
git fetch origin master
git reset --hard origin/master
git pull

git submodule foreach git submodule update

git status

é o mesmo que você virá (cd) recursivamente para o diretório de trabalho de cada submódulo e será executado:

git submodule update

E é muito diferente de

git checkout master
git pull

porque os submódulos apontam não para ramificação, mas para a confirmação.

Nesse caso, quando você faz check-out manualmente de uma ramificação para 1 ou mais submódulos, pode executar

git submodule foreach git pull
Eugene Kaurov
fonte
Por favor, forneça uma explicação, especialmente quando responder perguntas deste tipo. Sua resposta não é útil como está.
Erik A
A resposta aceita já propõe git reset --hard. Isso agrega pouco valor.
Florisla
0
git reset --hard
git clean -fd

Isso funcionou para mim - o clean também mostrou todos os arquivos excluídos. Se ele indicar que você perderá alterações, precisará ocultar.

Travis Heeter
fonte
-6

A maneira mais feia, porém mais simples: exclua sua pasta local e clone o repositório remoto novamente.

Hugo
fonte
10
Ou simplesmente exclua o ramo e confira novamente.
21712 laurent
Sim, eu acho que isso é o que eu vou fazer se eu não encontrar como fazê-lo de uma forma menos 'feia'
YemSalat
2
Às vezes, é feio saber. Eu gostaria que as pessoas não votassem menos nas coisas apenas porque não são do jeito convencional: deve haver uma razão mais racional para a votação negativa ... e deve ser dada. Git é uma coisa que alcança resultados. Não é algum tipo de texto sagrado.
mike roedor
3
Eu não entendo as downvotes :-( Sim, é deselegante, etc. mas pode funcionar melhor em alguns casos ... desculpe @Hugo
silverdr
@ Hugo, concordou. Algo misterioso e malcheiroso aconteceu com o meu ramo de desenvolvimento local, e o líder da equipe e o gerente de engenharia sugeriram, entre soluções mais elegantes, apenas (compactar, copiar e salvar meu trabalho de recurso, em seguida) destruir o repositório local e reclinar.
AmitaiB 22/05/19