¿Cómo se elimina una revisión específica en el historial de git?

StackOverflow https://stackoverflow.com/questions/37219

  •  09-06-2019
  •  | 
  •  

Pregunta

Supongamos que su historial de git se ve así:

1 2 3 4 5

1 a 5 son revisiones independientes.Debes eliminar 3 y conservar 1, 2, 4 y 5.¿Cómo se puede hacer esto?

¿Existe un método eficaz cuando hay cientos de revisiones después de la que se va a eliminar?

¿Fue útil?

Solución

Para combinar las revisiones 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, utilice squash.

He utilizado con éxito esta técnica de aplastamiento, pero nunca antes había necesitado eliminar una revisión.Es de esperar que la documentación de git-rebase en "División de confirmaciones" le dé una idea suficiente para resolverlo.(O quizás alguien más lo sepa).

Desde el documentación git:

Comience con la confirmación más antigua que desee conservar tal como está:

git rebase -i <after-this-commit>

Se activará un editor con todas las confirmaciones en su rama actual (ignorando las confirmaciones de fusión), que vienen después de la confirmación dada.Puede reordenar las confirmaciones en esta lista según lo desee y puede eliminarlas.La lista se parece más o menos a esto:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

Las descripciones en línea son exclusivamente para su placer;git-rebase no los verá, sino los nombres de confirmación ("deadbee" y "fa1afe1" en este ejemplo), así que no elimine ni edite los nombres.

Al reemplazar el comando "elegir" con el comando "editar", puede indicarle a git-rebase que se detenga después de aplicar esa confirmación, de modo que pueda editar los archivos y/o el mensaje de confirmación, modificar la confirmación y continuar con el cambio de base.

Si desea combinar dos o más confirmaciones en una, reemplace el comando "elegir" con "aplastar" para la segunda confirmación y las siguientes.Si las confirmaciones tuvieron diferentes autores, atribuirá la confirmación aplastada al autor de la primera confirmación.

Otros consejos

A continuación se muestra una forma de eliminar de forma no interactiva un archivo específico. <commit-id>, conociendo sólo el <commit-id> desea eliminar:

git rebase --onto <commit-id>^ <commit-id> HEAD

Por este comentario (y verifiqué que esto es cierto), la respuesta de rado es muy cercana pero deja a git en un estado de cabeza separada.En su lugar, elimine HEAD y usa esto para eliminar <commit-id> desde la sucursal en la que te encuentras:

git rebase --onto <commit-id>^ <commit-id>

Como se señaló antes git-rebase(1) es tu amigo.Suponiendo que las confirmaciones estén en su master rama, harías:

git rebase --onto master~3 master~2 master

Antes:

1---2---3---4---5  master

Después:

1---2---4'---5' master

De git-rebase(1):

Una variedad de confirmaciones también podría eliminarse con Rebase.Si tenemos la siguiente situación:

E---F---G---H---I---J  topicA

entonces el comando

git rebase --onto topicA~5 topicA~3 topicA

resultaría en la eliminación de los compromisos F y G:

E---H'---I'---J'  topicA

Esto es útil si F y G tuvieron defectos de alguna manera, o no deberían ser parte de Topica.Tenga en cuenta que el argumento a —onto y el parámetro puede ser cualquier compromiso válido.

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ás revirtiendo.

Lo que esto significa es que conserva información tanto sobre la confirmación no deseada como sobre la confirmación que elimina esos cambios.

Esto probablemente sea mucho más amigable si es posible que alguien haya retirado su repositorio mientras tanto, ya que la reversión es básicamente solo una confirmación estándar.

Todas las respuestas hasta ahora no abordan la preocupación final:

¿Existe un método eficiente cuando hay cientos de revisiones después de la que se eliminará?

Los pasos siguen, pero como referencia, supongamos la siguiente historia:

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

C:comprometerse justo después del compromiso que se eliminará (limpiar)

R:El compromiso que se eliminará

B:compromiso justo antes del compromiso que se eliminará (base)

Debido a la restricción de "cientos de revisiones", supongo las siguientes condiciones previas:

  1. Hay algún compromiso vergonzoso que desearías que nunca existiera.
  2. hay CERO confirmaciones posteriores que en realidad dependen de esa confirmación vergonzosa (cero conflictos al revertir)
  3. no le importa que aparezca como el 'Committer' de los cientos de confirmaciones intermedias (se conservará el 'Autor')
  4. nunca has compartido el repositorio
    • o en realidad tienes suficiente influencia sobre todas las personas que alguna vez han clonado la historia con ese compromiso para convencerlos de usar tu nueva historia.
    • y tú no me importa acerca de reescribiendo la historia

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:

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

Si realmente no hay conflictos, entonces esto debería continuar sin más interrupciones.Si hay conflictos, puedes resolverlos y rebase --continue o decidir simplemente vivir con la vergüenza y rebase --abort.

Ahora deberías estar encendido master que ya no tiene compromiso R en eso.El save La bifurcación 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.Necesitará estar familiarizado con stash, reset --hard, y cherry-pick.Y puedes eliminar el base, remove-me, y save sucursales

Aquí está el escenario al que me enfrenté y cómo lo resolví.

[branch-a]

[Hundreds of commits] -> [R] -> [I]

aquí R es el compromiso que necesitaba ser eliminado, y I es un compromiso único que viene después R

Hice un compromiso de reversión y los aplasté juntos.

git revert [commit id of R]
git rebase -i HEAD~3

Durante la rebase interactiva, aplasta las últimas 2 confirmaciones.

Yo también aterricé en una situación similar.Utilice la rebase interactiva usando el siguiente comando y mientras selecciona, suelte la tercera confirmación.

git rebase -i remote/branch

Las respuestas de rado y kareem no hacen nada por mí (solo aparece el mensaje "La sucursal actual está actualizada").Posiblemente esto suceda porque el símbolo '^' no funciona en la consola de Windows.Sin embargo, según este comentario, reemplazar '^' por '~1' resuelve el problema.

git rebase --onto <commit-id>^ <commit-id>

Para eliminar el historial de confirmaciones antiguo del repositorio de git:

Primero ejecute debajo de cmd

rm -rf .git

-- recrear el repositorio desde el actual

git init                                                                           
git add .                                                  
git commit -m "first commit"

-- empujar a los repositorios remotos de github

git remote add origin git@github.com<your git mail>   
git push -u --force origin master
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top