Rinomina il ramo master per i repository Git sia locali che remoti


821

Ho il ramo master che traccia il ramo remoto origin/master.

Voglio rinominarli master-old sia localmente che sul telecomando. È possibile?

Per gli altri utenti che hanno monitorato origin/master(e che hanno sempre aggiornato la propria masterfiliale locale tramite git pull), cosa sarebbe successo dopo aver rinominato la filiale remota?
Sarebbe lorogit pull ancora o genererebbe un errore che non è origin/masterpiù possibile trovare ?

Quindi, più avanti, voglio crearne uno nuovo master ramo (sia a livello locale che remoto). Ancora una volta, dopo averlo fatto, cosa accadrebbe ora se lo facessero gli altri utenti git pull?

Immagino che tutto ciò comporterebbe molti problemi. C'è un modo pulito per ottenere ciò che voglio? O dovrei semplicemente andarmene mastercosì com'è e creare una nuova filiale master-newe continuare a lavorare lì?


2
La ricetta indicata nella risposta accettata si applica a un ramo di qualsiasi nome, ma le avvertenze (come notato) non lo fanno, a causa del ruolo speciale (di default) del ramo principale in Git.
kynan,

3
@kynan: penso di non capire. Quali avvertenze si applicano al master e non si applicano ad altri rami? Se sarebbe un ramo di nome xy e altre persone hanno rintracciato quel ramo, come sarebbe diverso?
Albert,

4
L'avvertenza che normalmente non è possibile eliminare il master remoto. Ciò non si applica alla risposta di Aristotele, quindi potresti voler contrassegnarla come risposta accettata. Hai ragione, qualsiasi git push -finfluenza la capacità di pullqualsiasi ramo di tracciamento remoto.
kynan,

puoi creare un nuovo ramo master-oldche punta allo stesso commit del masterramo precedente . Quindi puoi sovrascrivere il masterramo con le tue nuove modifiche facendo un mergecon la oursstrategia. Fare un'unione funziona quando il telecomando non consente modifiche non rapide. Ciò significa anche che altri utenti non avranno aggiornamenti forzati.
Dnozay

1
@kynan masterè speciale solo se è l'unico ramo esistente. Non appena ne hai più di uno, tutti i rami sono su un piano di parità.
jub0bs,

Risposte:


615

La cosa più vicina alla ridenominazione è l'eliminazione e la successiva creazione sul telecomando. Per esempio:

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

Tuttavia, questo ha molti avvertimenti. Innanzitutto, nessun checkout esistente sarà a conoscenza della ridenominazione - git non tenta di tracciare le rinominazioni dei rami. Se il nuovo masternon esiste ancora, git pull si spegnerà. Se il nuovo masterè stato creato. il pull tenterà di unire mastere master-old. Quindi è generalmente una cattiva idea a meno che tu non abbia la collaborazione di tutti coloro che hanno verificato il repository in precedenza.

Nota: le versioni più recenti di git non ti permetteranno di eliminare il ramo master in remoto per impostazione predefinita. È possibile sovrascriverlo impostando il receive.denyDeleteCurrentvalore di configurazione su warno ignoresul repository remoto . Altrimenti, se sei pronto a creare subito un nuovo master, salta il git push remote :masterpassaggio e passa --forceal git push remote masterpassaggio. Nota che se non sei in grado di cambiare la configurazione del telecomando, non sarai in grado di eliminare completamente il ramo principale!

Questo avvertimento si applica solo al ramo corrente (di solito il masterramo); qualsiasi altro ramo può essere cancellato e ricreato come sopra.


2
i rami sono solo una coppia (nome, hash) - niente di più, niente di meno. C'è il reflog sui rami, ma questo non è mai esposto ai client remoti.
bdonlan,

122
Vorrei creare master-old sul telecomando prima di eliminare master sul telecomando. Sono solo paranoico.
Adam Dymitruk, l'

6
La risposta di Aristotele qui sotto ti consente di farlo senza eliminare il maestro, quindi penso che sia preferibile.
Clay Bridges,

13
sarebbe chiaro e SICURO se si potesse usare new-branch-namee old-branch-nameinvece di master/ master-old, quindi questo è un problema generale.
Jaider,

2
Se il ramo cancellato (qui: master) non è referenziato da altri rami, git potrebbe spazzare via tutti i commit su quel ... beh ... "ramo". - Alcuni comandi di git porcelain attivano una garbage collection. - Pertanto: crea prima il nuovo nome (puntando allo stesso commit), quindi elimina il vecchio nome.
Robert Siemer,

257

Supponendo che tu sia attualmente su 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
  1. Per prima cosa crea un master-oldramo nel originrepository, basato sumaster commit nel repository locale.
  2. Creare un nuovo ramo locale per questo nuovo origin/master-oldramo (che verrà automaticamente impostato correttamente come ramo di tracciamento).
  3. Ora punta il tuo locale mastera qualunque impegno tu voglia che indichi.
  4. Infine, modifica forzata masternel originrepository per riflettere il tuo nuovo locale master.

(Se lo fai in qualsiasi altro modo, hai bisogno di almeno un altro passaggio per assicurarti che master-oldsia impostato correttamente per tenere traccia origin/master-old. Nessuna delle altre soluzioni pubblicate al momento della stesura di questo documento lo include.)


11
Questa è una risposta migliore della "risposta", sono d'accordo, ma per le persone che sono venute qui solo per rinominare un ramo (non esplicitamente master), il terzo passo non ha molto senso.
Knocte,

Non fa assolutamente alcuna differenza la risposta se ci si trova mastero in un altro ramo. La domanda era mal intitolata, però, chiede un'attività più complessa della semplice ridenominazione di un ramo.
Aristotele Pagaltzis,

3
Questa si è rivelata la soluzione che ha funzionato per me. Stavo cercando di sostituire il maestro con un altro ramo. Ho fatto un log git -1 origin / what_i_want_as_new_master per ottenere $ new_master_commit per il passaggio 3. Dopo il push (passaggio 4), altri sviluppatori tiravano e ricevevano messaggi "il tuo ramo è in vantaggio rispetto a 295 commit". Per risolvere questo problema, ho inviato un'e-mail per far loro sapere ad ogni corsa: git pull; git checkout some_random_branch; ramo git -D master; git pull; git checkout master; Fondamentalmente, devono rimuovere il loro master locale ed estrarre la nuova versione, altrimenti si trovano nel posto sbagliato localmente.
nairbv,

Avresti potuto farlo molto più facilmente: supponendo che fossero già masterattivi, avrebbero potuto fare semplicemente git fetch && git reset --hard origin/masterper forzare il loro locale mastera essere uguale a quello attivo origin. Ho documentato questa, così come il caso più complesso in cui si dispone di commit locali in cima masterche si desidera conservare, in stackoverflow.com/q/4084868
Aristotele Pagaltzis

Assicurati che il file di configurazione remoto abbia "denyNonFastforwards = false" o otterrai "remote: errore: negazione di refs / heads / master non avanzati (dovresti tirare prima)"
gjcamann

160

Con Git v1.7, penso che questo sia leggermente cambiato. L'aggiornamento del riferimento di tracciamento della tua filiale locale al nuovo telecomando è ora molto semplice.

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

10
Un'alternativa --set-upstreamè la seguente: Una volta che il tuo ramo è stato rinominato localmente e cancellato sull'origine, fai semplicemente: git push -u --all
lucente

4
Questo non funzionerà con il ramo master, poiché git non ti permetterà di eliminare il master remoto.
Alexandre Neto,

4
@AlexandreNeto In questo caso è possibile eseguire la terza riga prima della seconda, impostare il ramo predefinito su new_branche infine eliminare il telecomando mastercon la seconda riga.
Tristan Jahier,

3
Passaggi incredibilmente semplici. Questa è la migliore risposta alla domanda
siddhusingh,

13
Per eliminare il ramo remoto git push origin --delete old_branchè leggermente più leggibile.
ThomasW

35
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

Potrebbe essere necessario passare manualmente a new-branch-nameprima di eliminareold-branch-name


Qualche parte di questa soluzione elimina il vecchio nome di filiale locale o è un esercizio sereno?
GreenAsJade,

4
Penso che alla fine debba essere eseguito git branch -d old-branch-nameper eliminare il vecchio ramo locale.
Nabi KAZ,

Puoi inviare le modifiche con un solo comando: git push remote-name new-branch-name :old-branch-name .
sigod

In questo modo non complicherai la storia di git? Perché stai aprendo un nuovo ramo invece semplicemente rinominando quello attuale.
androidevil,

1
@androider No. Branches in git è un semplice riferimento .
sigod

29

Esistono molti modi per rinominare il ramo, ma mi concentrerò sul problema più grande: "come consentire ai clienti di avanzare rapidamente e non dover fare confusione con i loro rami a livello locale" .

Prima una breve foto: rinominare il ramo master e consentire ai clienti di avanzare rapidamente

Questo è qualcosa di veramente facile da fare; ma non abusarne. L'intera idea si basa su commit di unione; poiché consentono l'avanzamento rapido e collegano le storie di un ramo con un altro.

rinominare il ramo:

# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old

creando il nuovo ramo "master":

# create master from new starting point
git branch master <new-master-start-point>

creazione di un commit di unione per avere una cronologia padre-figlio:

# 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 voilà.

git push origin master

Questo funziona perché la creazione di un mergecommit consente l'avanzamento rapido del ramo a una nuova revisione.

utilizzando un messaggio di commit merge sensibile:

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

3
Grazie! git merge -s ours master-oldè il pezzo cruciale che manca alle altre risposte. Inoltre, "facile da fare" non significa "facile da capire, o scoprire", che sembra essere il caso di gran parte di git, ma sto divagando.
Martin Vidner,

3
Adoro il fatto che non vengano menzionate soppressioni e che la transizione per coloro che lavorano con cloni di upstream sia "senza soluzione di continuità". Grazie!
Piotrek,

12

Suppongo che stai ancora facendo domande sulla stessa situazione della tua domanda precedente . Cioè, master-new non conterrà master-old nella sua storia. * Se chiami master-new "master", avrai effettivamente riscritto la cronologia. Non importa come si entra in uno stato in cui il master non è un discendente di una precedente posizione di master, semplicemente che si trova in quello stato.

Gli altri utenti che tentano di eseguire il pull mentre il master non esiste semplicemente falliranno i loro pull (nessuna tale ref sul telecomando) e una volta che esiste di nuovo in un nuovo posto, i loro pull dovranno tentare di unire il loro master con il nuovo master remoto, proprio come se avessi unito master-old e master-new nel tuo repository. Dato quello che stai cercando di fare qui, l'unione avrebbe dei conflitti. (Se fossero stati risolti e il risultato fosse riportato nel repository, saresti in uno stato ancora peggiore - entrambe le versioni della storia lì.)

Per rispondere semplicemente alla tua domanda: dovresti accettare che a volte ci saranno errori nella tua storia. Questo va bene. Succede a tutti. Ci sono commit ripristinati nel repository git.git. L'importante è che una volta che pubblichiamo la storia, è qualcosa di cui tutti possono fidarsi.

* In caso affermativo, ciò equivarrebbe a inviare alcune modifiche al master e quindi a creare un nuovo ramo dove prima si trovava. Nessun problema.


Sì, è lo stesso problema, era solo un'idea di come risolverlo. Ma anche se non volessi fare questo ridenominazione di branca, ero interessante se fosse possibile. Pensavo che riferimenti come "master" fossero solo riferimenti a commit specifici. Non voglio davvero cambiare nessuna storia. Pensavo di indicare il riferimento principale a un'altra testa. Questo significa anche che non potrò mai più usare un nome di ramo se l'ho mai usato prima?
Albert,

In effetti, i rami sono ref - puntatori a commit. Il fatto è che ci aspettiamo che il capo di un ramo si evolva in un modo particolare (vale a dire, sempre avanti veloce). Dal punto di vista di qualcun altro, spostare un ramo nel tuo repository pubblico equivale a riscrivere la storia del ramo. Non punta più a un commit contenente tutto ciò a cui era abituato.
Cascabel,

8

La risposta selezionata non è riuscita quando l'ho provata. Si genera un errore: refusing to delete the current branch: refs/heads/master. Immagino che posterò ciò che funziona per me:

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.

Il trucco è di fare il checkout al segnaposto subito prima di inviarlo al repository remoto. Il resto è autoesplicativo, l'eliminazione del ramo master e il push nel repository remoto dovrebbero funzionare ora. Estratto da qui .


Non funzionerebbe con git push remote: master se questo è selezionato sul lato remoto - vedrai "remote: error:" come prefisso nelle righe del log degli errori.
rafalmag,

2

Buona. I miei 2 centesimi. Che ne dici di accedere al server, andare alla directory git e rinominare il ramo nel repository nudo. Ciò non ha tutti i problemi associati al re-caricamento dello stesso ramo. In realtà, i "client" riconosceranno automaticamente il nome modificato e cambieranno il loro riferimento remoto. Successivamente (o prima) è anche possibile modificare il nome locale del ramo.


8
Ho dimenticato le credenziali per accedere al server github. Qualcuno con le credenziali là fuori :-P
Daniel Fisher lennybacon,

1

Che dire:

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

rovina il monitoraggio delle filiali: gli utenti potrebbero dover riparare la propria filiale localmente?
dnozay,

1

Questo è il modo più semplice e "leggibile" che conosco:

'Sposta' il ramo locale usando -m

git branch -m my_old_branch_name my_new_branch_name

Spingere il ramo "spostato" sul telecomando, impostare "a monte" usando -u

git push origin -u my_new_branch_name

(l'impostazione 'upstream' essenzialmente 'collega' il tuo ramo locale al telecomando, in modo che cose come prendere, tirare e spingere funzionino)

Elimina il vecchio ramo dal telecomando

git push origin -D <old_name>

(la tua filiale locale è già sparita, perché l'hai spostata nel primo passaggio)


1

OK , rinominando un ramo sia localmente che sul telecomando è abbastanza facile! ...

Se sei sul ramo, puoi facilmente fare:

git branch -m <branch>

o in caso contrario, devi fare:

git branch -m <your_old_branch> <your_new_branch>

Quindi, premi la cancellazione sul telecomando in questo modo:

git push origin <your_old_branch>

Ora hai fatto, se ricevi un errore a monte mentre provi a spingere, fai semplicemente:

git push --set-upstream origin <your_new_branch>

Creo anche l'immagine qui sotto per mostrare i passaggi nella riga di comando reale, basta seguire i passaggi e saresti buono:

inserisci qui la descrizione dell'immagine


0

Puoi fare quanto segue:

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

Ma forzare la spinta è una cattiva idea se altre persone condividono questo repository. La spinta forzata farà sì che la loro cronologia delle revisioni sia in conflitto con quella nuova.


0

Per eseguire il lavoro è possibile salvare quanto segue nello script della shell:

Per esempio:

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

Si noti che qui il nome remoto predefinito "origine" è codificato, è possibile estendere lo script per renderlo configurabile!

Quindi questo script può essere utilizzato con alias bash, alias git o, ad esempio, in azioni personalizzate sourcetree.


-1

Credo che la chiave sia la realizzazione che stai eseguendo un doppio rinomino: masterto master-olde anche master-newto master.

Da tutte le altre risposte ho sintetizzato questo:

doublerename master-new master master-old

dove dobbiamo prima definire la doublerenamefunzione 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
}

Ciò è simile a un cambio di cronologia git rebasein quanto il contenuto della filiale è piuttosto diverso, ma differisce dal fatto che i clienti possono ancora avanzare in modo sicuro con sicurezza git pull master.


-5
git update-ref newref oldref
git update-ref -d oldref newref

2
Questo non sembra funzionare per me, ottengo: git update-ref trunk trunk2 fatale: trunk2: non un SHA1 valido
Gregg Lind
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.