tag - qué tipos de etiquetas existen en git
¿Cómo revertir múltiples git commit? (11)
Estoy tan frustrado que esta pregunta no puede ser contestada. Todas las demás preguntas están relacionadas con cómo revertir correctamente y preservar la historia. Esta pregunta dice: "Quiero que el jefe de la rama apunte a A, es decir, quiero que B, C, D y HEAD desaparezcan y quiero que el jefe sea sinónimo de A".
git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f
Aprendí mucho leyendo el post de Jakub, pero un tipo de la empresa (con acceso a push en nuestra sucursal de "prueba" sin Pull-Request) empujó como 5 compromisos erróneos tratando de arreglar y corregir un error que cometió hace 5 confirmaciones. No solo eso, sino que se aceptaron una o dos solicitudes de extracción, que ahora eran malas. Así que olvídalo, encontré el último buen compromiso (abc1234) y simplemente ejecuté el script básico:
git checkout testing
git reset --hard abc1234
git push -f
Les dije a los otros 5 muchachos que trabajan en este repositorio que es mejor que tomen nota de sus cambios durante las últimas horas y que limpien / re-ramifiquen las últimas pruebas. El final de la historia.
Tengo un repositorio git que se ve así:
A -> B -> C -> D -> HEAD
Quiero que la cabeza de la rama apunte a A, es decir, quiero que B, C, D y HEAD desaparezcan y quiero que la cabeza sea sinónimo de A.
Parece que puedo intentar volver a generar (no se aplica, ya que he introducido cambios en el medio), o revertir. Pero, ¿cómo puedo revertir múltiples confirmaciones? ¿Revertiré uno a la vez? ¿Es importante el orden?
La forma fácil de revertir un grupo de confirmaciones en el repositorio compartido (que las personas usan y desea conservar el historial) es usar git revert
junto con git rev-list
. La última le proporcionará una lista de confirmaciones, la primera hará el cambio por sí misma.
Hay dos maneras de hacer eso. Si desea revertir múltiples confirmaciones en un solo uso de confirmación:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done
esto revertirá un grupo de confirmaciones que necesita, pero deje todos los cambios en su árbol de trabajo, debe confirmarlos como de costumbre.
Otra opción es tener una única confirmación por cambio revertido:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done
Por ejemplo, si tienes un árbol de compromiso como
o---o---o---o---o---o--->
fff eee ddd ccc bbb aaa
para revertir los cambios de eee a bbb , ejecute
for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
Limpio camino que encontré útil
git revert --no-commit HEAD~3..
Este comando revierte las últimas 3 confirmaciones con una sola confirmación.
Tampoco reescribe la historia.
Ninguno de esos funcionó para mí, así que tuve tres confirmaciones para revertir (las últimas tres confirmaciones), así que hice:
git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash
Trabajado como un encanto :)
Para hacerlo, solo tiene que usar el comando revert , especificando el rango de confirmaciones que desea revertir.
Teniendo en cuenta su ejemplo, tendría que hacer esto (suponiendo que está en el ''maestro'' de la rama):
git revert master~3..master
Esto creará una nueva confirmación en su local con la confirmación inversa de B, C y D (lo que significa que deshará los cambios introducidos por estas confirmaciones):
A <- B <- C <- D <- BCD'' <- HEAD
Primero asegúrese de que su copia de trabajo no se modifica. Entonces:
git diff HEAD commit_sha_you_want_to_revert_to | git apply
y luego simplemente cometer. No olvides documentar cuál es la razón para revertir.
Si desea revertir temporalmente las confirmaciones de una característica, puede usar la siguiente serie de comandos.
git log --pretty = oneline | grep ''feature_name'' | corte -d '''' -f1 | xargs -n1 git revert --no-editar
Similar a la respuesta de Jakub, esto le permite seleccionar fácilmente confirmaciones consecutivas para revertir.
# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD
$ git commit -m ''message''
Esta es una expansión de una de las soluciones provistas en la respuesta de Jakub.
Me enfrenté a una situación en la que los compromisos que necesitaba para revertir eran algo complejos, con varios de los compromisos que se cometen para fusionar, y tenía que evitar volver a escribir el historial. No pude usar una serie de comandos git revert
porque eventualmente tuve conflictos entre los cambios de reversión que se agregaron. Terminé siguiendo los siguientes pasos.
Primero, revise el contenido de la confirmación de destino mientras deja HEAD en la punta de la rama:
$ git checkout -f <target-commit> -- .
(El - se asegura de que <target-commit>
se interprete como una confirmación en lugar de un archivo; el. Se refiere al directorio actual.)
Luego, determine qué archivos se agregaron en las confirmaciones que se están revertiendo y, por lo tanto, deben eliminarse:
$ git diff --name-status --cached <target-commit>
Los archivos que se agregaron deberían aparecer con una "A" al principio de la línea, y no debería haber otras diferencias. Ahora, si es necesario eliminar algún archivo, prepare estos archivos para eliminarlos:
$ git rm <filespec>[ <filespec> ...]
Finalmente, cometer la reversión:
$ git commit -m ''revert to <target-commit>''
Si lo desea, asegúrese de volver al estado deseado:
$git diff <target-commit> <current-commit>
No debe haber diferencias.
Expandiendo lo que escribí en un comentario.
La regla general es que no debe volver a escribir (cambiar) el historial que ha publicado, porque alguien podría haber basado su trabajo en él. Si reescribe (cambia) el historial, tendría problemas al fusionar sus cambios y actualizarlos.
Entonces, la solución es crear un nuevo compromiso que revierta los cambios de los que desea deshacerse. Puedes hacer esto usando el comando git revert .
Tienes la siguiente situación:
A <-- B <-- C <-- D <-- master <-- HEAD
(Las flechas aquí se refieren a la dirección del puntero: la referencia "principal" en el caso de confirmaciones, la confirmación superior en el caso de la cabecera de la rama (referencia de la rama) y el nombre de la rama en el caso de la referencia HEAD).
Lo que necesitas crear es lo siguiente:
A <-- B <-- C <-- D <-- [(BCD)^-1] <-- master <-- HEAD
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"
Una solución alternativa sería checkout contenido de la confirmación A, y confirmar este estado:
$ git checkout -f A -- .
$ git commit -a
Entonces tendrías la siguiente situación:
A <-- B <-- C <-- D <-- A'' <-- master <-- HEAD
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 utiliza git reset :
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
git reset --hard a
git reset --mixed d
git commit
Eso actuará como un retroceso para todos ellos a la vez. Dar un buen mensaje de confirmación.