Origen del rollback maestro sin empuje de fuerza

¿Hay alguna forma de revertir el origen master a la confirmación previa, si forzar push está deshabilitado? Tengo A -> B -> C C es una confirmación incorrecta, por cierto, B es una combinación de fusión. Quiero que el origen maestro regrese a B, pero las políticas del server rechazan el empuje forzado.

¿Alguna otra forma de hacerlo?

Antes de entrar en las opciones técnicas, debemos reconocer que una política de "no empujar la fuerza" significa que no está destinado a hacer lo que usted describe. Borrar las confirmaciones de la historia de un árbitro es el quid de lo que hace el "empuje de fuerza" (más allá de un empuje regular). En general, hay una buena razón para que un repository de origen rechace los empujes de fuerza: consulte la sección "recuperación de rebase ascendente" de la documentation de git rebase , porque aunque no utilice el command rebase , se aplica la misma situación.

Y hay opciones que podrían ser "lo suficientemente buenas" en lugar de eliminar C ; Volveré a eso.

Pero vale, supongamos que por cualquier motivo usted (y su equipo / propietario del repository / quien sea responsable de decidir si esto está bien) entiende los costos y aún desea hacerlo, pero no puede cambiar la configuration de la política que su server está aplicando .

¿Hay alguna otra manera de eliminar C ?

No es simple. No al tratar el repository de origen como un control remoto, de todos modos. Por definición, "forzar empuje" es la operación que toma commits del historial de una reference remota.

Opción 1 : Bueno, no sé cómo se aloja su repository de origen. ¿El software del server le da opciones para manipular el repository? Si es así, esa es tu mejor apuesta.

Opción 2 : si tiene acceso directo al repository de origen, si puede iniciar session en algún lugar que le permita tratarlo como un repository local, puede hacerlo. El procedimiento es básicamente el mismo que hiciste localmente, excepto que tal vez tengas que crear primero un tree de trabajo (porque normalmente el origen sería un repository simple). Algo como

 git worktree add /path/to/create/a/worktree/at master # cd into the new work tree git reset --hard HEAD^ 

A continuación, elimine el tree de trabajo ( rm -r ... ) y limpie ( git worktree prune ) para que git no se preocupe por los empujes que afectan al tree de trabajo.

Opción 3 : si tiene acceso directo a los files de repos pero por alguna razón no puede ejecutar git en ellos, en teoría podría volver a escribir la reference. Trabajar directamente en files git es un juego peligroso y realmente no lo recomiendo, pero que nadie diga que no fui minucioso al considerar las opciones.

A less que sepa lo suficiente sobre git para resolver este procedimiento por su count, probablemente sea una mala idea hacerlo, así que me estoy moviendo …

Opción 4 : supongo que puedes replace todo el repository. Estamos llegando al background del barril aquí.

Entonces, ¿qué pasa si no puedo (o decido no) eliminar C ?

Usted podría revert su lugar. Cuando revierte un compromiso M , crea un nuevo compromiso W que "deshace" los cambios que se realizaron al crear M Asi que

 git revert C 

te daría

  (origin/master) | A --- B --- C --- !C <--(master) / ... X 

donde !C tiene el mismo TREE (estado de contenido) que B Esto puede ser presionado sin --force . Si es "lo suficientemente bueno" depende.

Si C contiene datos confidenciales (passwords, keys), es posible que realmente desee que no aparezca en el historial. Mi consejo es cambiar las passwords y revocar las keys. (Incluso si quitara C del historial, ¿podría garantizar que nadie ya lo había copydo?)

Si C contiene grandes files binarys … eso es una mala noticia. El repository siempre estará cargado por la hinchazón resultante. Reemplazar el repository con un historial reescrito es la única solución real (y eso nos lleva de vuelta a las opciones anteriores).

Pero si fue solo un "oops", entonces querer dejarlo fuera de la historia es comprensible pero no necesario. Las personas que no quieren ver a C en su historia podrían considerar el uso de git replace para "cubrir" el problema al "replace !C con B , supongo, pero puede no valer la pena. (Tenga en count que replace solo crea la ilusión de un cambio en el historial, y tiene algunos caprichos documentados: cualquiera que decida usarlo debe leer al less la documentation básica del command).