Expandiendo lo que escribí en un comentario
La regla general es que no debe reescribir (cambiar) el historial que ha publicado, porque alguien podría haber basado su trabajo en él. Si reescribe (cambia) el historial, tendrás problemas para fusionar sus cambios y actualizarlos.
Entonces, la solución es crear una nueva confirmación que revierta los cambios de los que desea deshacerse. Puede hacer esto usando el comando git revert .
Tienes la siguiente situación:
A <- B <- C <- D <- maestro <- CABEZA
(las flechas aquí se refieren a la dirección del puntero: la referencia "principal" en el caso de commits, el commit superior en el caso de branch head (branch ref) y el nombre de branch en el caso de HEAD reference).
Lo que necesita crear es lo siguiente:
A <- B <- C <- D <- [(BCD) ^ - 1] <- maestro <- CABEZA
donde "[(BCD) ^ - 1]" significa la confirmación que revierte los cambios en las confirmaciones B, C, D. Las matemáticas nos dicen que (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ -1, entonces Puede obtener la situación requerida utilizando los siguientes comandos:
$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"
La solución alternativa sería retirar el contenido de la confirmación A y confirmar este estado:
$ git checkout -f A -- .
$ git commit -a
Entonces tendría la siguiente situación:
A <- B <- C <- D <- A '<- maestro <- CABEZA
La confirmación A 'tiene el mismo contenido que la confirmación A, pero es una confirmación diferente (mensaje de confirmación, padres, fecha de confirmación).
La solución de Jeff Ferland, modificada por Charles Bailey, se basa en la misma idea, pero usa git reset :
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
git push -f HEAD~4:master
(suponiendo que la rama remota es master). Sí, puedes empujar cualquier commit así.