¿Cómo cambiar el compromiso anterior para incluir un archivo perdido?

98

Confirmé un cambio y olvidé agregar un archivo al conjunto de cambios. Después de otras confirmaciones, me di cuenta de que el archivo ahora falta en una HEAD^4confirmación.

¿Cómo reescribo una confirmación anterior para incluir el archivo que falta?

Kolrie
fuente
¿presionaste estas 4 confirmaciones?
MVP
@mvp no, están solo en mi repositorio local de git.
kolrie

Respuestas:

53

Use git rebase --interactive HEAD~4y establezca la editopción para el compromiso que desea modificar.

Recuerde que no debe modificar las confirmaciones enviadas al repositorio remoto de esta manera. En ese caso, es mejor agregar una nueva confirmación con un archivo faltante.

Rafał Rawicki
fuente
Gracias. ¿Es ese el caso incluso si soy el único usuario del repositorio remoto? ¿No me permitiría hacerlo git push -fsi estoy seguro de que el río arriba no cambió?
kolrie
1
Si eres el único usuario del repositorio remoto, está bien hacer el empuje forzado.
Rafał Rawicki
7
Creo que estas instrucciones no son lo suficientemente detalladas. Al intentarlo la primera vez, me dijeron "No se puede cambiar de base: su índice contiene cambios sin confirmar". Ya había addeditado los archivos que faltaban, así que hice una confirmación con "xxx" como mensaje. Luego hice el comando rebase, y cambié la confirmación "xxx" de "seleccionar" a "editar". Luego hice "git rebase --continue". Ahora, cuando miro el historial, tengo "xxx" como la última confirmación, ¡y la confirmación anterior a la que quería agregarlos no ha cambiado! Me pregunto dónde fue mi error.
Darren Cook
2
Aplastar la última confirmación no colocará el archivo en HEAD ~ 4.
Justin
1
git add editedFiles; git commit -m "Blah"; git rebase -i HEAD ~ 5; // como ahora se agregó una nueva confirmación, por lo que necesitábamos rebasear con 5 en lugar de 4. ahora mueva la confirmación "Blah" a la segunda línea y cámbiela de "Pick" a "s" (aplastar), lo que aplastará la confirmación con HEAD ~ 5 a medida que los comandos se ejecutan de arriba a abajo
zstring
274

Me doy cuenta de que la gente puede buscar en Google y venir aquí para encontrar una respuesta más simple: ¿Y si fuera solo la última confirmación? (La pregunta de OP es para arreglar el cuarto compromiso en la historia)

En el caso de que se comprometa y se dé cuenta de que olvidó agregar algún archivo inmediatamente , simplemente haga:

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

Donde --no-editmantendrá el mismo mensaje de confirmación.

¡Pan comido!

Dr. Beco
fuente
21
Esta es la respuesta.
Adam Bittlingmayer
5
Vale la pena mencionarlo, si las confirmaciones no se envían al control remoto.
Ram Patra
1
Sí, vale la pena mencionarlo aquí en los comentarios: Es para usar antes de push . Gracias por señalar eso.
Dr Beco
2
Un aviso es que las confirmaciones antes y después --amendtienen diferentes hashes
sonlexqt
5
Gracias, pero no puede ser: OP pidió HEAD^4. Está bien como está, solo como un apéndice como referencia. ;)
Dr Beco
11

Si NO ha enviado estas 4 confirmaciones, puede hacerlo de la siguiente manera:

Cree archivos de parche para todas estas confirmaciones:

git format-patch -4

Retroceda 4 confirmaciones:

git reset --hard HEAD~4

Agregar archivo faltante:

git add missing-file

Compromételo con --amend:

git commit --amend

Aplicar todos los parches guardados nuevamente:

git am *.patch

Si ha presionado, NO debe utilizar este método. En su lugar, solo admite tu error y crea una confirmación más además de HEAD que soluciona este problema.

mvp
fuente
Si desea hacer esto paso a paso, es más fácil seleccionar las confirmaciones después de la modificada que exportarlas como un parche.
Rafał Rawicki
1
Esto es cuestión de gustos. Me gusta git format-patch/ git ammucho mejor. Lo más importante es que te da más confianza si echas a perder algo: la confirmación guardada como parche en un archivo físico es tu mejor red de seguridad.
MVP
La verdadera confianza radica en que cuando se opera en un repositorio de git nunca se elimina nada. Las confirmaciones antiguas están disponibles hasta que ejecute git gc:)
Rafał Rawicki
Esto es trivial y obvio para ti y para mí. Pero, para el usuario que recién está comenzando y probablemente no entiende nada sobre git, este hecho no es obvio en absoluto.
MVP
2
Estas instrucciones parecían extensas, pero eran bastante simples y fáciles de seguir. Gracias. (Que acababa de añadir un último paso: rm *.patch)
Darren Cook,
9

Aunque la respuesta aceptada es correcta, carece de instrucciones detalladas sobre cómo realizar la edición de una confirmación durante un proceso de rebase.

  • Primero, inicie un proceso de rebase:

    git rebase --interactive HEAD~4
    
  • Se presentará una lista de confirmaciones, elegir una confirmación que desea modificar cambiando la palabra picka edity guardar el archivo.

  • Realice las modificaciones necesarias en su código (recuerde invocar git addnuevos archivos)

  • Una vez realizadas todas las modificaciones, emita git commit --amend: esto modificará una confirmación marcada comoedit

  • Invocar git rebase --continueque terminará el proceso (si hay más confirmaciones marcadas como edit, los pasos anteriores deben repetirse)

Notas importantes:

  • NO elimine las líneas marcadas como pickque no desea editar, déjelas como están. Eliminar estas líneas resultará en la eliminación de confirmaciones relacionadas

  • GIT te obliga a hacerlo stashantes de cambiar la base si tu directorio de trabajo no está limpio; Sin embargo, puede git stash pop / git stash applydurante el rebase, para enmendar estos cambios (es decir, los cambios guardados antes de iniciar el proceso de rebase) a una confirmación marcada comoedit

  • si algo salió mal y desea revertir los cambios realizados durante el proceso de rebase antes de que finalice (es decir, desea volver al punto antes de iniciar el rebase), use git rebase --abort- también lea: Cómo abortar una rebase interactiva si --abort doesn ' t trabajo?

  • Como se dice en la respuesta aceptada:

    Recuerde que no debe modificar las confirmaciones enviadas al repositorio remoto de esta manera. En ese caso, es mejor agregar una nueva confirmación con un archivo faltante.

    La respuesta por qué, está en el Libro de Git (párrafo titulado " Los peligros de volver a basar "):

    No reemplace las confirmaciones que existen fuera de su repositorio.

    Si sigue esa guía, estará bien. Si no lo hace, la gente lo odiará y sus amigos y familiares lo despreciarán.

    Cuando reabasteces cosas, estás abandonando las confirmaciones existentes y creando nuevas que son similares pero diferentes. Si empuja las confirmaciones en algún lugar y otros las bajan y basan el trabajo en ellas, y luego reescribe esas confirmaciones con git rebase y las sube de nuevo, sus colaboradores tendrán que volver a fusionar su trabajo y las cosas se complicarán cuando intente hacerlo. devolver su trabajo al suyo.

    [...]

dominik
fuente