Supongamos que su historial de git se ve así:
1 2 3 4 5
1–5 son revisiones separadas. Debe eliminar 3 mientras mantiene 1, 2, 4 y 5. ¿Cómo se puede hacer esto?
¿Existe un método eficiente cuando hay cientos de revisiones después de la que se eliminará?
git rebase --onto 2 3 HEAD
más o menos significa rebase en 2, con commits entre 3 y HEAD (HEAD es opcional, o 5 en este caso)Respuestas:
Para combinar la revisión 3 y 4 en una sola revisión, puede usar git rebase. Si desea eliminar los cambios en la revisión 3, debe usar el comando de edición en el modo de rebase interactivo. Si desea combinar los cambios en una sola revisión, use squash.
He utilizado con éxito esta técnica de squash, pero nunca antes había necesitado eliminar una revisión. Con suerte, la documentación de git-rebase en "Splitting commits" debería darle una idea suficiente para resolverlo. (O alguien más podría saberlo).
De la documentación de git :
fuente
Según este comentario (y verifiqué que esto es cierto), la respuesta de rado está muy cerca, pero deja a git en un estado de cabeza separada. En cambio, elimine
HEAD
y use esto para eliminar<commit-id>
de la rama en la que se encuentra:fuente
^
a~1
hacerlo funcionar.--strategy-option theirs
al final.Aquí hay una manera de eliminar de forma no interactiva un específico
<commit-id>
, sabiendo solo<commit-id>
lo que desea eliminar:fuente
HEAD
fin de evitar una cabeza desprendida.Como se señaló antes, git-rebase (1) es tu amigo. Asumiendo que los commits están en su
master
rama, usted haría:Antes de:
Después:
De git-rebase (1):
fuente
--onto master~3 master~1
?MERGE CONFLICT
error Usé el escenario mencionado en stackoverflow.com/questions/2938301/remove-specific-commit y no puedo eliminar la segunda confirmación en ese ejemplo.Si todo lo que desea hacer es eliminar los cambios realizados en la revisión 3, es posible que desee utilizar git revert.
Git revert simplemente crea una nueva revisión con cambios que deshacen todos los cambios en la revisión que está revocando.
Lo que esto significa es que retiene información sobre la confirmación no deseada y la confirmación que elimina esos cambios.
Esto es probablemente mucho más amigable si es posible que alguien haya retirado de su repositorio mientras tanto, ya que la reversión es básicamente una confirmación estándar.
fuente
Todas las respuestas hasta ahora no abordan la preocupación final:
Los pasos siguen, pero como referencia, supongamos el siguiente historial:
C : commit solo siguiendo el commit que se eliminará (clean)
R : El compromiso a eliminar
B : commit justo antes del commit a eliminar (base)
Debido a la restricción de "cientos de revisiones", estoy asumiendo las siguientes condiciones previas:
Este es un conjunto de restricciones bastante restrictivo, pero hay una respuesta interesante que realmente funciona en este caso de esquina.
Aquí están los pasos:
git branch base B
git branch remove-me R
git branch save
git rebase --preserve-merges --onto base remove-me
Si realmente no hay conflictos, esto debería proceder sin más interrupciones. Si hay conflictos, puede resolverlos
rebase --continue
o decidir vivir con la vergüenza yrebase --abort
.Ahora debería estar en
master
eso ya no tiene commit R en él. Lasave
rama apunta a donde estabas antes, en caso de que quieras conciliar.Depende de usted cómo desea organizar la transferencia de todos los demás a su nuevo historial. Usted tendrá que estar familiarizado con
stash
,reset --hard
ycherry-pick
. Y puede eliminar lasbase
,remove-me
ysave
las ramasfuente
También aterricé en una situación similar. Use el rebase interactivo usando el comando a continuación y mientras selecciona, suelte la tercera confirmación.
fuente
Así que aquí está el escenario que enfrenté y cómo lo resolví.
Aquí
R
está la confirmación que necesitaba eliminar, yI
es una confirmación única que viene despuésR
Hice un compromiso de reversión y los aplasté juntos
Durante el squash de rebase interactivo, los últimos 2 commits.
fuente
Las respuestas de rado y kareem no hacen nada por mí (solo aparece el mensaje "La rama actual está actualizada"). Posiblemente esto sucede porque el símbolo '^' no funciona en la consola de Windows. Sin embargo, de acuerdo con este comentario, reemplazar '^' por '~ 1' resuelve el problema.
fuente