Rinominare le filiali in remoto in Git


407

Se esiste un repository a cui ho git://accesso (e di solito spingerebbe + pull), c'è un modo per rinominare i rami in quel repository nello stesso modo in cui farei localmente git branch -m?


48
La domanda "duplicata" collegata chiede di rinominare un ramo "sia a livello locale che remoto". Questa domanda, tuttavia, chiede solo come rinominare i rami in remoto, il che consente una semplificazione. Questo è quello che faccio per rinominare un ramo sul server senza la necessità di cassa e / o creare una filiale locale: git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth,

1
@sschuberth: puoi dare entrambi i comandi in una volta sola. E questa dovrebbe davvero essere la risposta a questa domanda.
Joachim Breitner,

2
@JoachimBreitner Hai ragione, ho già fatto questa ottimizzazione in questa mia sceneggiatura .
sschuberth,

1
@sschuberth, dovresti pubblicare il tuo commento come risposta, dal momento che mi piace meglio degli altri sotto.
Phatmann,

Risposte:


480

Devi solo creare un nuovo ramo locale con il nome desiderato, inviarlo al tuo telecomando, quindi eliminare il vecchio ramo remoto:

$ git branch new-branch-name origin/old-branch-name
$ git push origin --set-upstream new-branch-name
$ git push origin :old-branch-name

Quindi, per vedere il vecchio nome del ramo, ogni client del repository dovrebbe fare:

$ git fetch origin
$ git remote prune origin

NOTA: se il vecchio ramo è il ramo principale, è necessario modificare le impostazioni del ramo principale. Altrimenti, quando si esegue $ git push origin :old-branch-name, verrà visualizzato l'errore "eliminazione del ramo corrente vietata" .


8
Bene, se i nomi vecchi e nuovi sono uguali, significa che non è necessario rinominare il ramo, quindi non ha senso eseguire il comando in primo luogo ;-)
Sylvain Defresne

9
Sicuro. Intendo solo che se lo chiami in modo automatizzato (in quanto parte di una funzione di qualche altro script) potresti anche non fargli fare la cosa sbagliata se puoi evitarlo.
Mysterious Dan,

9
Dan's way: riordina i comandi in modo che funzionino sempre. Il modo di Earth Engine: ricordati sempre di controllare o perdi i dati. So quale sceglierei.
Doradus,

2
Gli utenti possono semplicemente eseguire: git fetch origin --prune(per recuperare in modo efficace i nuovi rami e anche eliminare i riferimenti non più sul telecomando).
DolphinDream,

2
Può usare -do --deleteinvece che :nelle versioni più recenti di git.
Zitrax,

285

Se vuoi davvero solo rinominare i rami da remoto, senza rinominare i rami locali contemporaneamente , puoi farlo con un solo comando:

git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

Ho scritto questo script ( git-rename-remote-branch ) che fornisce un pratico collegamento per fare facilmente quanto sopra.

Come una funzione bash:

git-rename-remote-branch(){
  if [ $# -ne 3 ]; then
    echo "Rationale : Rename a branch on the server without checking it out."
    echo "Usage     : $(basename $0) <remote> <old name> <new name>"
    echo "Example   : $(basename $0) origin master release"
    exit 1 
  fi

  git push $1 $1/$2:refs/heads/$3 :$2
}

Per integrare il commento di @ ksrb : Ciò che sostanzialmente fa è due push in un singolo comando, prima git push <remote> <remote>/<old_name>:refs/heads/<new_name>di inviare un nuovo ramo remoto basato sul vecchio ramo di tracciamento remoto e poi git push <remote> :<old_name>di eliminare il vecchio ramo remoto.


10
Per coloro che desiderano un alias di quel comando: rename = "! F () {git push origin origin / $ 1: refs / heads / $ 2: $ 1;}; f" questo può essere usato come> git rename <old_name> < new_name>
Jonathan Schmidt,

33
Per chi è curioso di sapere cosa significhi in realtà questo comando è essenzialmente 2 push git push <remote>/<old_name>:refs/heads/<new_name>significa spingere un nuovo telecomando che utilizza il vecchio telecomando come src, quindi git push [space]:<old_name> eliminare il vecchio telecomando
ksrb

3
Perché hai bisogno di usare refs/heads/name? Non puoi semplicemente usare namedirettamente, facendo il primo comando git push <remote> <remote>/<old_name>:<new_name>?
Drew Noakes,

6
No, perché il ramo remoto <new_name>non esiste ancora. Se il ramo non esiste, Git richiede di utilizzare il nome completo, altrimenti <new_name>potrebbe fare riferimento anche al nome di un tag.
sschuberth,

3
Usiamo questo approccio nel nostro sistema di compilazione. L'unica avvertenza che incontriamo è se refs/heads/<new_name> esiste già. L'eliminazione ha ancora esito positivo, con conseguente eliminazione <remote>/<old_name>. Alcuni controlli prima mano possono facilmente evitarlo.
Apeiron,

172

Primo controllo alla filiale che si desidera rinominare:

git branch -m old_branch new_branch
git push -u origin new_branch

Per rimuovere un vecchio ramo da remote:

git push origin :old_branch

12
Quando si sposta il ramo rinominato (new_branch) su remoto (origine), è necessario impostarne anche l'upstream per tenere traccia del ramo con il nuovo nome (ad es. git push -u origin new_branch), Altrimenti il ​​ramo rinominato (new_branch) continuerà a tenere traccia dell'origine / old_branch. E dopo aver eliminato old_branch remoto, new_branch seguirà comunque l'origine / old_branch, anche se ora quel ramo non c'è più.
DolphinDream,

@DolphinDream Ho modificato la risposta per includere la tua utile modifica a monte.
mVChr,

10

Sicuro. Basta rinominare il ramo localmente, spingere il nuovo ramo e spingere una cancellazione del vecchio.

L'unico vero problema è che agli altri utenti del repository non verranno rinominati i rami di tracciamento locali.


1
quindi quando provo ad eliminare master, ho provato $ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master Ma si lamenta: la destinazione refspec non corrisponde a un riferimento esistente sul telecomando né inizia con refs / e non siamo in grado di indovinare un prefisso basato sul riferimento sorgente. errore: impossibile inviare alcuni riferimenti a '../alpha/' Il telecomando ha davvero un ramo chiamato master
kdt

2

TL; DR

"Rinominare" un ramo remoto è in realtà un processo in 2 fasi (non necessariamente ordinato):

  • cancellazione del vecchio ramo remoto ( git push [space]:<old_name>come spiegato da ksrb );
  • spingere in un nuovo ramo remoto (differenza tra un paio di comandi di risposta di seguito).

Eliminazione

Uso TortoiseGit e quando ho provato per la prima volta a eliminare il ramo dalla riga di comando, ho ottenuto questo:

$ git push origin :in
  • fatale: 'origine' non sembra essere un repository git

  • fatale: impossibile leggere dal repository remoto.

Assicurarsi di disporre dei diritti di accesso corretti e che il repository sia presente.

Ciò era probabilmente dovuto al fatto che il concorso non aveva la chiave privata caricata (che TortoiseGit carica automaticamente nel concorso ). Inoltre, ho notato che i comandi TortoiseGit non hanno il riferimento origin(es git.exe push --progress "my_project" interesting_local:interesting.).

Sto anche usando Bitbucket e, come altri gestori di git online del genere (GitHub, GitLab), sono stato in grado di eliminare il ramo remoto direttamente attraverso la loro interfaccia (pagina rami):

Elimina ramo Bitbucket

Tuttavia, in TortoiseGit è anche possibile eliminare i rami remoti tramite Sfoglia riferimenti :

Sfoglia il menu Riferimenti

Facendo clic con il pulsante destro del mouse su un ramo remoto (elenco telecomandi) viene visualizzata l' opzione Elimina ramo remoto :

TortoiseGit elimina ramo remoto

spingendo

Dopo aver eliminato il vecchio ramo remoto, ho inserito direttamente un nuovo ramo remoto tramite TortoiseGit semplicemente digitando il nuovo nome nel campo Remoto: della finestra Push e questo ramo è stato creato e visibile automaticamente in Bitbucket .

Tuttavia, se preferisci ancora farlo manualmente, un punto che non è stato ancora menzionato in questa discussione è che -u= --set-upstream.

Dai git pushdocumenti , -uè solo un alias di --set-upstream, quindi i comandi nelle risposte di Sylvain ( -set-upstream new-branch) e Shashank ( -u origin new_branch) sono equivalenti, dal momento che il riferimento remoto è predefinitoorigin se nessun altro riferimento è stato precedentemente definito:

  • git push origin -u new_branch= git push -u new_branch dalla descrizione dei documenti :

    Se manca la configurazione, per impostazione predefinita è origin.

Alla fine, non ho inserito manualmente o usato nessuno dei comandi suggeriti dalle altre risposte qui, quindi forse questo potrebbe essere utile ad altri in una situazione simile.


il problema è che il telecomando non viene chiamato origin. Devi nominare il tuo telecomando mentre lo ottieni dall'esecuzione del comando git remote. Git funziona con sshciò che implica che stai usando le chiavi pubbliche + private. Presumo che Autoload Putty keysTortoiseGit stia semplicemente caricando automaticamente le chiavi necessarie affinché tu possa fare qualsiasi cosa con il tuo riferimento remoto. L'ultima cosa è che git push -unon è un alias per l'invio in un ramo remoto, è un alias per l'inserimento in un ramo remoto creato localmente e il suo riferimento remoto non ha ancora questo ramo .
juanecabellob,

1
@juancab -uè un alias di --set-upstreame "se manca la configurazione, il valore predefinito èorigin ". Sylvain e Shashank lo usano per spingere in un ramo remoto appena creato . Il problema chiave potrebbe essere stato dovuto al fatto che il concorso non lo ha caricato quando ho provato git push origin :insulla shell. Quindi non capisco il tuo voto negativo, ho appena indicato il mio e i dettagli non affrontati in altre risposte, li ho spiegati e risolti.
CPHPython

Stai affermando cose sbagliate e gran parte di questa risposta non è correlata alla domanda stessa. Se stai indicando cosa ha funzionato per te, ti incoraggio a limitare la risposta a ciò che ha funzionato e se vuoi davvero dare una spiegazione, ti preghiamo di informarti meglio. A proposito: -uè un alias per --set-upstreamma non è un alias per spingere in un ramo remoto come hai detto. Per inserire un ramo remoto è necessario in modo univoco git push <remote>e se non si trova ancora nel telecomando, è necessario aggiungere git push -u <remote>. Pertanto, -uviene utilizzato per creare un riferimento al ramo nel telecomando.
juanecabellob,

1
@juancab forse quello che hai ritenuto sbagliato era principalmente l' alias frase o la scelta delle parole. Ho ristrutturato la mia risposta e la ho riformulata per fornire una spiegazione completa delle soluzioni che ho trovato per rinominare un ramo remoto.
CPHPython

Lo riformulerei ulteriormente. Adesso ha più senso, ma è ancora troppo lungo. Sarei più specifico al problema, ovvero affermare che per gli utenti di TortoiseGit le soluzioni proposte non funzioneranno. Stai raccontando una storia che è confusa e fa sì che gli utenti evitino di leggere. Modificherò la tua risposta con una proposta.
juanecabellob,

1

Non so perché ma la risposta di @Sylvain Defresne non funziona per me.

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

Devo disinserire l'upstream e quindi posso impostare nuovamente il flusso. Quanto segue è come l'ho fatto.

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name

0

Non so se questo è giusto o sbagliato, ma ho spinto il "vecchio nome" del ramo sul "nuovo nome" del ramo, quindi ho eliminato completamente il vecchio ramo con le seguenti due righe:

git push origin old_branch:new_branch
git push origin :old_branch

Per quanto ne so, questo è esattamente ciò che fanno tutte le altre risposte. La tua risposta è solo più concisa.
Più chiaro il

-1

È possibile creare un nuovo ramo basato sul ramo vecchio nome. Proprio così, quindi elimina il vecchio ramo, oltre !!!inserisci qui la descrizione dell'immagine


Questo è GitHub, non Git. ;)
Bouncner l'

-4

Aggiungendo alle risposte già fornite, ecco una versione che controlla prima se il nuovo ramo esiste già (quindi puoi tranquillamente usarlo in uno script)

if git ls-remote --heads "$remote" \
    | cut -f2 \
    | sed 's:refs/heads/::' \
    | grep -q ^"$newname"$; then
    echo "Error: $newname already exists"
    exit 1
fi
git push "$oldname" "$remote/$oldname:refs/heads/$newname" ":$oldname"

(il controllo è da questa risposta )


Avrei usato al git show-ref --quiet --verify -- refs/heads/$new_nameposto di ls-remote | cut | sed | grep.
Andy,
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.