4

Tengo un servidor Git (en GitLab), al que solo tengo acceso de escritura a la branch devel. Por diversos motivos, tengo otro servidor Git en una máquina distinta (myserver). Este último se creó mediante la orden

git clone --bare https://GITLAB.URL/PATH/TO/REPO

y puedo acceder a él mediante la URL ssh://MISERVER/PATH/TO/REPO.

En mi máquina local, cloné desde myserver:

git clone ssh://myserver/repo.git

Desde ese momento, uso exclusivamente el repo en myserver: push, pull, ... todo ello sin problemas, y siempre en la branch devel.

Ahora, tengo que sincronizar ambos repos. Para ello, entro por ssh a myserver, y, con el usuario adecuado, intento:

   git fetch -v origin devel

Username for 'https://gitlab.com': ****
Password for 'https://username@gitlab.com': ****
From https://gitlab.com/path/to/repo
* branch devel -> FETCH_HEAD

No se muestra ningún error. A continuación, hago:

   git push -v origin devel

Pushing to https://gitlab.com/path/to/repo.git
Username for 'https://gitlab.com': ****
Password for 'https://username@gitlab.com': ****
To https://gitlab.com/path/to/repo.git

! [rejected] devel -> devel (non-fast-forward)

error: failed to push some refs to 'https://gitlab.com/path/to/repo.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

En resumen:

  • repo1: maquina en gitlab (--bare).
  • repo2: maquina en myserver (--bare).
  • repo3: mi equipo de desarrollo (máquina local, git clone normal, no --bare).

Flujo de trabajo normal:

repo3 -> pull from repo2, push to repo2.

Flujo de trabajo ocasional, objetivo de la pregunta:

repo2 -> pull from repo1, push to repo1.

El repo2 se creó usando git clone --bare. Es decir, no tiene copia de trabajo y no puedo ejecutar git pull en él.

En el repo2, el git fetch se ejecuta aparentemente sin errores. Sin embargo, el commando git push si muestra errores y no se realiza.

  • ¿ Que estoy haciendo mal ?

  • ¿ Cómo lo soluciono ?

Trauma
  • 25,297
  • 4
  • 37
  • 60
  • 1
    puedes aclarar lo de los servidores? me da a entender que lo que tienes son repositorios clonados, no "servidores" como tal... El error te dice que estas intentando subir algo, cuando en el servidor remoto hay mas cosas y no has integrado esos cambios. Quizas lo que quieres es un `git pull origin devel`? – Jakala May 28 '20 at 09:11
  • @Jakala Son 2 *repos*, cada uno en una máquina física distinta. En `myserver` se hizo un `git clone --bare`. Es decir, no tiene copia de trabajo y no puedo ejecutar `git pull` en él. Sin embargo, el `git fetch` se ejecuta **aparentemente** sin errores O_o – Trauma May 28 '20 at 09:18

2 Answers2

1

Entiendo que hablamos de 3 repos (dices 2, pero nombras 3)

  • Original en gitlab - rama devel (1)
  • Clonado en modo bare (2)
  • Local normal obtenido desde (3)

De todos modos, entiendo que:

Al hacer git fetch -v origin devel en (2) estás trayendo a local las copias de las ramas, pero no estás actualizando el estado de las mismas, sino únicamente trayendo una copia local de los metadatos de las ramas. OJO porque en este caso, parece que traes a (2) el estado de (1). Cuando dices tengo que sincronizar ambos repos te refieres a ¿1 y 2? a ¿2 y 3?

Como dicen en el link que te he pegado,

git pull es una abreviación de git fetch seguido de git merge FETCH_HEAD

De todos modos, he tratado de escribir la respuesta más cercana a lo que yo intentaría.

Así, entiendo que deberías hacer desde el repo (2) git fetch origin devel:devel para poder traer la última versión del repo (1) a (2).

De todos modos, también puedes traer al repositorio local la copia a una rama diferente y realizar el mergeo.

git checkout --track -b devel_copy origin/devel //Te traes la rama origen a devel_copy
git checkout devel_copy  //Asegúrate que estas en la rama local copiada
git merge devel //mergeas tus cambios que tenías en la rama local devel
git push origin devel_copy //subes tus cambios a la rama origin/devel
git fetch origin devel //traes el estado (metadata) de la rama devel de nuevo
git checkout devel //cambias a ella
git reset --hard //La reseteas para que quede asociada con el HEAD actualizado.

Espero que te ayude. De todos modos, decirte que también puedes revisar qué cambios contiene cada rama con git log branchname por lo que con un poco de paciencia, y quizá cambiando algo de lo que yo he explicado, puedas hacerlo.

Recuerda también que si tienes claro que todos tus cambios están ok, puedes forzar los push con git push origin devel_copy -f (OJO al hacerlo)

Entiendo que al menos con esto tendrás algo más de pistas. Por favor, si finalmente tomas otra solución dinos cuál es o propón tú mismo una respuesta si así lo consideras.

Gracias!

  • Muchas gracias por la respuesta. He editado un poco, a ver si aclaro algo mas la pregunta. Probaré lo que propones en cuanto me sea posible. – Trauma May 28 '20 at 11:16
  • 1
    Ánimo... siento si no es 100% precisa, pero más o menos creo que da una idea de cómo en alguna ocasión he lidiado con ello. Al final cada repo es un mundo, y podría ser que algo no funcionara. De todos modos, entiendo que podrás seguir a partir de ahí. Lo dicho, edita y mejora la respuesta o propón la tuya sin problema!! Gracias por responder!!! – Alejandro Teixeira Muñoz May 28 '20 at 11:19
1

Para tener los tres repos sincronizados, me parece que lo más conveniente es hacerlo desde local, que es el único de los tres que es un repo de trabajo en lugar de uno bare.

Entonces, una vez sincronizados local y myserver (que entiendo que ya es así), lo que falta seria sincronizar Gitlab con local.

Desde el repo local y en el branch devel:

  1. Verificar que este al día con myserver:

    git status

Muestra que no hay archivos modificados ni que haya que hacer un pull o un push.

  1. Verificar que tenemos origin apuntando a myserver (seguro es así)

    git remote -v

  2. Agregar gitlab como remote a Gitlab

    git remote add gitlab https://GITLAB.URL/PATH/TO/REPO

  3. Verificar que ahora tenemos origin mirando a myserver y también, gitlab mirando a Gitlab.

    git remote -v

  4. Traer la referencia de devel en gitlab.

    git fetch gitlab devel

  5. Opcionalmente ver un preview de lo que se va a mergear. Esto es para ver los commits que difierente entre local y Gitlab, los commits precedidos por < indican commits que están en local y no en Gitlab y los que están precedidos por > indican commits que están en Gitlab y no en local.

    git log -p --left-right devel...gitlab/devel

  6. Estando en local y en el branch devel, hacemos el merge de devel en Gitlab.

    git merge gitlab/devel

  7. Si hay conflictos, arreglar los conflictos, y terminar el merge-commit.

  8. Pushear la versión sincronizada a myserver

    git push origin devel

  9. Pushea la versión sincronizada a Gitlab

    git push gitlab devel

En este punto los tres repos tienen lo mismo.

Yo creo que no hay necesidad pero si queres podés quitar el remote a Gitlab que habiamos agregado antes: git remote remove gitlab

Juan
  • 5,605
  • 1
  • 9
  • 15