Tornar o ramo Git atual um ramo mestre


1657

Eu tenho um repositório no Git. Fiz uma ramificação, depois fiz algumas alterações no mestre e na ramificação.

Então, dezenas de confirmações depois, percebi que o ramo está em um estado muito melhor que o mestre, então quero que o ramo "se torne" o mestre e desconsidere as alterações no mestre.

Não posso mesclar, porque não quero manter as alterações no mestre. O que devo fazer?

Extra : Nesse caso, o mestre 'antigo' já foi pushenviado para outro repositório como o GitHub. Como isso muda as coisas?


2
Verifique respostas para a pergunta muito semelhante stackoverflow.com/q/2862590/151641
mloskot

4
Tinha um mesmo problema, porém eu simplesmente removido o mestre e renomeado outro ramo de dominar: stackoverflow.com/a/14518201/189673
jayarjo

10
@ jayarjo, você deve evitar isso, se puder, porque ele reescreverá a história e causará problemas para todos os outros na próxima tentativa de puxar o mestre.
Joelittlejohn 19/09/2013

3
É por isso que eu amo a resposta de @Jefromi. Nenhuma desconstrução da história do arquivo está em andamento.
precisa saber é o seguinte

Respostas:


2134

O problema com as outras duas respostas é que o novo mestre não tem o antigo mestre como ancestral; portanto, quando você pressiona, todo mundo fica bagunçado. Isto é o que você quer fazer:

git checkout better_branch
git merge --strategy=ours master    # keep the content of this branch, but record a merge
git checkout master
git merge better_branch             # fast-forward master up to the merge

Se você quiser que seu histórico seja um pouco mais claro, recomendo adicionar algumas informações à mensagem de confirmação de mesclagem para deixar claro o que você fez. Mude a segunda linha para:

git merge --strategy=ours --no-commit master
git commit          # add information to the template merge message

25
Nota sobre as "estratégias" de mesclagem do git: --strategy=oursé diferente de --strategy=recursive -Xours. Ou seja, o "nosso" pode ser uma estratégia em si (o resultado será o ramo atual, não importa o quê), ou passado como uma opção para a estratégia "recursiva" (traga as alterações de outros ramos e prefira automaticamente as alterações do ramo atual quando houver um conflito )
Kelvin

5
Eu tive que fazer a segunda linha git merge --strategy=ours master -m "new master"para que funcionasse.
Incandescentman

5
@Johsm Isso é exatamente o que a primeira frase da minha resposta está falando. Se você fizer isso, o novo mestre não terá o mesmo histórico que o antigo, o que é muito ruim se você deseja pressionar / puxar. Você precisa ter ancestralidade compartilhada para que funcione corretamente; se, em vez disso, você fizer o que está dizendo, quando tentar empurrá-lo, simplesmente falhará, a menos que você o force (porque isso é Ruim e está tentando impedi-lo) e, se você forçar, qualquer um que puxar posteriormente tentará mesclar o velho mestre e o novo mestre, o que provavelmente será um acidente de trem.
Cascabel

4
Se o editor vi durante a mesclagem aparecer, digite: w (para salvar): q (para sair do vi)
Tomas Kubes 27/10/16

9
Essa resposta funciona muito bem. Eu só queria acrescentar (para as pessoas que podem ser novas ou inseguras) que você precisará fazer isso git pushlogo após isso, se quiser que seu código seja transferido para remoto. Você pode ver um aviso como Your branch is ahead of 'origin/master' by 50 commits.Isso é esperado. Apenas empurre! : D
chapeljuice 26/06

388

Verifique se tudo foi enviado ao seu repositório remoto (GitHub):

git checkout master

Substitua "master" por "better_branch":

git reset --hard better_branch

Force o envio ao seu repositório remoto:

git push -f origin master

81
Esta é provavelmente a resposta que a maioria das pessoas está procurando. Todas as outras respostas com a mesclagem da estratégia BS não substituem totalmente a ramificação. Isso fez tudo como eu queria, simplesmente sobrescreva o ramo e empurre-o para cima.
Gubatron

31
embora isso seja realmente o que muitos estão procurando, deve-se notar que quaisquer outras cópias locais do repositório precisarão da git reset --hard origin/masterpróxima vez que quiserem puxar, caso contrário, o git tentará mesclar as mudanças em seu local (agora) divergente. Os perigos disso são explicados mais nesta resposta
7yl4r 27/03

3
Observe também que você precisa para ser autorizado a empurrar força para o repositório - por exemplo, em um ambiente de negócios isto não vai funcionar
inetphantom

A vantagem aqui também pode ser uma desvantagem, dependendo do que as pessoas querem. Se você deseja ir tão longe quanto substituir o histórico do mestre pelo histórico do outro ramo, esta é sua resposta.
b15 11/03

75

Edit: Você não disse que tinha empurrado para um repo público! Isso faz um mundo de diferença.

Existem duas maneiras, a maneira "suja" e a maneira "limpa". Suponha que seu ramo seja nomeado new-master. Esta é a maneira limpa:

git checkout new-master
git branch -m master old-master
git branch -m new-master master
# And don't do this part.  Just don't.  But if you want to...
# git branch -d --force old-master

Isso fará com que os arquivos de configuração sejam alterados para corresponder aos ramos renomeados.

Você também pode fazê-lo da maneira suja, o que não atualizará os arquivos de configuração. É o que se passa sob o capô do que foi dito acima ...

mv -i .git/refs/new-master .git/refs/master
git checkout master

2
Obrigado. Mais uma pergunta. Estou empurrando para o github. O que vai acontecer lá, se eu fizer isso?
Karel Bílek

3
@Karel: Isso criará um pouco de confusão para outros usuários; eles terão que redefinir seu mestre para o mestre do github. Se você quiser evitar causar problemas a eles, dê uma olhada na minha resposta.
Cascabel

6
@ Dietrick Epp: Não sei se é uma boa idéia sugerir o caminho sujo. Vai atrapalhar o rastreamento remoto, reflogs ... não consigo pensar em nenhum motivo para você fazer isso.
Cascabel

2
Ah, esse é um bom argumento. Você pode ter as duas coisas, no entanto: git branch old-master master; git branch -f master new-master. Crie a ramificação de backup atualizada e mova o mestre diretamente para o novo mestre. (E desculpe por erro ortográfico o seu nome, só notei isso)
Cascabel

2
@FakeName Eu não concluí que não havia razão para fazê-lo, apenas que não há razão para fazê-lo da maneira suja . Você pode fazer isso usando comandos normais (como no meu comentário anterior) e obter o mesmo resultado, exceto com os reflogs intactos e sem chance de burlar as coisas. E é garantido que funcione, pois você não está mexendo nos detalhes da implementação.
Cascabel

46

Renomeie a ramificação para master:

git branch -M branch_name master

11
Infelizmente, o git não rastreia as renomeações de ramificações, portanto, se você já transferiu seu repositório para um controle remoto e outras pessoas têm alterações locais em suas ramificações principais antigas locais, elas estarão com problemas.
thSoft

existe alguma diferença entre isso e git checkout master&&git reset --hard better_branch?
precisa saber é

26

Pelo que entendi, você pode ramificar a ramificação atual em uma ramificação existente. Em essência, isso substituirá o masterque você tiver no ramo atual:

git branch -f master HEAD

Depois de fazer isso, normalmente você pode enviar sua masterfilial local , possivelmente exigindo o parâmetro force aqui também:

git push -f origin master

Sem mesclagens, sem comandos longos. Simplesmente branche push- mas, sim, isso vai reescrever a história do masterramo, por isso, se você trabalha em uma equipe que você tem que saber o que está fazendo.




Como alternativa, descobri que você pode enviar qualquer ramo para qualquer ramo remoto, portanto:

# This will force push the current branch to the remote master
git push -f origin HEAD:master

# Switch current branch to master
git checkout master

# Reset the local master branch to what's on the remote
git reset --hard origin/master

Muito simples e funcionou perfeitamente! Dois comandos git simples e fáceis de entender. Meu repositório git é salvo e agora parece super limpo. Obrigado!
thehelix

16

Encontrei a resposta que queria na postagem do blog Substitua o ramo principal por outro ramo no git :

git checkout feature_branch
git merge -s ours --no-commit master
git commit      # Add a message regarding the replacement that you just did
git checkout master
git merge feature_branch

É essencialmente o mesmo que a resposta de Cascabel . Exceto que a "opção" que ele adicionou abaixo de sua solução já está incorporada no meu bloco de código principal.

É mais fácil encontrar esse caminho.

Estou adicionando isso como uma nova resposta, porque se precisar dessa solução mais tarde, quero ter todo o código que vou usar em um bloco de código.

Caso contrário, posso copiar e colar e ler os detalhes abaixo para ver a linha que eu deveria ter alterado - depois de executá-la.


14

As soluções fornecidas aqui (renomeando a ramificação em 'master') não insistem nas consequências para o repositório remoto (GitHub):

    -f
    --força

Normalmente, o comando se recusa a atualizar uma ref remota que não é um ancestral da ref local usada para substituí-la. Este sinalizador desativa a verificação. Isso pode fazer com que o repositório remoto perca confirmações; use-o com cuidado.

Se outras pessoas já realizaram seu repo, elas não poderão obter esse novo histórico mestre sem substituir o próprio mestre por esse novo ramo mestre do GitHub (ou lidar com muitas mesclagens).
Existem alternativas para uma força de empurrar git para repositórios públicos .
A resposta de Jefromi (mesclando as alterações certas de volta ao mestre original) é uma delas.


14

Encontrei esse método simples para funcionar da melhor maneira. Ele não reescreve o histórico e todos os check-ins anteriores da ramificação serão anexados ao mestre. Nada está perdido, e você pode ver claramente o que ocorreu no log de confirmação.

Objetivo: Tornar o estado atual da "ramificação" o "mestre"

Trabalhando em uma ramificação, confirme e envie suas alterações para garantir que seus repositórios locais e remotos estejam atualizados:

git checkout master      # Set local repository to master
git reset --hard branch  # Force working tree and index to branch
git push origin master    # Update remote repository

Depois disso, seu mestre será o estado exato do seu último commit da filial e seu log de confirmação principal mostrará todos os check-ins da filial.


10

Também é possível fazer o checkout de todos os arquivos da outra ramificação no master:

git checkout master
git checkout better_branch -- .

e depois confirme todas as alterações.


5

Para adicionar à resposta de Jefromi, se você não deseja colocar uma mesclagem sem sentido no histórico da sourceramificação, é possível criar uma ramificação temporária para a oursmesclagem e jogá-la fora:

git checkout <source>
git checkout -b temp            # temporary branch for merge
git merge -s ours <target>      # create merge commit with contents of <source>
git checkout <target>           # fast forward <target> to merge commit
git merge temp                  # ...
git branch -d temp              # throw temporary branch away

Dessa forma, a consolidação de mesclagem só existirá no histórico da targetramificação.

Como alternativa, se você não deseja criar uma mesclagem, basta pegar o conteúdo sourcee usá-lo para um novo commit em target:

git checkout <source>                          # fill index with contents of <source>
git symbolic-ref HEAD <target>                 # tell git we're committing on <target>
git commit -m "Setting contents to <source>"   # make an ordinary commit with the contents of <source>

3

Para mim, eu queria que meu demônio estivesse de volta ao mestre depois que estivesse à frente.

Enquanto estiver desenvolvendo:

git checkout master
git pull

git checkout develop
git pull

git reset --hard origin/master
git push -f

2

Minha maneira de fazer as coisas é a seguinte

#Backup branch
git checkout -b master_backup
git push origin master_backup
git checkout master
#Hard Reset master branch to the last common commit
git reset --hard e8c8597
#Merge
git merge develop

2

Se você estiver usando o eGit no Eclipse :

  • Clique com o botão direito do mouse no nó do projeto.
  • Escolha EquipeAvançadoRenomear Filial
  • Em seguida, expanda a pasta de rastreamento remoto .
  • Escolha a ramificação com o nome errado, clique no botão renomear e renomeie para qualquer que seja o novo nome.
  • Escolha o novo mestre e renomeie-o para mestre.

Eu fiz isso, mas não tenho certeza se funcionou. No github, nada mudou, mas nas extensões git, posso ver que o ramo foi renomeado.
Pramod

0

As etapas a seguir são executadas no navegador Git, desenvolvido pela Atlassian (servidor Bitbucket)

Fazendo {ramo atual} como master

  1. Faça uma ramificação mastere nomeie-a como duplicada principal.
  2. Faça uma ramificação de {current-branch} e nomeie-o como “{current-branch} -copy”.
  3. Na configuração do repositório (Bitbucket), altere "Ramificação padrão" para apontar para "duplicação mestre" (sem esta etapa, você não poderá excluir o mestre - "Na próxima etapa").
  4. Excluir ramificação “master” - fiz esta etapa na árvore de origem (você pode fazê-lo no navegador CLI ou Git)
  5. Renomeie “{current-branch}” para “master” e pressione push para o repositório (isso criará um novo branch “master” ainda que “{current-branch}” exista).
  6. Nas configurações do repositório, altere "Ramificação padrão" para apontar para "mestre".
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.