Renomeie a filial Master para repositórios Git local e remoto
-
20-09-2019 - |
Pergunta
Eu tenho o ramo master
que rastreia o ramo remoto origin/master
.
Eu quero renomeá -los para master-old
localmente e no controle remoto. Isso é possível? Para outros usuários que rastrearam origin/master
(e quem sempre atualizou seus locais master
ramificação via git pull
), o que aconteceria depois que eu renomeei a filial remota? Seria o deles git pull
ainda funcionar ou causaria um erro que não conseguiu encontrar origin/master
não mais?
Então, mais adiante, quero criar um novo master
ramificação (local e controle remoto). Novamente, depois que eu fiz isso, o que aconteceria agora se os outros usuários fizessem git pull
?
Eu acho que tudo isso resultaria em muitos problemas. Existe uma maneira limpa de conseguir o que eu quero? Ou devo simplesmente sair master
como é e crie um novo ramo master-new
e apenas trabalhar lá mais adiante?
Solução
A coisa mais próxima de renomear é excluir e depois recriar no controle remoto. Por exemplo:
git branch -m master master-old
git push remote :master # delete master
git push remote master-old # create master-old on remote
git checkout -b master some-ref # create a new local master
git push remote master # create master on remote
No entanto, isso tem muitas advertências. Primeiro, nenhum caixa existente saberá sobre a renomear - o git faz não Tente rastrear renomeamentos de ramificação. Se o novo master
Ainda não existe, o git pull erra. Se o novo master
foi criado. A atração tentará se fundir master
e master-old
. Portanto, geralmente é uma má idéia, a menos que você tenha a cooperação de todos que fizeram o check -out do repositório anteriormente.
Nota: As versões mais recentes do Git não permitirão excluir a filial mestre remotamente por padrão. Você pode substituir isso definindo o receive.denyDeleteCurrent
valor de configuração para warn
ou ignore
no controlo remoto repositório. Caso contrário, se você estiver pronto para criar um novo mestre imediatamente, pule o git push remote :master
passo e passe --force
para o git push remote master
degrau. Observe que, se você não conseguir alterar a configuração do controle remoto, não poderá excluir completamente o ramo principal!
Esta ressalva se aplica apenas ao ramo atual (geralmente o master
ramo); Qualquer outro ramo pode ser excluído e recriado como acima.
Outras dicas
Supondo que você esteja atualmente master
:
git push origin master:master-old # 1
git branch master-old origin/master-old # 2
git reset --hard $new_master_commit # 3
git push -f origin # 4
- Primeiro faça um
master-old
ramo noorigin
repositório, com base nomaster
comprometer no repositório local. - Crie uma nova filial local para este novo
origin/master-old
ramificação (que será configurada automaticamente corretamente como uma ramificação de rastreamento). - Agora aponte seu local
master
Para qualquer comprometimento que você queira apontar. - Finalmente, mudança de força
master
noorigin
repositório para refletir seu novo localmaster
.
(Se você fizer isso de outra maneira, precisará de pelo menos mais uma etapa para garantir que master-old
está configurado corretamente para rastrear origin/master-old
. Nenhuma das outras soluções publicadas no momento da redação deste artigo incluem isso.)
Com o Git v1.7, acho que isso mudou um pouco. Atualizar a referência de rastreamento da filial local para o novo controle remoto agora é muito fácil.
git branch -m old_branch new_branch # Rename branch locally
git push origin :old_branch # Delete the old branch
git push --set-upstream origin new_branch # Push the new branch, set local branch to track the new remote
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name
Você pode ter que mudar manualmente para new-branch-name
antes de excluir old-branch-name
Existem muitas maneiras de renomear o ramo, mas vou me concentrar no maior problema: "Como permitir que os clientes sejam velozes e não precisam mexer com seus ramos localmente".
Isso é algo realmente fácil de fazer; Mas não abuse. Toda a ideia depende de cometidos de mesclagem; como eles permitem avançar rapidamente e vincular histórias de um ramo com outro.
renomear o ramo:
# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old
Criando o novo ramo "mestre":
# create master from new starting point
git branch master <new-master-start-point>
Criando uma mesclagem se compromete a ter um histórico de pai-filho:
# now we've got to fix the new branch...
git checkout master
# ... by doing a merge commit that obsoletes
# "master-old" hence the "ours" strategy.
git merge -s ours master-old
e pronto.
git push origin master
Isso funciona porque criando um merge
Commit permite Avanço rápido o ramo para uma nova revisão.
Usando uma mensagem sensata de compromisso de fusão:
renamed branch "master" to "master-old" and use commit ba2f9cc as new "master"
-- this is done by doing a merge commit with "ours" strategy which obsoletes
the branch.
these are the steps I did:
git branch -m master master-old
git branch master ba2f9cc
git checkout master
git merge -s ours master-old
Estou assumindo que você ainda está perguntando sobre a mesma situação que em seu pergunta anterior. Ou seja, o Master-New não conterá a Mestre-Old em sua história. Isso não importa Como as Você entra em um estado em que o mestre não é descendente de uma posição anterior de mestre, simplesmente que está nesse estado.
Outros usuários que tentam puxar enquanto o mestre não existem simplesmente terão suas falhas (não é esse ref em controle remoto) e, uma vez que existir novamente em um novo lugar, seus puxões terão que tentar mesclar seu mestre com o novo mestre remoto, Como se você tivesse fundido o mestre-mestre e o mestre-novo em seu repositório. Dado o que você está tentando fazer aqui, a mesclagem teria conflitos. (Se eles fossem resolvidos e o resultado foi empurrado de volta ao repositório, você estaria em um estado ainda pior - ambas as versões da história lá.)
Para responder sua pergunta simplesmente: você deve aceitar que às vezes haverá erros em sua história. Esta certo. Isso acontece com todos. Existem commits revertidos no repositório git.git. O importante é que, uma vez que publicamos a história, é algo que todos podem confiar.
*Se o fizesse, isso seria equivalente a empurrar algumas alterações no mestre e, em seguida, criar um novo ramo onde costumava estar. Sem problemas.
o resposta selecionada falhou quando eu tentei. Ele lança um erro: refusing to delete the current branch: refs/heads/master
. Acho que vou postar o que funciona para mim:
git checkout master # if not in master already
git branch placeholder # create placeholder branch
git checkout placeholder # checkout to placeholder
git push remote placeholder # push placeholder to remote repository
git branch -d master # remove master in local repository
git push remote :master # remove master from remote repository.
O truque é fazer o check -out para o espaço reservado antes de empurrá -lo para o repositório remoto. O resto é auto -explicativo, excluir o ramo principal e empurrá -lo ao repositório remoto deve funcionar agora. Extraído de aqui.
Bom. Meus 2 centavos. Que tal fazer login no servidor, ir ao diretório Git e renomear a ramificação no repositório nu. Isso não tem todos os problemas associados à reuppliação do mesmo ramo. Na verdade, os 'clientes' reconhecerão automaticamente o nome modificado e alterarão sua referência remota. Depois (ou antes), você também pode modificar o nome local da filial.
A respeito:
git checkout old-branch-name
git push remote-name new-branch-name
git push remote-name :old-branch-name
git branch -m new-branch-name
Esta é a maneira mais simples e mais 'legível' que conheço:
Filial Local 'Move' usando -m
git branch -m my_old_branch_name my_new_branch_name
Empurre o ramo 'movido' para o controle remoto, configurado 'upstream' usando -u
git push origin -u my_new_branch_name
(Configurando 'Upstream' essencialmente 'conecta' sua filial local ao controle remoto, para que coisas como buscar, puxar e empurrar funcionarão)
Exclua o ramo antigo do controle remoto
git push origin -D <old_name>
(Sua filial local já se foi, porque você 'moveu' na 1ª etapa)
Você pode fazer o seguinte:
git -m master master-old #rename current master
git checkout -b master #create a new branch master
git push -f origin master #force push to master
Mas a força de força é uma má idéia se outras pessoas estiverem compartilhando esse repositório. Force Push fará com que seu histórico de revisão entre em conflito com o novo.
OK, renomeando um ramo ambos localmente e em o remoto é muito fácil! ...
Se você estiver no ramo, poderá fazer facilmente:
git branch -m <branch>
Ou se não, você precisa fazer:
git branch -m <your_old_branch> <your_new_branch>
Em seguida, empurre a exclusão para o controle remoto assim:
git push origin <your_old_branch>
Agora você terminou, se você receber um erro rio acima enquanto tenta pressionar, basta fazer:
git push --set-upstream origin <your_new_branch>
Eu também crio a imagem abaixo para mostrar as etapas na linha de comando real, basta seguir as etapas e você seria bom:
O seguinte pode ser salvo no script do shell para fazer o trabalho:
Por exemplo:
remote="origin"
if [ "$#" -eq 0 ] # if there are no arguments, just quit
then
echo "Usage: $0 oldName newName or $0 newName" >&2
exit 1
elif
[ "$#" -eq 1 ] # if only one argument is given, rename current branch
then
oldBranchName="$(git branch | grep \* | cut -d ' ' -f2)" #save current branch name
newBranchName=$1
else
oldBranchName=$1
newBranchName=$2
fi
git branch -m $oldBranchName $newBranchName
git push $remote :$oldBranchName #delete old branch on remote
git push --set-upstream $remote $newBranchName # add new branch name on remote and track it
Observe que aqui o nome remoto padrão "Origin" é codificado, você pode estender o script para fazer se configurável!
Em seguida, esse script pode ser usado com aliases do Bash, aliases git ou, por exemplo, ações personalizadas de Sourcetree.
Eu acredito que a chave é a percepção de que você está realizando um em dobro Renomear: master
para master-old
e também master-new
para master
.
De todas as outras respostas, sintetizei o seguinte:
doublerename master-new master master-old
onde primeiro temos que definir o doublerename
Função Bash:
# doublerename NEW CURRENT OLD
# - arguments are branch names
# - see COMMIT_MESSAGE below
# - the result is pushed to origin, with upstream tracking info updated
doublerename() {
local NEW=$1
local CUR=$2
local OLD=$3
local COMMIT_MESSAGE="Double rename: $NEW -> $CUR -> $OLD.
This commit replaces the contents of '$CUR' with the contents of '$NEW'.
The old contents of '$CUR' now lives in '$OLD'.
The name '$NEW' will be deleted.
This way the public history of '$CUR' is not rewritten and clients do not have
to perform a Rebase Recovery.
"
git branch --move $CUR $OLD
git branch --move $NEW $CUR
git checkout $CUR
git merge -s ours $OLD -m $COMMIT_MESSAGE
git push --set-upstream --atomic origin $OLD $CUR :$NEW
}
Isso é semelhante a uma mudança de história git rebase
na medida em que o conteúdo da filial é bem diferente, mas difere para que os clientes ainda possam avançar com segurança com git pull master
.
git update-ref newref oldref
git update-ref -d oldref newref