Renommer des succursales à distance dans Git

407

S'il existe un référentiel auquel j'ai uniquement git://accès (et que je ne fais que pousser + tirer), existe-t-il un moyen de renommer les branches de ce référentiel de la même manière que je le ferais localement git branch -m?

kdt
la source
48
La question liée "en double" demande de renommer une branche "à la fois localement et à distance". Cette question, cependant, demande uniquement comment renommer les branches à distance, ce qui permet une simplification. C'est ce que je fais pour renommer une branche sur le serveur sans avoir à la caisse et / ou créer une branche locale: git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth
1
@sschuberth: vous pouvez donner les deux commandes en une seule fois. Et cela devrait vraiment être la réponse à cette question.
Joachim Breitner
2
@JoachimBreitner Vous avez raison, j'ai déjà fait cette optimisation dans mon script .
sschuberth
1
@sschuberth, vous devriez poster votre commentaire comme réponse, car je l'aime mieux que les autres ci-dessous.
phatmann
C'est fait .
sschuberth

Réponses:

480

Il vous suffit de créer une nouvelle branche locale avec le nom souhaité, de la pousser vers votre télécommande, puis de supprimer l'ancienne branche distante:

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

Ensuite, pour voir l'ancien nom de branche, chaque client du référentiel devrait faire:

$ git fetch origin
$ git remote prune origin

REMARQUE: si votre ancienne branche est votre branche principale, vous devez modifier vos paramètres de branche principale. Sinon, lorsque vous exécutez $ git push origin :old-branch-name, vous obtenez l'erreur "suppression de la branche actuelle interdite" .

Sylvain Defresne
la source
8
Eh bien, si l'ancien et le nouveau nom sont les mêmes, cela signifie que vous n'avez pas besoin de renommer la branche, il est donc inutile d'exécuter la commande en premier lieu ;-)
Sylvain Defresne
9
Sûr. Je veux juste dire que si vous appelez cela de manière automatisée (en tant que partie fonctionnelle d'un autre script), vous pourriez tout aussi bien ne pas le faire faire la mauvaise chose si vous pouvez l'éviter.
Mysterious Dan
9
À la manière de Dan: réorganisez les commandes pour qu'elles fonctionnent toujours correctement. À la manière d'Earth Engine: n'oubliez pas de vérifier, sinon vous perdez des données. Je sais lequel je choisirais.
Doradus
2
Les utilisateurs peuvent simplement exécuter: git fetch origin --prune(pour récupérer efficacement les nouvelles branches et également se débarrasser des références qui ne se trouvent plus sur la télécommande).
DolphinDream
2
Peut utiliser -dou --deleteau lieu de :dans les versions plus récentes de git.
Zitrax
285

Si vous voulez vraiment renommer des branches à distance, sans renommer de branches locales en même temps , vous pouvez le faire avec une seule commande:

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

J'ai écrit ce script ( git-rename-remote-branch ) qui fournit un raccourci pratique pour faire ce qui précède facilement.

En tant que fonction 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
}

Pour intégrer le commentaire de @ ksrb : Ce que cela fait, c'est essentiellement deux poussées dans une seule commande, d'abord git push <remote> <remote>/<old_name>:refs/heads/<new_name>pour pousser une nouvelle branche distante basée sur l'ancienne branche de suivi à distance, puis git push <remote> :<old_name>pour supprimer l'ancienne branche distante.

sschuberth
la source
10
Pour ceux qui voudraient un alias de cette commande: rename = "! F () {git push origin origin / $ 1: refs / heads / $ 2: $ 1;}; f" ceci peut être utilisé comme> git rename <old_name> < nouveau_nom>
Jonathan Schmidt
33
Pour ceux qui sont curieux de savoir ce que signifie réellement cette commande, c'est essentiellement 2 poussées git push <remote>/<old_name>:refs/heads/<new_name>signifie pousser une nouvelle télécommande qui utilise l'ancienne télécommande comme src, puis git push [space]:<old_name> supprimer l'ancienne télécommande
ksrb
3
Pourquoi faut-il utiliser refs/heads/name? Ne pouvez-vous pas simplement utiliser namedirectement la première commande git push <remote> <remote>/<old_name>:<new_name>?
Drew Noakes
6
Non, car la branche distante <new_name>n'existe pas encore. Si la branche n'existe pas, Git vous oblige à utiliser le nom complet car sinon, vous <new_name>pourriez également faire référence à un nom de balise.
sschuberth
3
Nous utilisons cette approche dans notre système de build. La seule mise en garde que nous rencontrons est si elle refs/heads/<new_name> existe déjà. La suppression réussit toujours, entraînant <remote>/<old_name>uniquement sa suppression. Une vérification préalable peut facilement éviter cela.
Apeiron
172

Tout d'abord, passez à la succursale que vous souhaitez renommer:

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

Pour supprimer une ancienne branche de remote:

git push origin :old_branch
Shashank Hegde
la source
12
Lorsque vous poussez la branche renommée (new_branch) sur distante (origine), vous devez également définir son amont pour suivre la branche avec le nouveau nom (par exemple git push -u origin new_branch) sinon la branche renommée (new_branch) continuera à suivre l'origine / old_branch. Et une fois que vous supprimez le old_branch distant, le new_branch suivra toujours l'origine / old_branch, même si maintenant cette branche a disparu.
DolphinDream
@DolphinDream J'ai modifié la réponse pour inclure votre changement utile en amont.
mVChr
10

Sûr. Renommez simplement la branche localement, appuyez sur la nouvelle branche et appuyez sur une suppression de l'ancienne.

Le seul vrai problème est que les autres utilisateurs du référentiel n'auront pas de branches de suivi locales renommées.

Lily Ballard
la source
1
donc en essayant de supprimer le master, j'ai essayé $ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master Mais il se plaint: La destination refspec ne correspond à aucune référence existante sur la télécommande ni ne commence par refs /, et nous ne pouvons pas deviner un préfixe basé sur la référence source. erreur: impossible de pousser certaines références vers '../alpha/' La télécommande a vraiment une branche appelée master
kdt
2

TL; DR

"Renommer" une branche distante est en fait un processus en 2 étapes (pas nécessairement ordonné):

  • suppression de l'ancienne branche distante ( git push [space]:<old_name>comme l' explique ksrb );
  • pousser dans une nouvelle branche distante (différence entre quelques commandes de réponses ci-dessous).

Suppression

J'utilise TortoiseGit et quand j'ai essayé pour la première fois de supprimer la branche via la ligne de commande, j'ai obtenu ceci:

$ git push origin :in
  • fatal: 'origin' ne semble pas être un dépôt git

  • fatal: impossible de lire à partir du référentiel distant.

Veuillez vous assurer que vous disposez des droits d'accès appropriés et que le référentiel existe.

Cela était probablement dû au fait que pageant n'a pas chargé la clé privée (que TortoiseGit charge automatiquement dans pageant ). De plus, j'ai remarqué que les commandes TortoiseGit n'ont pas la originréférence (par exemple git.exe push --progress "my_project" interesting_local:interesting).

J'utilise également Bitbucket et, comme d'autres gestionnaires de git en ligne sur le Web (GitHub, GitLab), j'ai pu supprimer la branche distante directement via leur interface (page branches):

Supprimer la branche Bitbucket

Cependant, dans TortoiseGit, vous pouvez également supprimer des branches distantes via Parcourir les références :

Menu Parcourir les références

En cliquant avec le bouton droit sur une branche distante (liste des télécommandes), l' option Supprimer la branche distante apparaît:

Suppression d'une branche distante TortoiseGit

Pousser

Après avoir supprimé l'ancienne branche distante, j'ai poussé directement dans une nouvelle branche distante via TortoiseGit simplement en tapant le nouveau nom dans le champ Remote: de la fenêtre Push et cette branche a été automatiquement créée et visible dans Bitbucket .

Cependant, si vous préférez toujours le faire manuellement, un point qui n'a pas encore été mentionné dans ce fil est que -u= --set-upstream.

De la git pushdocumentation , -uest juste un alias de --set-upstream, donc les commandes dans les réponses de Sylvain ( -set-upstream new-branch) et Shashank ( -u origin new_branch) sont équivalentes, car la référence dist par défaut estorigin si aucune autre référence n'a été précédemment définie:

  • git push origin -u new_branch= à git push -u new_branch partir de la description des documents :

    Si la configuration est manquante, elle est par défaut origin.

En fin de compte, je n'ai pas tapé ou utilisé manuellement les commandes suggérées par les autres réponses ici, donc cela pourrait être utile à d'autres dans une situation similaire.

CPHPython
la source
le problème est que votre télécommande n'est pas appelée origin. Vous devez nommer votre télécommande lorsque vous l'obtiendrez en exécutant la commande git remote. Git fonctionne avec sshce qui implique que vous utilisez des clés publiques + privées. Je suppose que Autoload Putty keysTortoiseGit ne fait que charger automatiquement les clés nécessaires pour que vous puissiez faire quoi que ce soit avec votre référence à distance. La dernière chose est que ce git push -un'est pas un alias pour pousser dans une branche distante, c'est un alias pour pousser dans une branche distante qui a été créée localement et sa référence distante n'a pas encore cette branche .
juanecabellob
1
@juancab -uest un alias de --set-upstreamet "si la configuration est manquante, elle est par défautorigin ". Sylvain et Shashank l' utilisent pour pousser dans une branche distante nouvellement créée . Le problème clé peut être dû au fait que Pageant ne l' a pas chargé lorsque j'ai essayé git push origin :inle shell. Je ne comprends donc pas votre downvote, je viens de souligner les détails non traités dans les autres réponses, de les expliquer et de les résoudre.
CPHPython
Vous dites de mauvaises choses et une grande partie de cette réponse n'est pas liée à la question elle-même. Si vous montrez ce qui a fonctionné pour vous, je vous encourage à limiter la réponse à ce que cela a fonctionné et si vous voulez vraiment donner une explication, veuillez mieux vous informer. Btw: -uest un alias pour --set-upstreammais ce n'est pas un alias pour pousser dans une branche distante comme vous l'avez dit. Pour pousser dans une branche distante, vous avez uniquement besoin git push <remote>, et si ce n'est pas encore dans la télécommande, vous ajoutez git push -u <remote>. Par conséquent, -uest utilisé pour créer une référence de la branche dans la télécommande.
juanecabellob
1
@juancab peut-être que ce que vous avez jugé mauvais était principalement le phrasé d' alias ou le choix des mots. J'ai restructuré ma réponse et l'ai reformulée afin de fournir une explication complète de la ou des solutions que j'ai trouvées pour renommer une branche distante.
CPHPython
Je le reformulerais davantage. Cela a plus de sens maintenant, mais c'est encore trop long. Je serais plus spécifique au problème, c'est-à-dire que pour les utilisateurs de TortoiseGit, les solutions proposées ne fonctionneront pas. Vous racontez une histoire, c'est déroutant et cela évite aux utilisateurs de lire. Je vais modifier votre réponse avec une proposition.
juanecabellob
1

Je ne sais pas pourquoi mais la réponse de @Sylvain Defresne ne fonctionne pas pour moi.

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

Je dois désamorcer l'amont, puis je peux à nouveau définir le flux. Voici comment je l'ai fait.

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name
Arthur bryant
la source
0

Je ne sais pas si c'est vrai ou faux, mais j'ai poussé "l'ancien nom" de la branche vers le "nouveau nom" de la branche, puis j'ai supprimé l'ancienne branche entièrement avec les deux lignes suivantes:

git push origin old_branch:new_branch
git push origin :old_branch
EpicPandaForce
la source
Pour autant que je sache, c'est exactement ce que font toutes les autres réponses. Votre réponse est juste plus succincte.
Plus clair le
-1

Vous pouvez créer une nouvelle branche basée sur l'ancienne branche. Juste comme ça, puis supprimez l'ancienne branche, c'est fini !!!entrez la description de l'image ici

Pober Wong
la source
C'est GitHub, pas Git. ;)
Bouncner
-4

En plus des réponses déjà données, voici une version qui vérifie d'abord si la nouvelle branche existe déjà (afin que vous puissiez l'utiliser en toute sécurité dans un 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"

(le chèque provient de cette réponse )

myzzzl
la source
J'aurais utilisé git show-ref --quiet --verify -- refs/heads/$new_nameau lieu de ls-remote | cut | sed | grep.
Andy