Empuje el repositorio local de Git a un nuevo control remoto que incluya todas las ramas y etiquetas

551

Tengo un repositorio Git local que me gustaría enviar a un nuevo repositorio remoto (nuevo repositorio configurado en Beanstalk, si eso es importante).
Mi repositorio local tiene algunas ramas y etiquetas, y me gustaría mantener toda mi historia.

Parece que básicamente solo necesito hacer un git push, pero eso solo carga la masterrama.

¿Cómo presiono todo para obtener una réplica completa de mi repositorio local en el control remoto?

Cory Imdieke
fuente
Respuesta más corta y fácil: stackoverflow.com/a/39992258/6648326 .
MasterJoe2

Respuestas:

898

Para empujar todas sus ramas , use cualquiera (reemplace REMOTE con el nombre del control remoto, por ejemplo "origen"):

git push REMOTE '*:*'
git push REMOTE --all

Para empujar todas sus etiquetas :

git push REMOTE --tags

Finalmente, creo que puedes hacer esto todo en un comando con:

git push REMOTE --mirror

Sin embargo, además --mirror, también empujará sus controles remotos, por lo que esto podría no ser exactamente lo que desea.

cmcginty
fuente
53
--allen lugar de *:*parece más amigable
Idan K
56
Dios mío ... rompí todo el Internet y descubrí que el interruptor `--todo` es AAAAALLLLLLLLLLLLLL que necesitaba!
Rakib
21
Solo notando que git push REMOTE --allregresó sin No refs in common and none specified;hacer nada, mientras que en git push REMOTE "*:*realidad empujó todas las ramas al control remoto.
Im0rtality
10
Use --dry-run para inspeccionar lo que sucederá, en caso de que tenga ramas "tmp" o "feature" localmente que realmente no quiera actualizar en REMOTE
Jonno
55
Si el control remoto original todavía está disponible, es una buena idea hacerlo git clone --mirror old-remote-url; cd repo.git; git push --mirror new-remote-url.
Suzanne Dupéron
157

En el caso como yo, que adquirió un repositorio y ahora está cambiando el origen remoto a un repositorio diferente, uno nuevo y vacío ...

Entonces tiene su repositorio y todas las ramas dentro, pero aún necesita verificar esas ramas para que el git push --allcomando realmente las empuje también.

Debe hacer esto antes de presionar:

for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done

Seguido por

git push --all
Daniel
fuente
44
Esto también es realmente útil, ya que tuve que pagar todas las ramas manualmente. Esto será bueno para la próxima vez.
Cory Imdieke
10
Extrañamente, git push '*:*'empujó todas las ramas. git push -allAcabo de empujar al maestro. Estaba transportando repo de github a bitbucket.
jerrymouse
3
En lugar de revisar cada rama, debe hacer "git branch --track $ remote". En grandes repositorios, echar un vistazo a una antigua sucursal lleva algún tiempo
Moataz Elmasry
2
Tuve que hacer un pequeño cambio para que esto funcione: en --track remotes/$remotelugar de --track $remote. Aquí está la línea de comando completa:for remote in `git branch -r | grep -v master `; do git checkout --track remotes/$remote ; done
Adrian T
Gracias, funciona para mí, la respuesta anterior no funciona tan bien.
Benyamin Jafari
90

Aquí hay otra versión de lo mismo que funcionó mejor para la situación en la que me encontraba. Resuelve el problema en el que tiene más de un control remoto, le gustaría clonar todas las ramas de remoto sourcea remoto destinationpero sin tener que verificarlas todas de antemano.

(El problema que tuve con la solución de Daniel fue que se negaría a pagar una rama de seguimiento desde el sourcecontrol remoto si ya la había revisado anteriormente, es decir, no actualizaría mi rama local antes del envío)

git push destination +refs/remotes/source/*:refs/heads/*

Nota: Si no está utilizando la CLI directa, debe escapar de los asteriscos:

git push destination +refs/remotes/source/\*:refs/heads/\*

esto empujará todas las ramas del control remoto sourcea una rama principal destination, posiblemente haciendo un empuje no rápido hacia adelante. Aún debe presionar las etiquetas por separado.

Raza Pieter
fuente
8
+1 Esto funcionó para mí, clonando de uno remotea otro. ¡Gracias!
Laurence
44
Tuve que escapar de los asteriscos:git push destination +refs/remotes/source/\*:refs/heads/\*
mattalxndr
2
Para mí, esto terminó empujando una rama llamada HEAD, que no creo que sea intencional en este escenario.
maxwellb
1
Esta respuesta fue increíblemente útil para mí. La única mención en la página de manual de git-push (1) de este uso de asteriscos está en un pequeño ejemplo de la --pruneopción.
laindir
44
Excelente respuesta, muy diferente al --mirrorparámetro habitual que todos recomiendan. Funciona perfectamente para escenarios en los que solo desea mantener sincronizados dos controles remotos para fines de automatización o auditoría.
Vinicius Xavier
15

Esta es la forma más concisa que he encontrado, siempre que el destino esté vacío. Cambie a una carpeta vacía y luego:

# Note the period for cwd >>>>>>>>>>>>>>>>>>>>>>>> v
git clone --bare https://your-source-repo/repo.git .
git push --mirror https://your-destination-repo/repo.git

Sustituir https://...por file:///your/repoetc. según corresponda.

ta.speot.is
fuente
13

La página del manual de git-pushla pena leer. En combinación con este sitio web , escribí lo siguiente en mi .git/config:

[remote "origin"]
    url = …
    fetch = …
    push = :
    push = refs/tags/*

Los push = :medios "empujan cualquier rama 'coincidente' (es decir, ramas que ya existen en el repositorio remoto y tienen una contraparte local)", mientras que push = refs/tags/*significa "empujar todas las etiquetas".

Así que ahora solo tengo que correr git pushpara empujar todas las ramas coincidentes y todas las etiquetas.

Sí, esto no es exactamente lo que quería el OP (todas las ramas para empujar ya deben existir en el lado remoto), pero podría ser útil para aquellos que encuentran esta pregunta mientras buscan en Google "¿Cómo empujo ramas y etiquetas al mismo tiempo? hora".

scy
fuente
13

En mi caso lo que funcionó fue.

git push origin --all
nomulex
fuente
44
Simple y fácil. ¡Funciona! origines un alias para el repositorio remoto de URL Git.
Do Nhu Vy
8

Reflejando un repositorio

Cree un clon desnudo del repositorio.

git clone --bare https://github.com/exampleuser/old-repository.git

Mirror-push al nuevo repositorio.

cd old-repository.git
git push --mirror https://github.com/exampleuser/new-repository.git

Elimine el repositorio local temporal que creó en el paso 1.

cd ..
rm -rf old-repository.git

Duplicar un repositorio que contiene objetos de almacenamiento de archivos grandes de Git

Cree un clon desnudo del repositorio. Reemplace el nombre de usuario de ejemplo con el nombre de la persona u organización propietaria del repositorio, y reemplace el nombre del repositorio de ejemplo con el nombre del repositorio que desea duplicar.

git clone --bare https://github.com/exampleuser/old-repository.git

Navegue hasta el repositorio que acaba de clonar.

cd old-repository.git

Tire de los objetos Git Large File Storage del repositorio.

git lfs fetch --all

Mirror-push al nuevo repositorio.

git push --mirror https://github.com/exampleuser/new-repository.git

Empuje los objetos Git Large File Storage del repositorio a su espejo.

git lfs push --all https://github.com/exampleuser/new-repository.git

Elimine el repositorio local temporal que creó en el paso 1.

cd ..
rm -rf old-repository.git

Las instrucciones anteriores provienen de la Ayuda de Github: https://help.github.com/articles/duplicating-a-repository/

Michał Zalewski
fuente
1
Si bien esto puede responder teóricamente la pregunta, sería preferible incluir aquí las partes esenciales de la respuesta y proporcionar el enlace para referencia. Consulte aquí para obtener instrucciones sobre cómo escribir mejores respuestas "basadas en enlaces". ¡Gracias!
GhostCat
5

Encontré que las respuestas anteriores todavía tienen algunas cosas poco claras, lo que engañará a los usuarios. Primero, es seguro que git push new_origin --ally git push new_origin --mirrorno puede duplicar todas las ramas de origen, simplemente duplica las ramas locales existentes a su nuevo_origen.

A continuación hay dos métodos útiles que he probado:

1, duplicado por clon bare repo. git clone --bare origin_url, luego ingrese la carpeta y git push new_origin_url --mirror. De esta manera, también puede usar git clone --mirror origin_urlambos --barey --mirrordescargará un repositorio sin incluir el espacio de trabajo. por favor refiérase a esto

2, si tiene un repositorio git usando git clone, lo que significa que tiene un repositorio desnudo y un espacio de trabajo git, puede usar git remote add new_origin new_origin_url, y luego git push new_origin +refs/remotes/origin/\*:refs/heads/\*, y luegogit push new_origin --tags

De esta manera, obtendrá una rama de cabeza adicional, que no tiene sentido.

yanzi1225627
fuente
2

Para empujar ramas y etiquetas (pero no controles remotos):

git push origin 'refs/tags/*' 'refs/heads/*'

Esto sería equivalente a combinar las opciones --tagsy --allpara git push, que git no parece permitir.

CEL
fuente
¿Hay una opción adicional para empujar desde otro control remoto? Por ejemplo con+refs/remotes/source/*
Yves Martin
2

Basado en la respuesta de @Daniel , hice:

for remote in \`git branch | grep -v master\`
do 
    git push -u origin $remote
done
Arthur Julião
fuente
2
Aún mejor, | grep -v masterse puede reemplazar con | sed 's/\*//'(supongo que excluyó masterpara evitar lo desagradable *que se antepone a la rama actualmente seleccionada) que le permite incluir mastery evitar problemas cuando masterno es su rama actualmente seleccionada. También lo siento por la necroposición, es solo que esta respuesta me ayudó hoy y quería compartir mi modificación si puede ayudar a otros en mi posición ...
ToVine
1

Descubrí que ninguno de estos parecía funcionar correctamente para mí. Siéntase libre de encender esto hasta la muerte, pero por alguna razón no pudo lograr que las otras opciones funcionen correctamente.

El resultado esperado fue un repositorio "clonado" a otro remoto (es decir, de Github a otro proveedor):

  • Todas las sucursales se crean en un nuevo control remoto.
  • Todo el historial de sucursales se crea en un nuevo control remoto
    • (Esto se perdió en cada solución que probé)
  • Todas las etiquetas se crean en un nuevo control remoto
  • La fuente se mueve (un hecho)
  • No destructivo (dando pausa a la opción --mirror)

El problema principal que estaba viendo era que todas las ramas remotas no se recreaban en el nuevo control remoto. Si un comando lo hizo, el nuevo control remoto no tenía el historial de la rama (es decir, hacer un git checkout branch; git logno mostraría las confirmaciones de rama esperadas).

Noté git checkout -b branchnameque NO es lo mismo que git checkout branchname(este último es lo que necesitaba). Noté git checkout --track branchnameque no parecía extraer el historial de la rama.

Mi solución (basada en powershell):

Function Git-FetchRemoteBranches {
$originalbranch = (git symbolic-ref HEAD).split("/")[-1]

Foreach ($entry in (git branch -r)) {

If ($entry -like "*->*") {
  $branch = $entry.split("->")[2].split("/")[1]
}
  else {$branch = $entry.split("/")[1]}

Write-Host "--Trying git checkout " -NoNewline
Write-Host "$branch" -Foreground Yellow

git checkout $branch

Remove-Variable branch -Force

""}

#Switch back to original branch, if needed
If ( ((git symbolic-ref HEAD).split("/")[-1]) -ne $originalbranch) {
"Switching back to original branch"
git checkout $originalbranch
Remove-Variable originalbranch -Force
}
}

git clone http://remoterepo
cd remoterepo
Git-FetchRemoteBranches
git remote add newremote
git push newremote --all
git push newremote --tags #Not sure if neeeded, but added for good measure
PatataGranja
fuente
1

El siguiente comando empujará todas las ramas ( incluidas las que nunca ha desprotegido pero presente en su repositorio de git, puede verlas porgit branch -a )

git push origin '*:*'

NOTA: Este comando es útil cuando está migrando el servicio de control de versiones ( es decir, migrando de Gitlab a GitHub )

Pratik Patel
fuente
1
¡Migrar entre los servicios de control de versiones y esto es exactamente lo que estoy buscando, saludos!
Luka Špoljarić
1

Estaba en un proceso de cambiar de un servicio de control de versiones a otro y necesitaba clonar todos los repositorios, incluidas todas las ramas, etiquetas e historial.

Para lograr lo anterior hice lo siguiente:

  • desproteger manualmente todas las ramas al repositorio local (el script para desproteger todo se muestra a continuación),
  • git push origin '*:*'

El script .sh se usa para pagar todas las ramas al repositorio local:

for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master `; do
   git branch --track ${branch#remotes/origin/} $branch
done
Luka Špoljarić
fuente