Renombrar sucursales de forma remota en Git

407

Si hay un repositorio al que solo tengo git://acceso (y generalmente solo presionaría + jalar), ¿hay alguna forma de cambiar el nombre de las sucursales en ese repositorio de la misma manera que lo haría localmente git branch -m?

kdt
fuente
48
La pregunta "duplicada" vinculada pide cambiar el nombre de una rama "localmente y remotamente". Sin embargo, esta pregunta solo pregunta cómo cambiar el nombre de las sucursales de forma remota, lo que permite una simplificación. Esto es lo que hago para cambiar el nombre de una rama en el servidor sin la necesidad para obtener y / o crear una sucursal local: git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth
1
@sschuberth: puedes dar ambos comandos de una vez. Y esta realmente debería ser la respuesta a esta pregunta.
Joachim Breitner
2
@JoachimBreitner Tienes razón, ya hice esa optimización en este script mío.
sschuberth
1
@sschuberth, debe publicar su comentario como respuesta, ya que me gusta más que los otros a continuación.
phatmann
Hecho .
sschuberth

Respuestas:

480

Solo tiene que crear una nueva sucursal local con el nombre deseado, insertarla en su control remoto y luego eliminar la rama remota anterior:

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

Luego, para ver el nombre de la rama anterior, cada cliente del repositorio tendría que hacer:

$ git fetch origin
$ git remote prune origin

NOTA: Si su rama anterior es su rama principal, debe cambiar la configuración de su rama principal. De lo contrario, cuando ejecute $ git push origin :old-branch-name, obtendrá el error "se prohíbe la eliminación de la rama actual" .

Sylvain Defresne
fuente
8
Bueno, si los nombres antiguos y nuevos son iguales, significa que no necesita cambiar el nombre de la rama, por lo que no tiene sentido ejecutar el comando en primer lugar ;-)
Sylvain Defresne
99
Por supuesto. Solo quiero decir que si está llamando a esto de forma automatizada (como parte de una función de otro script), es mejor que no haga que haga lo incorrecto si puede evitarlo.
Mysterious Dan
99
A la manera de Dan: reordena los comandos para que siempre funcionen. La forma de Earth Engine: recuerde siempre verificar o perderá datos. Sé cuál elegiría.
Doradus
2
Los usuarios pueden simplemente ejecutar: git fetch origin --prune(para buscar efectivamente las nuevas ramas y también deshacerse de las referencias que ya no están en el control remoto).
DolphinDream
2
Se puede usar -do en --deletelugar de :en versiones más nuevas de git.
Zitrax
285

Si realmente solo desea cambiar el nombre de las sucursales de forma remota, sin cambiar el nombre de las sucursales locales al mismo tiempo , puede hacerlo con un solo comando:

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

Escribí este script ( git-rename-remote-branch ) que proporciona un práctico acceso directo para hacer lo anterior fácilmente.

Como una función 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
}

Para integrar el comentario de @ksrb : lo que esto básicamente hace es dos empujes en un solo comando, primero git push <remote> <remote>/<old_name>:refs/heads/<new_name>para empujar una nueva rama remota basada en la antigua rama de seguimiento remoto y luego git push <remote> :<old_name>eliminar la rama remota anterior.

sschuberth
fuente
10
Para aquellos que desean un alias de ese comando: rename = "! F () {git push origin origin / $ 1: refs / heads / $ 2: $ 1;}; f" esto se puede usar como> git rename <old_name> < nuevo_nombre>
Jonathan Schmidt
33
Para aquellos curiosos sobre lo que este comando realmente significa que es esencialmente 2 empujones git push <remote>/<old_name>:refs/heads/<new_name>significa empujar un nuevo control remoto que usa el control remoto anterior como un src, luego git push [space]:<old_name> significa eliminar el control remoto anterior
ksrb
3
¿Por qué necesitas usar refs/heads/name? ¿No puedes usar namedirectamente, haciendo el primer comando git push <remote> <remote>/<old_name>:<new_name>?
Drew Noakes
66
No, porque la rama remota <new_name>aún no existe. Si la rama no existe, Git requiere que use el nombre completo, ya que de lo contrario <new_name>también podría referirse a un nombre de etiqueta.
sschuberth
3
Utilizamos este enfoque en nuestro sistema de compilación. La única advertencia que encontramos es si refs/heads/<new_name> ya existe. La eliminación aún tiene éxito, lo que resulta en que <remote>/<old_name>solo se elimine. Algunas comprobaciones antes de la mano pueden evitar esto fácilmente.
Apeiron
172

Primer pago a la rama a la que desea cambiarle el nombre:

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

Para eliminar una rama vieja de remote:

git push origin :old_branch
Shashank Hegde
fuente
12
Cuando empuja la rama renombrada (new_branch) a remota (origen) también debe establecer su flujo ascendente para rastrear la rama con el nuevo nombre (por ejemplo git push -u origin new_branch), de lo contrario la rama renombrada (new_branch) continuará rastreando el origen / old_branch. Y una vez que elimine el old_branch remoto, el new_branch seguirá rastreando el origen / old_branch, aunque ahora esa rama haya desaparecido.
DolphinDream
@DolphinDream Edité la respuesta para incluir su útil cambio aguas arriba.
mVChr
10

Por supuesto. Simplemente cambie el nombre de la rama localmente, presione la nueva rama y presione una eliminación de la antigua.

El único problema real es que otros usuarios del repositorio no cambiarán el nombre de las ramas de seguimiento locales.

Lily Ballard
fuente
1
así que cuando trato de eliminar master, he intentado $ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master Pero se queja: El destino refspec no coincide con una referencia existente en el control remoto ni comienza con refs /, y no podemos adivinar un prefijo basado en la referencia de origen. error: error al insertar algunas referencias a '../alpha/' El control remoto realmente tiene una rama llamada master
kdt
2

TL; DR

"Renombrar" una rama remota es realmente un proceso de 2 pasos (no necesariamente ordenado):

  • eliminación de la antigua rama remota ( git push [space]:<old_name>como explica ksrb );
  • presione en una nueva rama remota (la diferencia entre un par de comandos de respuestas a continuación).

Borrando

Uso TortoiseGit y cuando intenté eliminar la rama por primera vez a través de la línea de comando, obtuve esto:

$ git push origin :in
  • fatal: 'origen' no parece ser un repositorio git

  • fatal: no se pudo leer desde el repositorio remoto.

Asegúrese de tener los derechos de acceso correctos y de que exista el repositorio.

Esto probablemente se debió a que el concurso no tenía cargada la clave privada (que TortoiseGit carga automáticamente en el concurso ). Además, noté que los comandos de TortoiseGit no tienen la originreferencia en ellos (por ejemplo git.exe push --progress "my_project" interesting_local:interesting).

También estoy usando Bitbucket y, como otros administradores de git en línea basados ​​en la web (GitHub, GitLab), pude eliminar la rama remota directamente a través de su interfaz (página de ramas):

Eliminar rama Bitbucket

Sin embargo, en TortoiseGit también puede eliminar ramas remotas a través de las referencias de exploración :

Examinar el menú de referencias

Al hacer clic derecho en una rama remota (lista de controles remotos), aparece la opción Eliminar rama remota :

TortoiseGit borrar sucursal remota

Emprendedor

Después de eliminar la antigua rama remota, empujé directamente a una nueva rama remota a través de TortoiseGit simplemente escribiendo el nuevo nombre en el campo Remoto: de la ventana Empujar y esta rama se creó automáticamente y fue visible en Bitbucket .

Sin embargo, si aún prefiere hacerlo manualmente, un punto que aún no se ha mencionado en este hilo es que -u= --set-upstream.

De los git pushdocumentos , -ues solo un alias de --set-upstream, por lo que los comandos en las respuestas de Sylvain ( -set-upstream new-branch) y Shashank ( -u origin new_branch) son equivalentes, ya que la referencia remota se establece de manera predeterminadaorigin si no se definió previamente ninguna otra referencia:

  • git push origin -u new_branch= git push -u new_branch de la descripción de los documentos :

    Si falta la configuración, su valor predeterminado es origin.

Al final, no escribí manualmente ni utilicé ninguno de los comandos sugeridos por las otras respuestas aquí, por lo que quizás esto podría ser útil para otros en una situación similar.

CPHPython
fuente
El problema es que no se llama a su control remoto origin. Debe asignar un nombre a su control remoto a medida que lo obtiene al ejecutar el comando git remote. Git funciona con sshlo que implica que estás usando claves públicas + privadas. Supongo que Autoload Putty keysTortoiseGit solo carga automáticamente las teclas necesarias para que pueda hacer algo con su referencia remota. Lo último es que git push -uno es un alias para ingresar a una rama remota, es un alias para ingresar a una rama remota que se creó localmente y su referencia remota aún no tiene esta rama .
juanecabellob
1
@juancab -ues un alias de --set-upstreamy "si falta la configuración, su valor predeterminado esorigin ". Sylvain y Shashank usan esto para ingresar a una rama remota recién creada . El problema clave puede deberse a que el concurso no lo cargó cuando lo intenté git push origin :inen el shell. Entonces, no entiendo su voto negativo, solo señalé los detalles míos y no abordados en otras respuestas, los expliqué y los resolví.
CPHPython
Está declarando cosas incorrectas y gran parte de esta respuesta no está relacionada con la pregunta misma. Si está señalando lo que funcionó para usted, lo aliento a limitar la respuesta a lo que funcionó y si realmente desea dar una explicación, infórmese mejor. Por cierto: -ues un alias para --set-upstreampero no es un alias para empujar a una rama remota como dijiste. Para ingresar a una rama remota que necesita de forma exclusiva git push <remote>, y si aún no está en el remoto, agrega git push -u <remote>. Por lo tanto, -use utiliza para crear una referencia de la rama en el control remoto.
juanecabellob
1
@juancab quizás lo que consideró incorrecto fue principalmente el alias o la elección de palabras. Reestructuré mi respuesta y la reformulé para proporcionar una explicación completa de las soluciones que encontré para cambiar el nombre de una rama remota.
CPHPython
Lo reformularía más. Tiene más sentido ahora, pero aún es demasiado largo. Sería más específico al problema, es decir, para los usuarios de TortoiseGit las soluciones propuestas no funcionarán. Estás contando una historia y eso es confuso y hace que los usuarios eviten leer. Editaré tu respuesta con una propuesta.
juanecabellob
1

No sé por qué, pero la respuesta de @Sylvain Defresne no me funciona.

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

Tengo que desarmar el flujo ascendente y luego puedo configurar el flujo nuevamente. Lo siguiente es cómo lo hice.

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
fuente
0

No sé si esto es correcto o incorrecto, pero empujé el "nombre antiguo" de la rama al "nombre nuevo" de la rama, luego eliminé la rama vieja por completo con las dos líneas siguientes:

git push origin old_branch:new_branch
git push origin :old_branch
EpicPandaForce
fuente
Por lo que puedo decir, esto es exactamente lo que hacen todas las otras respuestas. Tu respuesta es más sucinta.
Más claro
-1

Puede crear una nueva rama basada en una rama de nombre antiguo. ¡Así como así, luego borre la rama anterior, sobre !!!ingrese la descripción de la imagen aquí

Pober Wong
fuente
Eso es GitHub, no Git. ;)
Bouncner
-4

Agregando a las respuestas ya dadas, aquí hay una versión que primero verifica si la nueva rama ya existe (para que pueda usarla con seguridad en 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"

(el cheque es de esta respuesta )

myzzzl
fuente
Hubiera usado en git show-ref --quiet --verify -- refs/heads/$new_namelugar de ls-remote | cut | sed | grep.
Andy