Git reset: duro y push al repositorio remoto
Tenía un repositorio que tenía algunas confirmaciones incorrectas (D, E y F para este ejemplo).
Maestro ABCDEF y origen/maestro
Modifiqué el repositorio local específicamente con un archivo git reset --hard
. Tomé una rama antes del reinicio, así que ahora tengo un repositorio que se ve así:
A-B-C master
\ D-E-F old_master
A-B-C-D-E-F origin/master
Ahora necesitaba algunas partes de esas confirmaciones incorrectas, así que seleccioné las partes que necesitaba e hice algunas confirmaciones nuevas, así que ahora tengo lo siguiente localmente:
A-B-C-G-H master
\ D-E-F old_master
Ahora quiero llevar esta situación al repositorio remoto. Sin embargo, cuando intento hacer un git push
Git cortésmente me desestima:
$ git push origin +master:master --force
Total 0 (delta 0), reused 0 (delta 0)
error: denying non-fast forward refs/heads/master (you should pull first)
To [email protected]:myrepo.git
! [remote rejected] master -> master (non-fast forward)
error: failed to push some refs to '[email protected]:myrepo.git'
¿Cómo consigo que el repositorio remoto tome el estado actual del repositorio local?
Si forzar un envío no ayuda ( git push --force origin
o git push --force origin master
debería ser suficiente), podría significar que el servidor remoto está rechazando envíos que no sean de avance rápido, a través de cualquiera de receive.denyNonFastForwards
las variables de configuración (consulte la página de manual de git config para obtener una descripción) o mediante una actualización/pre- recibir gancho.
Con Git anterior, puede solucionar esa restricción eliminando git push origin :master
(tenga en cuenta el :
nombre de la rama anterior) y luego volviendo a crear git push origin master
la rama determinada.
Si no puede cambiar esto, entonces la única solución sería, en lugar de reescribir el historial, crear una confirmación que revierta los cambios en DEF :
A-B-C-D-E-F-[(D-E-F)^-1] master
A-B-C-D-E-F origin/master
Para los usuarios de GitHub, esto funcionó para mí:
- En cualquier regla de protección de rama donde desee realizar el cambio, asegúrese de que Permitir empujes forzados esté habilitado
git reset --hard <full_hash_of_commit_to_reset_to>
git push --force
Esto "corregirá" el historial de la rama en su máquina local y el servidor GitHub, pero cualquiera que haya sincronizado esta rama con el servidor desde la confirmación incorrecta tendrá el historial en su máquina local. Si tienen permiso para enviar directamente a la rama, estas confirmaciones se mostrarán de nuevo cuando se sincronicen.
Todo lo que todos los demás deben hacer es el git reset
comando de arriba para "corregir" la rama en su máquina local. Por supuesto, tendrían que tener cuidado con cualquier compromiso local realizado en esta rama después del hash objetivo. Elija/haga una copia de seguridad y vuelva a aplicarlos según sea necesario, pero si se encuentra en una rama protegida, es probable que la cantidad de personas que pueden comprometerse directamente con ella sea limitada.
Para complementar la respuesta de Jakub, si tiene acceso al servidor git remoto en ssh, puede ir al directorio remoto de git y configurar:
user@remote$ git config receive.denyNonFastforwards false
Luego regrese a su repositorio local, intente nuevamente realizar su confirmación con --force
:
user@local$ git push origin +master:master --force
Y finalmente revierta la configuración del servidor en el estado protegido original:
user@remote$ git config receive.denyNonFastforwards true